Node.js
首发于Node.js
科普文:为什么不能在服务器上 npm install ?

科普文:为什么不能在服务器上 npm install ?

## 背景

Node.js 很简单,容易上手。但也因此缺乏不少规范,使用者水平参差不齐。

最近经常看到的一个问题是:很多新手,在部署的时候,是直接在服务器上 npm install ,这是非常不推荐的。


## 先抛结论

鉴于评论区的情况,把本文的主要观点提炼到前面:

  • 不能在线上多台服务器上去安装依赖。(不管你锁还是没锁版本)
  • 依赖必须是在 CI 或 打包机 上去安装并打包。
  • 打包方式可以是压缩包,也可以是 Docker 镜像(推荐)。

## 存在的问题

1. 无法确定唯一性

因为安装是有较大的网络耗时的,所以你甚至无法保证集群情况下,两台服务器上npm install 下来的包是一模一样的。

如果某个库刚好更新了,并且它有 BUG,然后你就是百思不得其解:一定概率出某个问题。排查起来简直想死。

当然,很多人为了解决这个问题,就选择「锁版本」这个方案。


评论区的同学,不要急,看完下面第 2 点,即使锁版本也是在 CI 上 install 而不是服务器上。


鉴于 「锁版本」属于 「屎色自行车问题」 ,这里不想讨论。
我们的观点参见:「知乎专栏 - 死马:为什么我不使用 shrinkwrap(lock)」


2. 上线耗时久,无法快速回滚

上线后,发现线上故障,要快速回滚止血的时候,就懵逼了:

  1. 要等待依赖安装,万一网络有个抖动啥的,妥妥的 P4 故障变为 P0 故障,年终奖没了。
  2. 万一问题是底层依赖导致的,回滚也没用。
  3. npm cache 解决不了问题,如机器扩容的时候。

## 推荐方案

知乎图片查看体验差,请点击大图,清晰点


其中,关键点是:在构建期就把依赖打包进去。


优点:

  • 解压即可立刻启动,无需等待网络耗时。
  • 能保证肯定是可以运行的,因为此时依赖都是确定好的,且经过 CI 单测保障的。
  • 可以快速回滚,止血。
  • 打包方式可以是 tar 或 docker。(推荐后者)

缺点:

  • 包体积大(但其实存储不值钱。。。)


知乎图片查看体验差,请点击大图,清晰点
上图是用 PlantUML 在语雀绘制的,想享受类 Markdown 的体验来画流程图,就用 PlantUML

## 如何实施?

那有同学就要问了:我是小公司,不像你们有这些基建可以服务,怎么办?

其实成本真的很低:

  • 代码仓库 GitLab 自带 CI 了,你只需要写个配置文件,触发自动构建即可。(或 Jenkins)
  • 然后把构建后的文件,找个地方存储,如 OSS 。
  • 服务器部署的话,有运维发布系统最好,没有的话,自己写个 shell 把 OSS 文件下载解压。
  • 当然,很多云服务都支持 Docker 镜像了,那就更简单了。

## 广告区

  • 更好的阅读体验请访问 语雀版
  • 如果喜欢我的文章,请关注 我的知乎Follow GitHub
  • 广州阿里游戏,招前端,熟悉动效,Node 的速来~

文章被以下专栏收录

    在 eggjs 团队的日常协作中,遵循「基于 GitLab 的硬盘式异步协作模式」。 先通过 issue 发起 RFC 召集讨论,再提交 Pull Request 和 Code Review,这样便于沉淀,即使是当时没有参与讨论的开发者,事后也能通过 issue 了解某个功能设计的前因后果。 因此,本专栏用于汇总近期值得关注的 Egg.js 和 Node.js 相关动态,将不定期发布。