环境(2022-8-16):
`node -v` > v16.15.1 `npm -v` > 8.11.0 `yarn -v` > 1.22.19 `pnpm -v` > 7.9.0
npm0:
mkdir npm0
cd npm0
npm install element-plus --save
此时的目录结构:
+-- node_modules
| +-- ...
| +-- dayjs@1.10.4
| +-- element-plus
| +-- vue
| +-- ...
+-- package.json
解析: 这是因为在npm3之后采用了扁平结构,vue是element-plus的依赖,会提升到顶层,形成这样的目录结构,node_modules下其他的依赖也是如此。
此时在目录下再添加index.html文件,代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">{{ message }}</div>
</body>
<script src="bundle.js"></script>
</html>
添加index.js文件 ,代码如下:
const vue = require('vue')
const { createApp } = vue
createApp({
data () {
return {
message: 'Hello Vue!'
}
}
}).mount('#app')
添加 browserify依赖
npm install browserify -D
在package.json中添加打包脚本
"build": "browserify index.js > bundle.js"
运行打包脚本:
npm run build
然后打开html.index,可正常显示。
为什么项目依赖中里没有添加vue,但是却可以却是可以使用呢?这是因为node_modules的扁平结构,element-plus依赖了vue,所以可以项目中使用,这也就是所谓的幽灵依赖。
npm1:
mkdir npm1
cd npm1
npm install dayjs@1.11.2 --save
此时的目录结构:
+-- node_modules
| +-- dayjs@1.11.2
+-- package.json
此时的package.json :
{
"dependencies": {
"dayjs": "^1.11.2"
}
}
然后安装element-plus
npm install element-plus --save
安装完成后,新的目录结构
+-- node_modules
| +-- ...
| +-- dayjs@1.11.5
| +-- element-plus@2.2.13
| +-- ...
+-- package.json
解析: 可以在element-plus的package.json中看到,element-plus也依赖了dayjs
"dayjs": "^1.11.3"
element-plus声明依赖dayjs的最低版本为1.11.3,项目中声明dayjs的最低版本为1.11.2,所以提升到当前的最新版本1.11.5
npm2:
mkdir npm2
cd npm2
npm install element-plus --save
此时的目录结构
+-- node_modules
| +-- ...
| +-- element-plus
| +-- dayjs@1.11.5
| +-- ...
+-- package.json
此时的package.json :
{
"dependencies": {
"element-plus": "^2.2.13"
}
}
然后安装dayjs
npm install dayjs@1.11.2 --save
安装完成后新的目录结构:
+-- node_modules
| +-- ...
| +-- dayjs@1.11.2
| +-- element-plus
| | +-- node_modules
| | | +-- dayjs@1.11.5
| +-- ...
+-- package.json
新的package.json:
{
"dependencies": {
"dayjs": "^1.11.2",
"element-plus": "^2.2.13"
}
}
解析:就算当前项目中已通过间接依赖存在了dayjs,若再安装指定版本,还是会优先安装指定的版本。
若指定版本不满足其他包的版本要求,则会在对应包下再安装一份满足条件的版本;
若指定版本满足其他包的版本要求,则会统一使用新的依赖版本(下面是一个具体举例说明);
// 若当时dayjs时指定版本为1.11.4
// npm install dayjs@1.11.4 --save
// 则生成的目录结构如下:
+-- node_modules
| +-- ...
| +-- dayjs@1.11.4
| +-- element-plus
| +-- ...
+-- package.json
npm3:
mkdir npm2
cd npm2
npm install element-plus --save
npm install ant-design-vue --save
此时的目录结构:
+-- node_modules
| +-- ...
| +-- ant-design-vue
| +-- element-plus
| +-- dayjs@1.11.5
| +-- ...
+-- package.json
然后安装dayjs
+-- node_modules
| +-- ...
| +-- dayjs@1.10.4
| +-- ant-design-vue
| | +-- node_modules
| | | +-- dayjs@1.11.5
| +-- element-plus
| | +-- node_modules
| | | +-- dayjs@1.11.5
| +-- ...
+-- package.json
可以看到 ant-design-vue和element-plus没有共享dayjs这个依赖
npm4:
模拟从代码仓库clone代码:拷贝npm3下的package.json过来, 然后安装依赖
npm install
此时npm4的目录结构:
+-- node_modules
| +-- ...
| +-- dayjs@1.11.5
| +-- ant-design-vue
| +-- element-plus
| +-- ...
+-- package.json
但是npm3的目录结构却不一样:
+-- node_modules
| +-- ...
| +-- dayjs@1.10.4
| +-- ant-design-vue
| | +-- node_modules
| | | +-- dayjs@1.11.5
| +-- element-plus
| | +-- node_modules
| | | +-- dayjs@1.11.5
| +-- ...
+-- package.json
同样的代码,同样的脚本,但是生成的依赖不同,这是因为没有锁定版本。
npm5:
和npm4做相同的事情,但是拷贝时,需要把package-lock.json一起拷贝过来
npm install
此时npm5的目录结构:
+-- node_modules
| +-- ...
| +-- dayjs@1.10.4
| +-- ant-design-vue
| | +-- node_modules
| | | +-- dayjs@1.11.5
| +-- element-plus
| | +-- node_modules
| | | +-- dayjs@1.11.5
| +-- ...
+-- package.json
可以看到和npm3的结构是完全一样的:
+-- node_modules
| +-- ...
| +-- dayjs@1.10.4
| +-- ant-design-vue
| | +-- node_modules
| | | +-- dayjs@1.11.5
| +-- element-plus
| | +-- node_modules
| | | +-- dayjs@1.11.5
| +-- ...
+-- package.json
上传package-lock.json这类lockFile是很有必要的,比如前段时间发布的vue2的最后一个版本vue2.7(代号Naruto)支持了Composition Api 这就是同一个大版本中的重大更新,lockFile可以有效避免团队间因本地代码依赖不同产生的问题。
npm6:
mkdir npm6
cd npm6
npm install element-plus --save
npm install ant-design-vue --save
npm install dayjs@1.10.4 --save
+-- node_modules
| +-- ...
| +-- dayjs@1.10.4
| +-- ant-design-vue
| | +-- node_modules
| | | +-- dayjs@1.11.5
| +-- element-plus
| | +-- node_modules
| | | +-- dayjs@1.11.5
| +-- ...
+-- package.json
然后执行命令
npm dedupe
可以看到输出:
removed 2 packages, changed 1 package, and audited 64 packages in 2s
然后依赖的目录结构也发生了变化:
+-- node_modules
| +-- ...
| +-- ant-design-vue
| +-- element-plus
| +-- dayjs@1.11.5
| +-- ...
+-- package.json
下面是官方对这个命令的解释
Searches the local package tree and attempts to simplify the overall structure by moving dependencies further up the tree, where they can be more effectively shared by multiple dependent packages
npm7:
此时先断网,然后拷贝npm3下的package.json过来安装依赖
npm install
输出:
added 63 packages in 45s
npm采用了离线缓存,下面这个命令可以看到缓存列表
npm cache ls
pnpm3:
拷贝npm3下的package.json过来, 然后安装依赖
pnpm install
会看到报错:
Unmet peer dependencies Peer dependencies that should be installed: vue@">=3.2.0 <4.0.0"
此时需要添加vue依赖:
pnpm add vue --save
然后再install后成功,安装成功后的目录结构:
+-- node_modules
| +-- .pnpm
| | +-- ...
| | +-- ant-design-vue@3.2.11
| | | +-- node_modules
| | | | +-- ...
| | | | +-- dayjs@1.11.5
| | | | +-- ...
| | +-- dayjs@1.11.5
| | +-- element-plus@2.2.13
| | | +-- node_modules
| | | | +-- ...
| | | | +-- dayjs@1.11.5
| | | | +-- ...
| +-- ant-design-vue
| +-- dayjs
| +-- element-plus
| +-- vue
+-- package.json
+-- pnpm-lock.yaml
在文件资源管理器里可以看到ant-design-vue, dayjs 这些重复依赖都是以符号链接的形式存在,而且依赖结构也没有扁平化。
npm yarn pnpm 发展历程