自动部署装包速度提升
现在程序的开发都提倡能用技术放开双手,那就要技术解决,所以现在无论是构建、代码检查、部署或者测试,这些都有一定程度的自动化过程,减少人为操作失误,而这的主题是 npm 装包耗时过长的优化方案。
当我们本地使用 npm 装包时,因为在本地环境中安装依赖是有状态的,如 node_modules,~/.npmrc,~/.npm 一系列硬盘目录及文件,无不构成状态。而在生产环境中,往往结合 CICD 工具,每次分配的 Runner 不一定是一台服务器(容器),往往被视为无状态,因而无法有效利用缓存而导致 CI 中部署用时过长。
但也正因为 CICD Runner 的无状态化,这意味着你只要参考构建脚本,如 .gitlab-ci.yaml,.travis.yaml 或者 .github/workflows/deploy.yaml,就可以从零把项目跑起来,而避免过多在熟悉新项目时求助他人。
那么我们应该怎么让 npm 在 CICD 上跑的更快呢?
优化一:
使用 –production 可以只安装 package.json 中 dependencies 中的依赖项,只把要安装在 CI 中需要使用到的依赖。在生产环境部署时可以指定 –production。
1 | npm install --production |
但这样以后装包要严格遵守装包的规则,项目使用到的都要装到 dependencies 里,这是一个缺点,会出现人为的失误导致的 BUG。
优化二:
使用私有镜像仓库,既公司自己搭建 npm 仓库,然后包都从公司仓库拉取。
对于企业级项目的生产环境来说,在集群内部搭建私有仓库是一个更好的选择,也更能缩短时延。 流量能在局域网完成的,就不需要去互联网中溜圈了。
1 | 如: |
优化三:
正如 http cache 一样,npm install 也可以充分利用缓存,npm 的缓存在 linux 系统中存在于以下路径:
命令 npm cache verify 可以校验缓存,如下所示:
1 | npm cache verify |
结合 npm install --prefer-offline 缓存优先策略充分利用缓存
既
1 | npm cache verify |
优化四:
使用npm ci装包
它安装依赖时,默认是缓存优先的,它会充分利用缓存,从而加速装包。npm ci 可以减少将近一半的的依赖安装时间。
优化五:
每次对比上一次 MR 的 package.json 与这次 MR 的 package.json,筛选出不同的地方,如包的版本不一样,新增包等,然后只安装这部分的包
npm 进阶-node_modules
nodejs 中 package.json 中的依赖必须每个项目都有自己的 node_modules 文件夹,而无法在多个项目之间共用一套 node_modules(不像 Java 中的 Maven 那样共享一个全居仓库)。
没法共用一个 node_modules 会导致互相依赖的项目当使用是同一个包时,但由于包保存了数据需要获取出来使用而导致的报错,因为它们不是依赖同一个包,如 redux,react-router-dom 等。
依赖管理是每个现代语言的标配。在 Java 中,maven 同时兼具 依赖管理 和 打包 两大功能,而前段领域这两个功能是两种不同的工具分别提供:
- npm 负责依赖管理
- webpack 负责打包
1 | 依赖管理最难解决的问题就是版本问题。库A依赖库B,库C也依赖库B,但是库A跟库C所依赖的库B不是同一版本,如果库B的这两个版本兼容还好,如果不兼容就坑大发了,这是无解的问题。 |
Java 中的 Maven 仓库在开发者电脑上是全局的,所有项目的依赖都集中存放在本地仓库中。每个项目都有 pom.xml 指明依赖本地仓库中的哪些库,如果本地仓库没有会从局域网仓库或网络仓库下载至本地仓库。
Node 中的依赖如果你不写 package.json,那么依赖的就是全局的库;如果写了 package.json,就会把所有依赖下载到 node_modules 文件夹
Node 这种 node_modules 文件夹的方式有利有弊。
好处:
- 使用 package.json 安装好之后,node_modules 文件夹中没有版本信息,从而 package.json 可以删掉了。
- 移动/复制/打包项目比较简单,对于开发、部署都有好处
- 对于设计 npm 的人来说,这是最省事的包依赖方法。这就好比 maven 安装依赖之后自动将 jar 包安装到项目的 lib 里面。
- 随意改代码。安装在 node_modules 里面的东西,你可以随便改,无需担心对其它项目的影响。在 Java 中使用 maven 管理项目时,如果想要定制某个库,就需要更改这个库的源代码,这时就需要把这个库的源代码复制到项目中,跟 node_modules 是一个道理。npm 的设计者大概认为:前端都是经常修改库的源代码的。
坏处:
- 每次都需要安装依赖,费流量,网速慢时很费时间
- 浪费磁盘空间,每个 node_modules 中包含的工具很多,动辄 20M
但我觉得这些坏处都不是很大的问题,应该也就浪费一些流量和几十分钟的时间,而且也不是经常全量安装包,后续开发就会单独新增包,单独安装包是很快的,并且 npm 或 yarn 之类的工具都在不断的优化,装包只会越来越快,再不济也可以是使用国内镜像或公司搭建私仓下载,这也是对装包速度很大的提升。