[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"content-work-with-npm-package-lock":3,"$f3vws3fo099bti":21},{"id":4,"type":5,"slug":6,"title":7,"date":8,"category":9,"tags":10,"body_markdown":13,"permalink":14,"excerpt_src":14,"media_type":14,"media_title":14,"media_author":14,"media_url":14,"rating":14,"layout":14,"pv":15,"admin_only":15,"created_at":16,"updated_at":16,"deleted_at":14,"status":17,"html":18,"excerpt":19,"cover":20},185,"article","work-with-npm-package-lock","如何与NPM package-lock.json愉快地玩耍","2018-07-26 19:40","web",[11,12],"npm","package-lock","\n## 背景\n\n对的，最近写文章都会交代一下背景。因为按标题的套路，这本应该是一篇教程类的文章，但这种文章其实挺无趣的。之所以想写这篇，是因为确实碰到了一些很麻烦的事情。闲言少叙，我们进入正题。\n\n最近我们前端代码打包正在接入Gitlab CI，使用Docker来作为Executor，也就是在Docker中进行前端代码打包，然后收集打包结果，以备发布时使用。打包时Docker镜像很自然地就选择了官方Node镜像，最新版本（Node 10）。\n\n一开始我们尝试性地接入了几个项目，有使用NPM scripts进行打包的，也有使用Gulp进行打包的，一切都很正常。但是昨天在接入一个新项目，使用Gulp打包的时候，却突然碰到了报错：\n\n```sh\n$ gulp gitlab-ci\ngulp[85]: ..\u002Fsrc\u002Fnode_contextify.cc:631:static void node::contextify::ContextifyScript::New(const v8::FunctionCallbackInfo\u003Cv8::Value>&): Assertion `args[1]->IsString()' failed.\nAborted\nERROR: Job failed: exit code 134\n```\n\n看了一眼这个错误信息，一下子就发现，这并不是来自JS层的错误，而是来自Node原生层，这就超出了我的理解范围了。\n\n\u003C!-- more -->\n\n## 模块版本兼容问题\n\n通过搜索，首先找到一篇中文的解决方案：[升级node10后gulp报错的解决办法](https:\u002F\u002Fliyang.pro\u002Fafter-upgrading-node10-gulp-error-solution\u002F)。文中给出了如下解决办法：\n\n```sh\nrm -fr node_modules\nrm -fr package-lock.json\nnpm cache clean --force\nnpm install\n```\n\n所以这是什么原理呢？没看到文章有解释，另外这文章本身也写得不是很清楚。抱着半信半疑的态度，在CI的脚本中加上了`npm cache clean --force`，结果问题依旧。\n\n接着搜索了一下，很快发现一些和这个问题有关的issue：\n\n- nodejs\u002Fnode: [node 10.0.0安装模块时core dump](https:\u002F\u002Fgithub.com\u002Fnodejs\u002Fnode\u002Fissues\u002F20281)\n- nodejs\u002Fnode: [新发布的版本与Gulp ^3.9.0不兼容](https:\u002F\u002Fgithub.com\u002Fnodejs\u002Fnode\u002Fissues\u002F20285)\n- gulpjs\u002Fgulp: [将graceful-fs的升级合并回Gulp 3](https:\u002F\u002Fgithub.com\u002Fgulpjs\u002Fgulp\u002Fissues\u002F2146)\n- gulpjs\u002Fgulp: [node 10中崩溃](https:\u002F\u002Fgithub.com\u002Fgulpjs\u002Fgulp\u002Fissues\u002F2162)\n- isaacs\u002Fnode-graceful-fs [v3.x分支与Node.js master不兼容](https:\u002F\u002Fgithub.com\u002Fisaacs\u002Fnode-graceful-fs\u002Fissues\u002F120)\n- isaacs\u002Fnode-graceful-fs [v3.0.11依赖natives 1.1.1，后者与node 10不兼容](https:\u002F\u002Fgithub.com\u002Fisaacs\u002Fnode-graceful-fs\u002Fissues\u002F130)\n\n通过`npm ls`，一下子就看到了`natives`模块的版本是1.1.1，于是定位到真正的问题：`gulp`依赖`vinyl-fs`，`vinyl-fs`依赖`graceful-fs`，`graceful-fs`依赖`natives`，而`natives`在1.1.3之前都不兼容Node 10。\n\n那么解决方案就简单了，想办法升级一下模块不就好了？\n\n## 如何升级间接依赖\n\n首先想到的是Gulp是否有解决这个问题，`npm info gulp`看了一下，发现最新版本是`3.9.1`，然后`npm ls`一下，发现本机装的已经是`3.9.1`了，也就是说，Gulp根本没有升级的可能。那要如何升级这个间接的依赖呢？\n\n这里我绕了个弯子，`package.json`中直接依赖的模块无法升级，`npm update`也不能搞定。于是想到，如果显式安装一下这个模块，是不是能解决问题？\n\n```sh\nnpm install natives@1.1.3\n```\n\n安装完之后还要在`package.json`中将直接依赖`natives`删除（因为我并不直接依赖它，留着没用）。然后再次查看依赖：\n\n```sh\n▶ npm ls natives\nseed@1.0.0 \u002FUsers\u002FTooBug\u002Fwork\u002Foa\u002Flearn\u002Ffrontend\n└─┬ gulp@3.9.1\n  └─┬ vinyl-fs@0.3.14\n    └─┬ graceful-fs@3.0.11\n      └── natives@1.1.3\n```\n\n这次对了。\n\n但是，这个操作我是在本机进行的，这个操作到底改了什么呢？如果去CI上再次执行`npm install`，会不会依然安装到旧版本呢？毕竟`package.json`并没有任何改动。\n\n于是翻看了一下`git diff`，发现了本文的主角`package-lock.json`被修改了，其中的`natives`由1.1.1变成了1.1.3。\n\n```json\n\"natives\": {\n    \"version\": \"1.1.3\",\n    \"resolved\": \"http:\u002F\u002Fregistry.npm.oa.com\u002Fnatives\u002Fdownload\u002Fnatives-1.1.3.tgz\",\n    \"integrity\": \"sha1-RKV5vmRQfqLW7RygSpQVkVz3VVg=\"\n},\n```\n\n于是怦然大悟：本来npm在安装模块是是按语义化版本安装最新版的，但是在CI上却没有安装`natives` 1.1.3版本，而是安装了`natives` 1.1.1版本，这正是因为`package-lock.json`装版本锁定了，从而导致了与Node 10的不兼容问题。\n\n这也能很好地解释，为什么其它项目没有这样的问题，因为其它的项目在代码仓库中没有包含`package-lock.json`，在安装时自然就安装了`natives` 1.1.3版本。\n\n于是再回头看一开始搜到的文章提出的解决办法：\n\n```sh\nrm -fr node_modules\nrm -fr package-lock.json\nnpm cache clean --force\nnpm install\n```\n\n其实是非常有效的，因为它将`package-lock.json`直接删除了，然后重新安装一遍最新版本，生成新的`package-lock.json`，从而解决问题。\n\n## 延伸：如何正确地在项目中使用`package-lock.json`\n\n最后，也补充说明一下`package-lock.json`的正确用法。（虽然我知道，但还是不小心踩坑了。如果不清楚它的用法的话，可能会在坑里待更长时间爬不出来。）\n\n首先，需要确保`npm`的版本在5.6以上，因为在5.0 - 5.6中间，对`package-lock.json`的处理逻辑更新过几个版本。5.6以上的才是符合认知的逻辑。\n\n然后，在项目中如果没有锁版本的必要，可以不使用`package-lock.json`，在安装模块时指定`--no-lock`即可。\n\n如果项目中有`package-lock.json`，则安装模块时会以这个文件中指定的版本和地址为准，直接下载安装。（除非它和`package.json`中指定的版本不相符。）\n\n最后，如果已经锁定了版本的情况下，需要更新直接依赖，则直接安装指定版本，`package.json`和`package-lock.json`都会同步更新。如果需要更新间接依赖的话，则需要像本文这样，手工安装一下，保证`package-lock.json`被更新到。或者如果其它模块的锁定并不是那么重要时，也可以直接删除`package-lock.json`，然后重新安装一遍，相当于把所有（直接依赖+间接依赖）模块全部更新一遍。\n",null,0,"2026-08-28 04:37:17","published","\u003Ch2>背景\u003C\u002Fh2>\n\u003Cp>对的，最近写文章都会交代一下背景。因为按标题的套路，这本应该是一篇教程类的文章，但这种文章其实挺无趣的。之所以想写这篇，是因为确实碰到了一些很麻烦的事情。闲言少叙，我们进入正题。\u003C\u002Fp>\n\u003Cp>最近我们前端代码打包正在接入Gitlab CI，使用Docker来作为Executor，也就是在Docker中进行前端代码打包，然后收集打包结果，以备发布时使用。打包时Docker镜像很自然地就选择了官方Node镜像，最新版本（Node 10）。\u003C\u002Fp>\n\u003Cp>一开始我们尝试性地接入了几个项目，有使用NPM scripts进行打包的，也有使用Gulp进行打包的，一切都很正常。但是昨天在接入一个新项目，使用Gulp打包的时候，却突然碰到了报错：\u003C\u002Fp>\n\u003Cpre>\u003Ccode>$ gulp gitlab-ci\ngulp[85]: ..\u002Fsrc\u002Fnode_contextify.cc:631:static void node::contextify::ContextifyScript::New(const v8::FunctionCallbackInfo&lt;v8::Value&gt;&amp;): Assertion `args[1]-&gt;IsString()' failed.\nAborted\nERROR: Job failed: exit code 134\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>看了一眼这个错误信息，一下子就发现，这并不是来自JS层的错误，而是来自Node原生层，这就超出了我的理解范围了。\u003C\u002Fp>\n\u003Ch2>模块版本兼容问题\u003C\u002Fh2>\n\u003Cp>通过搜索，首先找到一篇中文的解决方案：\u003Ca href=\"https:\u002F\u002Fliyang.pro\u002Fafter-upgrading-node10-gulp-error-solution\u002F\">升级node10后gulp报错的解决办法\u003C\u002Fa>。文中给出了如下解决办法：\u003C\u002Fp>\n\u003Cpre>\u003Ccode>rm -fr node_modules\nrm -fr package-lock.json\nnpm cache clean --force\nnpm install\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>所以这是什么原理呢？没看到文章有解释，另外这文章本身也写得不是很清楚。抱着半信半疑的态度，在CI的脚本中加上了\u003Ccode>npm cache clean --force\u003C\u002Fcode>，结果问题依旧。\u003C\u002Fp>\n\u003Cp>接着搜索了一下，很快发现一些和这个问题有关的issue：\u003C\u002Fp>\n\u003Cul>\n\u003Cli>nodejs\u002Fnode: \u003Ca href=\"https:\u002F\u002Fgithub.com\u002Fnodejs\u002Fnode\u002Fissues\u002F20281\">node 10.0.0安装模块时core dump\u003C\u002Fa>\u003C\u002Fli>\n\u003Cli>nodejs\u002Fnode: \u003Ca href=\"https:\u002F\u002Fgithub.com\u002Fnodejs\u002Fnode\u002Fissues\u002F20285\">新发布的版本与Gulp ^3.9.0不兼容\u003C\u002Fa>\u003C\u002Fli>\n\u003Cli>gulpjs\u002Fgulp: \u003Ca href=\"https:\u002F\u002Fgithub.com\u002Fgulpjs\u002Fgulp\u002Fissues\u002F2146\">将graceful-fs的升级合并回Gulp 3\u003C\u002Fa>\u003C\u002Fli>\n\u003Cli>gulpjs\u002Fgulp: \u003Ca href=\"https:\u002F\u002Fgithub.com\u002Fgulpjs\u002Fgulp\u002Fissues\u002F2162\">node 10中崩溃\u003C\u002Fa>\u003C\u002Fli>\n\u003Cli>isaacs\u002Fnode-graceful-fs \u003Ca href=\"https:\u002F\u002Fgithub.com\u002Fisaacs\u002Fnode-graceful-fs\u002Fissues\u002F120\">v3.x分支与Node.js master不兼容\u003C\u002Fa>\u003C\u002Fli>\n\u003Cli>isaacs\u002Fnode-graceful-fs \u003Ca href=\"https:\u002F\u002Fgithub.com\u002Fisaacs\u002Fnode-graceful-fs\u002Fissues\u002F130\">v3.0.11依赖natives 1.1.1，后者与node 10不兼容\u003C\u002Fa>\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>通过\u003Ccode>npm ls\u003C\u002Fcode>，一下子就看到了\u003Ccode>natives\u003C\u002Fcode>模块的版本是1.1.1，于是定位到真正的问题：\u003Ccode>gulp\u003C\u002Fcode>依赖\u003Ccode>vinyl-fs\u003C\u002Fcode>，\u003Ccode>vinyl-fs\u003C\u002Fcode>依赖\u003Ccode>graceful-fs\u003C\u002Fcode>，\u003Ccode>graceful-fs\u003C\u002Fcode>依赖\u003Ccode>natives\u003C\u002Fcode>，而\u003Ccode>natives\u003C\u002Fcode>在1.1.3之前都不兼容Node 10。\u003C\u002Fp>\n\u003Cp>那么解决方案就简单了，想办法升级一下模块不就好了？\u003C\u002Fp>\n\u003Ch2>如何升级间接依赖\u003C\u002Fh2>\n\u003Cp>首先想到的是Gulp是否有解决这个问题，\u003Ccode>npm info gulp\u003C\u002Fcode>看了一下，发现最新版本是\u003Ccode>3.9.1\u003C\u002Fcode>，然后\u003Ccode>npm ls\u003C\u002Fcode>一下，发现本机装的已经是\u003Ccode>3.9.1\u003C\u002Fcode>了，也就是说，Gulp根本没有升级的可能。那要如何升级这个间接的依赖呢？\u003C\u002Fp>\n\u003Cp>这里我绕了个弯子，\u003Ccode>package.json\u003C\u002Fcode>中直接依赖的模块无法升级，\u003Ccode>npm update\u003C\u002Fcode>也不能搞定。于是想到，如果显式安装一下这个模块，是不是能解决问题？\u003C\u002Fp>\n\u003Cpre>\u003Ccode>npm install natives@1.1.3\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>安装完之后还要在\u003Ccode>package.json\u003C\u002Fcode>中将直接依赖\u003Ccode>natives\u003C\u002Fcode>删除（因为我并不直接依赖它，留着没用）。然后再次查看依赖：\u003C\u002Fp>\n\u003Cpre>\u003Ccode>▶ npm ls natives\nseed@1.0.0 \u002FUsers\u002FTooBug\u002Fwork\u002Foa\u002Flearn\u002Ffrontend\n└─┬ gulp@3.9.1\n  └─┬ vinyl-fs@0.3.14\n    └─┬ graceful-fs@3.0.11\n      └── natives@1.1.3\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>这次对了。\u003C\u002Fp>\n\u003Cp>但是，这个操作我是在本机进行的，这个操作到底改了什么呢？如果去CI上再次执行\u003Ccode>npm install\u003C\u002Fcode>，会不会依然安装到旧版本呢？毕竟\u003Ccode>package.json\u003C\u002Fcode>并没有任何改动。\u003C\u002Fp>\n\u003Cp>于是翻看了一下\u003Ccode>git diff\u003C\u002Fcode>，发现了本文的主角\u003Ccode>package-lock.json\u003C\u002Fcode>被修改了，其中的\u003Ccode>natives\u003C\u002Fcode>由1.1.1变成了1.1.3。\u003C\u002Fp>\n\u003Cpre>\u003Ccode>&quot;natives&quot;: {\n    &quot;version&quot;: &quot;1.1.3&quot;,\n    &quot;resolved&quot;: &quot;http:\u002F\u002Fregistry.npm.oa.com\u002Fnatives\u002Fdownload\u002Fnatives-1.1.3.tgz&quot;,\n    &quot;integrity&quot;: &quot;sha1-RKV5vmRQfqLW7RygSpQVkVz3VVg=&quot;\n},\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>于是怦然大悟：本来npm在安装模块是是按语义化版本安装最新版的，但是在CI上却没有安装\u003Ccode>natives\u003C\u002Fcode> 1.1.3版本，而是安装了\u003Ccode>natives\u003C\u002Fcode> 1.1.1版本，这正是因为\u003Ccode>package-lock.json\u003C\u002Fcode>装版本锁定了，从而导致了与Node 10的不兼容问题。\u003C\u002Fp>\n\u003Cp>这也能很好地解释，为什么其它项目没有这样的问题，因为其它的项目在代码仓库中没有包含\u003Ccode>package-lock.json\u003C\u002Fcode>，在安装时自然就安装了\u003Ccode>natives\u003C\u002Fcode> 1.1.3版本。\u003C\u002Fp>\n\u003Cp>于是再回头看一开始搜到的文章提出的解决办法：\u003C\u002Fp>\n\u003Cpre>\u003Ccode>rm -fr node_modules\nrm -fr package-lock.json\nnpm cache clean --force\nnpm install\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>其实是非常有效的，因为它将\u003Ccode>package-lock.json\u003C\u002Fcode>直接删除了，然后重新安装一遍最新版本，生成新的\u003Ccode>package-lock.json\u003C\u002Fcode>，从而解决问题。\u003C\u002Fp>\n\u003Ch2>延伸：如何正确地在项目中使用\u003Ccode>package-lock.json\u003C\u002Fcode>\u003C\u002Fh2>\n\u003Cp>最后，也补充说明一下\u003Ccode>package-lock.json\u003C\u002Fcode>的正确用法。（虽然我知道，但还是不小心踩坑了。如果不清楚它的用法的话，可能会在坑里待更长时间爬不出来。）\u003C\u002Fp>\n\u003Cp>首先，需要确保\u003Ccode>npm\u003C\u002Fcode>的版本在5.6以上，因为在5.0 - 5.6中间，对\u003Ccode>package-lock.json\u003C\u002Fcode>的处理逻辑更新过几个版本。5.6以上的才是符合认知的逻辑。\u003C\u002Fp>\n\u003Cp>然后，在项目中如果没有锁版本的必要，可以不使用\u003Ccode>package-lock.json\u003C\u002Fcode>，在安装模块时指定\u003Ccode>--no-lock\u003C\u002Fcode>即可。\u003C\u002Fp>\n\u003Cp>如果项目中有\u003Ccode>package-lock.json\u003C\u002Fcode>，则安装模块时会以这个文件中指定的版本和地址为准，直接下载安装。（除非它和\u003Ccode>package.json\u003C\u002Fcode>中指定的版本不相符。）\u003C\u002Fp>\n\u003Cp>最后，如果已经锁定了版本的情况下，需要更新直接依赖，则直接安装指定版本，\u003Ccode>package.json\u003C\u002Fcode>和\u003Ccode>package-lock.json\u003C\u002Fcode>都会同步更新。如果需要更新间接依赖的话，则需要像本文这样，手工安装一下，保证\u003Ccode>package-lock.json\u003C\u002Fcode>被更新到。或者如果其它模块的锁定并不是那么重要时，也可以直接删除\u003Ccode>package-lock.json\u003C\u002Fcode>，然后重新安装一遍，相当于把所有（直接依赖+间接依赖）模块全部更新一遍。\u003C\u002Fp>\n","\u003Ch2>背景\u003C\u002Fh2>\n\u003Cp>对的，最近写文章都会交代一下背景。因为按标题的套路，这本应该是一篇教程类的文章，但这种文章其实挺无趣的。之所以想写这篇，是因为确实碰到了一些很麻烦的事情。闲言少叙，我们进入正题。\u003C\u002Fp>\n\u003Cp>最近我们前端代码打包正在接入Gitlab CI，使用Docker来作为Executor，也就是在Docker中进行前端代码打包，然后收集打包结果，以备发布时使用。打包时Docker镜像很自然地就选择了官方Node镜像，最新版本（Node 10）。\u003C\u002Fp>\n\u003Cp>一开始我们尝试性地接入了几个项目，有使用NPM scripts进行打包的，也有使用Gulp进行打包的，一切都很正常。但是昨天在接入一个新项目，使用Gulp打包的时候，却突然碰到了报错：\u003C\u002Fp>\n\u003Cpre>\u003Ccode>$ gulp gitlab-ci\ngulp[85]: ..\u002Fsrc\u002Fnode_contextify.cc:631:static void node::contextify::ContextifyScript::New(const v8::FunctionCallbackInfo&lt;v8::Value&gt;&amp;): Assertion `args[1]-&gt;IsString()' failed.\nAborted\nERROR: Job failed: exit code 134\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>看了一眼这个错误信息，一下子就发现，这并不是来自JS层的错误，而是来自Node原生层，这就超出了我的理解范围了。\u003C\u002Fp>\n","",{"total":15,"totalRoots":15,"comments":22,"pv":15},[]]