Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
atian25 opened this issue Jul 8, 2018 · 10 comments
Open

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

atian25 opened this issue Jul 8, 2018 · 10 comments
Labels

Comments

@atian25
Copy link
Owner

atian25 commented Jul 8, 2018

背景

很多公司的服务器环境没有做隔离,就是全局安装一个 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 库来简化这个步骤:
  • Node 8 后支持了类似的特性

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

但需要注意的是:

  • 必须在跟你线上服务器一样操作系统的 CI 上去打包,否则如果你是在本地 Windows 下打包的,线上却是 Linux,那对应的 Node Runtime 就不对了。
  • 记得写文档
    • 经常有同学会说,我 Node 是 8 的,但为啥不支持 async 。
    • 这时候让他执行 ./node_modules/.bin/node -p process.versions 就知道了。

Node 8 内建支持

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

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

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

写在最后

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

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

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

广告区

@tong3jie
Copy link

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

@atian25
Copy link
Owner Author

atian25 commented Oct 17, 2018

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

@betgar
Copy link

betgar commented May 7, 2019

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

@atian25
Copy link
Owner Author

atian25 commented May 7, 2019

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

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

@betgar
Copy link

betgar commented May 7, 2019

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

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

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

@atian25
Copy link
Owner Author

atian25 commented May 7, 2019

截图里面也有啊,npm install node

@betgar
Copy link

betgar commented May 7, 2019

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

@xuke007
Copy link

xuke007 commented Sep 2, 2020

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

@atian25
Copy link
Owner Author

atian25 commented Sep 2, 2020

啥,没看到

@xuke007
Copy link

xuke007 commented Sep 2, 2020

啥,没看到

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants