谁动了我的package-lock
血淋淋的教训只为呈现更好的文章内容
# package-lock 介绍
nodejs 对 package-lock 的介绍:package-lock.json 文件 (opens new window)
最重要的一句就是:
该文件旨在跟踪被安装的每个软件包的确切版本,以便产品可以以相同的方式被 100% 复制(即使软件包的维护者更新了软件包)。
# 问题的出现
今天新开了一个项目,就把一个项目的脚手架复制到另外一个项目去。然后突然出现了各种各样的问题。
最离谱就是同样的代码,另外一个域名运行的好好的,就新项目各种问题。。。没报错,本地运行没警告~
其中遇到最明显的就是 <slot></slot>
变为 undefined
。
这意味着下面的运行达不到预期的效果:
<!-- 忽略一堆vue的写法。。。 --> <slot>content</slot> <!-- 正常输出如下 --> content <!-- 打包后 --> 为空,甚至 undefined
1
2
3
4
5
6
7
8
偏偏项目中封装的组件多是用的都是默认插槽,有些甚至加了 v-if
的判断,导致页面轻则不显示内容,重则整个页面 GG~
这一切都起源于:vue - 插槽文档 (opens new window) 2.6.0 之后对 slot 改了点东西。
# 问题复现的场景
- package-lock.json 是忽略的文件
- 使用 vue.js 并且在 vue.config.js 中使用外部引入 JS 的方式引入的 vue(并非从 node_modules)打包生成
- 本地调试 OK,CI 打包后 GG
- slot 多数为默认插槽,并且默认插槽内还有默认内容,甚至有的插槽使用了 v-if
- pageage.json 中的 vue 版本为
"vue":"^2.6.10"
。动态引入的 vue 版本也是2.6.10
调试一番才发现,本地运行的 vue 版本使用的是 2.6.14。而且 vue-template-compiler
的版本也是 2.6.14。然而上线前的打包后引入的 vue.js 版本是 2.6.10!
不过我觉得最终的问题并不在于 vue 的版本,而是打包的时候
vue-template-compiler
的版本(因为如果单单是 vue 的问题,以前的项目早就出问题了,所以只能是打包时解析 vue 模版的库的版本也 vue 版本对应不上了!)
所以最后是先注释掉了 vue.config.js
中的 externals
配置。把 vue 的 cdn 去掉,还是改用打包的方式引入 vue.js。暂时解决了问题
PS:externals 配置是什么?webpack - externals 配置 (opens new window)
# package.json 文件符号解释
回到本地调试的问题,明明 package.json 写的是 2.6.10 版本,为什么实际使用的是 2.6.14 ?
注意看:"vue":"^2.6.10"
。前面的 ^
,同样在 package-lock.json 文件 (opens new window) 中有介绍,下面在概括一下
这样的符号一共有 4 个
- ^ 表示只锁主版本号 :
"vue":"^2.6.10"
代表主版本号为 2。后面的会获取主版本号下最新的版本,截到现在,最新版本确实就是 2.4.16 - ~表示只锁主版本号和次版本号:还是以
"vue":"~2.6.10"
为例,主版本为 2,次版本为 6,最终还是会获取到 2.6.x 下最新的一个版本。 - 没有任何符号表示版本锁死:
"vue":"2.6.10"
就会指定是 2.6.10 。不会有变化 *
代表最新的版本。如果写的是"vue":"*"
。哪天 vue3.0 更新到官网的稳定版了,再去安装会直接升级到 3.0
总结:
^
锁主版本~
锁主+次版本空
锁定指定版本号*
最新的版本
# 如何快速找到 node_modules 中的包
了解完 package.json 各个符号的定义后,再来说说我是怎么找到问题的:推荐一个 vscode 插件 Search node_modules (opens new window)
安装后,CTRL+P。输入 >node
然后就可以很快的搜索到我们想找到的 npm 包
打开 vue 的 package.json。虽然 _form 写的是 2.6.10
。可是最底下实际安装的 version 是 14 的。
# package-lock 到底要不要删?
在这件事发生之前,我通常都会把 yarn.lock
或者 package-lock.json
先删,在 npm i
。甚至在项目的 .gitignore 把他们加入到了忽略文件中。
# package-lock.json
他会帮你一直锁定当前运行的版本号。
虽然 package.json 中有 4 种符号,好像如果使用了 ^
之类的符号就会显得整个程序一直处于版本自动升级的状态。对于企业级项目来说是极其不稳定的,那 package-lock 文件就能帮你锁定当前运行的环境。
假设当前 package.json 的 vue 版本写的还是 "vue":"^2.6.10"
。然后当前 vue 最新版本是 "vue":"^2.6.14"
。这时候新建项目,安装的就是 "vue":"^2.6.14"
依赖。同时 package-lock.json
会记录下 vue 当前的 2.6.14 版本。
哪怕过了一个月后,vue 更新到了 2.7.0。只要有 package-lock.json 的版本记录,在怎么 npm i
。安装的都是 2.6.14。有点类似于 package.json 中的 “空符号” 的意思。
只有完全锁定了版本,才能保证 “产品可以以相同的方式被 100% 复制(即使软件包的维护者更新了软件包)”
所以,你还敢乱删 package-lock.json 吗?
# 总结
package.json 的符号有 4 个
^
锁主版本~
锁主+次版本空
锁定指定版本号*
最新的版本
package-lock.json 视情况删除和忽略
- 如果你们是一个朝气蓬勃,乐于升级的团队/个人,直接把版本号改为
"*"
- 如果是项目要持续交付/对稳定运行有很高要求的,就千万别删了
- 还有就是如果用了 webpack - externals 配置 (opens new window) 的也不要删,因为他会随时让你和你的 CDN 版本对不上号~
从而引发一系列“我的电脑上看没问题啊”
的错觉
- 如果你们是一个朝气蓬勃,乐于升级的团队/个人,直接把版本号改为
推荐了一个小插件
- Search node_modules (opens new window) 平时想看看某个 npm 包的源码也方便许多
又是吃一堑长一智的一天