天天看点

node应用线上部署时锁定包的依赖版本

我们使用node开发时,经常需要依赖一些模块来完成功能需求,而我们所依赖的模块也必然会依赖其他模块,就这样一级一级的依赖,而且这些依赖模块并不为我们所控制。一个产品或项目的开发周期,少则几个周,多则几个月几年。开发人员往往在一开始时下载了依赖包发现能够正常工作后,便一直在依赖包的当前版本上工作,然而在线上服务器布属时往往是根据依赖配置文件,重新下载依赖包。可这个时候依赖链中的包的开发者很可能已经将某个模块升级了,而且并不能保证这些新的依赖包没有bug。一旦依赖链上的某个包出现bug,可能对产品造成严重影响,而且这个时候往往无法找回开发时所用的正确依赖,以及依赖的依赖的版本。

我们来看一个经典的例子:

假设有包a依赖包b,包b依赖包c:

假设在开发时,我们运行<code>npm install a</code>得到以下的依赖链:

而在项目需要部署上线时,我们不可能把所有<code>node_modules</code>放到线上服务器中,所以将项目代码放到服务器时,我们便会运行<code>npm install a</code>,而恰恰这阶段,包b的版本更新到了<code>0.0.8</code>,所以我们在服务器上得到的依赖链就是:

如果b的新版本有问题,这时就会对产品造成难以预估的损失。

所以我们推荐当开发环境中,所有依赖模块都能正常工作时,便在部署到服务器之前将依赖包的版本锁住,这时候就运行这个命令:

我们会得到一个npm-shrinkwrap.json的文件,这个文件保存了所有当前使用的依赖模块的版本:

将这个文件连同项目源码一同部署到服务器上,然后运行<code>npm install</code>这时候,npm会首先检查有没有npm-shrinkwrap.json文件,有的话会根据该文件中依赖包的版本以及resolve字段下载依赖包,这样就能够保证线上环境与开发环境一致。

这个文件时根据我们当前项目中的<code>node_modules</code>中的模块的当前版本生成的。<code>version</code>代表当前模块版本,<code>from</code>表示的是package.json中对该依赖模块的版本描述,<code>resolve</code>代表当前模块的实际来源。

比如当你的package.json中对于某个依赖模块有如下描述:

当<code>acorn</code>模块安装后,它的package.json文件中会出现如下字段:

这时候运行<code>npm shrinkwrap</code>便会出现:

对于npm-shrinkwrap.json来说,这其中最重要的就是<code>resolve</code>字段。

如果要安装新的依赖模块,一定要使用<code>npm install --save 模块</code>,这样保证package.json与npm-shrinkwrap.json文件同步更新。

<code>node_modules</code>中的模块必须能够包含package.json中的依赖模块,如果node_modules中不存在package.json中指定的依赖模块,运行<code>npm shrinkwrap</code>会报错;如果node_modules中包含有package.json中未指定的模块,根据官方说法是也会报错,但根据我的实验(windows7系统)并没有报错,npm-shrinkwrap.json会包含所有在node_modules中的模块。

npm-shrinkwrap.json中并不会包含<code>devdependencies</code>字段中的模块。

<a href="https://docs.npmjs.com/cli/shrinkwrap">npm-shrinkwrap-lock down dependency versions</a>