atian25 / blog

天猪部落阁 http://atian25.github.io
1.59k stars 107 forks source link

科普文:服务器上如何 Node 多版本共存 #31

Open atian25 opened 6 years ago

atian25 commented 6 years ago

背景

很多公司的服务器环境没有做隔离,就是全局安装一个 Node.js Runtime,一般很少升级。

nvs / nvm 等可以用来切换版本,但无法同时共存。而且一般服务器不允许你随意升级。

因此很多同学都会很痛苦:「都 8012 年了,还是 Node 4.x 甚至 0.x 简直想死!」

时至今天,最好的办法就是 Docker。但奈何很多小公司还处于水深火热之中。

本文将介绍下我们很早前就使用的一套方案,可以完美解决非 Docker 情况下 Node 多版本共存问题。

npm scripts

首先要介绍下 npm scripts ,简单的说,就是可以在 package.json 里面定义脚本。

{
  "name": "egg-showcase",
  "scripts": {
    "start": "node index.js",
    "debug": "egg-bin debug --inspect-brk"
  },
  "devDependencies": {
    "egg-bin": "^4.7.0",
  }
}

如上,定义脚本后即可执行:

$ npm start
$ # 执行并传参,需要多一个 --
$ npm run debug -- --inspect-brk

同学们可能会比较好奇,上面的 egg-bin 是哪来的?这是 npm 的一个很重要的特性:

通过 npm run your-scripts 启动的脚本,会默认把 node_modules/.bin 加到 PATH 环境变量中。

由于,我们的依赖 egg-bin 有定义了 bin 字段 ,因此安装后会软链到 node_modules/.bin ,从而能被寻址并执行。

聪明的同学很快就会想到,如果 Node 的 Runtime 也在这个目录下,会怎么样呢?

Node Runtime

因此,问题就可以转换为:如何把 Node Runtime 打包到项目中?

答案就是在构建期打包进去,参见我们的上一篇文章 『科普文:为什么不能在服务器上 npm install ?』

🙋🙋🙋 老师!打包能否更简单一点呢?能否就像 dependencies 那样定义一下就好了呢?

没问题!方案有几种:

nodeinstall

定义:

{
  "name": "egg-showcase",
  "scripts": {
    "start": "node index.js",
    "debug": "egg-bin debug --inspect-brk",
    "echo": "node -p process.versions"
  },
  "devDependencies": {
    "egg-bin": "^4.7.0",
  },
  "engines": {
    "install-node": "^8.0.0",
    // AliNode 的话用这个
    "install-alinode": "^3.8.0"
  }
}

安装:

$ npm install nodeinstall -g

$ cd path/to/your/project
$ nodeinstall

$ # 验证
$ npm run echo

node: '8.10.0'

就这么简单,从此服务器上只要有一个任意版本的 npm 即可,各项目都可以用自己的 Node 版本,不会互相影响。

如果你是阿里员工,这一步都可以省了,因为 tnpm 内置就支持这个配置,无需单独安装 nodeinstall

但需要注意的是:

Node 8 内建支持

另外,除了我们写的这个工具外,在 Node 8 里面,官方终于也支持了类似的功能。

不过它是在 postinstall 里面安装的,没有优先安装 Node ,会导致 Native Addons 依赖有问题(应该先安装 Node,再用这个版本去安装其他依赖)。现在不知道改了没。

挺期待官方完善这个特性的,这样我们的又一个轮子可以完成历史使命,退休了。

写在最后

那如果我有服务器权限,我可以随意升级 Node 版本,就不需要了吧? 我们 Node 工程化的理念是一个包可以快速部署,这样就不依赖 PE 来配置环境了。

如果应用多了,服务器就得根据应用名配置 Node 版本,这样应用升级就得分开两步操作。

当然,最优的解决方案,还是 Docker 化隔离,都是一样的思路,一份产物部署的理念。

广告区

tong3jie commented 6 years ago

@atian25 egg在服务器的代码如何混淆和加密呢?

atian25 commented 6 years ago

我们没有需要混淆加密的场景,你可以搜下 GitHub 上的一些实现,Egg 跟其他 Node 的混淆没任何区别。

betgar commented 5 years ago

@atian25 大佬,大佬,怎么把node runtime作为dependencies打包到项目里面,现在node或者npm支持相关的功能吗?如果有有没有计划给大家科普下?

atian25 commented 5 years ago

@atian25 大佬,大佬,怎么把node runtime作为dependencies打包到项目里面,现在node或者npm支持相关的功能吗?如果有有没有计划给大家科普下?

上面的正文不是写了怎么打了么?

betgar commented 5 years ago

@atian25 大佬,大佬,怎么把node runtime作为dependencies打包到项目里面,现在node或者npm支持相关的功能吗?如果有有没有计划给大家科普下?

上面的正文不是写了怎么打了么?

额,看到了,我意思,你介绍的官方的node内置的方式怎么用?额,可能过分了,给个参考文档地址也行。

atian25 commented 5 years ago

截图里面也有啊,npm install node

betgar commented 5 years ago

@atian25 原谅我的无知,一直没有理解,其实和自带jre一个意思,sorry,浪费你宝贵的时间😔

xuke007 commented 4 years ago

@atian25 老哥能否看下邮箱 有些问题想问下 你的qq邮箱

atian25 commented 4 years ago

啥,没看到

xuke007 commented 4 years ago

啥,没看到

我又发了一遍 我看的是你github上面的qq邮箱