## 背景
很多公司的服务器环境没有做隔离, 就是全局安装一个 Node.js Runtime, 一般很少升级.
nvs / nvm 等可以用来切换版本, 但无法同时共存. 而且一般服务器不允许你随意升级.
因此很多同学都会很痛苦:都 8012 年了, 还是 Node 4.x 甚至 0.x 简直想死!
最好的办法就是 Docker, 但奈何很多小公司的前端没有话语权, 处于水深火热之中.
本文将介绍我们很早前就使用的方案, 可以解决非 Docker 情况下 Node 多版本共存问题.
## npm scripts
首先要介绍下 npm scripts https://docs.npmjs.com/misc/scripts , 简单的说, 就是可以在 package.json 里面定义脚本.
- {
- "name": "egg-showcase",
- "scripts": {
- "start": "node index.js",
- "debug": "egg-bin debug"
- },
- "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 字段 https://github.com/eggjs/egg-bin/blob/master/package.json#L7 , 因此安装后会软链到 node_modules/.bin , 从而能被寻址并执行.
聪明的同学很快就会想到, 如果 Node 的 Runtime 也在这个目录下, 会怎么样呢?
## Node Runtime
因此, 问题就可以转换为: 如何把 Node Runtime 打包到项目中?
答案就是在构建期打包进去, 参见我们的上一篇文章.
科普文: 为什么不能在服务器上 npm install ? https://zhuanlan.zhihu.com/p/39209596
老师! 打包能否更简单一点呢? 能否就像 dependencies 那样定义一下就好了呢?
没问题! 方案有几种:
我们很早前写了一个 https://github.com/cnpm/nodeinstall 库来简化这个步骤
Node 8 后支持了类似的特性
### nodeinstall
cnpm/nodeinstall - Another node installer that bundle node with application. https://github.com/cnpm/nodeinstall
配置:
- {
- "name": "egg-showcase",
- "scripts": {
- "start": "node index.js",
- "debug": "egg-bin debug",
- "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 就不对了.
记得写文档, 否则有些同学全局装了 8.x, 但项目是依赖 6.x 的, 就会奇怪为何不支持 async
### Node 8 内建支持
另外, 除了我们写的这个工具外, 在 Node 8 里面, 官方终于也支持了类似的功能.
不过它是在 postinstall 里面安装的, 没有优先安装 Node , 会导致 Native Addons 依赖有问题 (应该先安装 Node, 再用这个版本去安装其他依赖). 现在不知道改了没.
挺期待官方完善这个特性的, 这样我们的又一个轮子可以完成历史使命, 退休了.
## 写在最后
那如果我有服务器权限, 我可以随意升级 Node 版本, 就不需要了吧?
我们 Node 工程化的理念是一个包可以快速部署, 这样就不依赖 PE 来配置环境了.
如果应用多了, 服务器就得根据应用名配置 Node 版本, 这样应用升级就得分开两步操作.
当然, 最优的解决方案, 还是 Docker 化隔离, 都是一样的思路, 一份产物部署的理念.
来源: https://juejin.im/entry/5b43d3be5188251b3950c4c7