一个上班摸鱼的契机,看到了pnpm这个新名词,带着我的一丝好奇和一丝疑问,就想着了解一下。
什么是pnpm?
pnpm是我们正常印象中的软件包管理器,类似的我们肯定用过淘宝的cnpm,无非是如何又全又快又小巧地获取需要拉取的软件包。
它给自己的slogan是【速度快】、【节省磁盘空间】这两个前缀,具体我们再往下了解下。
pnpm和yarn/cnpm/npm有什么区别?
谈到差别,最主要的还是它标语提到的两点,一个是时间,一个是空间。
它也是在官网上有一个TAB,就是写的【性能对比】,具体来看看它提供的是怎样的成绩。
取了一次更新于【Jan 1, 2023, 3:20 AM】的分析说明
测试的点有:
- clean install: 在没有任何lockfile、packages、node_modules时
- with cache, with lockfile, with node_modules: 在首次install之后,再次install后
- with cache, with lockfile: 当开发人员获取存储库并首次运行安装时
- with cache: 与上面的相同,但包管理器没有可以使用的lockfile
- with lockfile: 当安装在 CI 服务器上运行时
- with cache, with node_modules: 删除lockfile并再次运行安装命令
- with node_modules, with lockfile: 删除包缓存并再次运行安装命令
- with node_modules: 删除包缓存和lockfile,并再次运行安装命令
- update: 通过更改 package.json 中的版本并再次运行安装命令来更新依赖项
使用一个固定的package.json进行测试
{
"name": "alotta-modules",
"version": "0.0.1",
"dependencies": {
"animate.less": "^2.2.0",
"autoprefixer": "^10.4.8",
"babel-core": "^6.26.3",
"babel-eslint": "^10.1.0",
"babel-loader": "^8.2.5",
"babel-plugin-lodash": "^3.3.4",
"babel-plugin-module-resolver": "^4.1.0",
"babel-plugin-transform-decorators-legacy": "^1.3.5",
"babel-plugin-transform-runtime": "^6.23.0",
"babel-polyfill": "^6.26.0",
"babel-preset-es2015": "^6.24.1",
"babel-preset-react": "^6.24.1",
"babel-preset-react-hmre": "^1.1.1",
"babel-preset-stage-1": "^6.24.1",
"babel-runtime": "^6.26.0",
"clean-webpack-plugin": "^4.0.0",
"core-decorators": "^0.20.0",
"css-loader": "^6.7.1",
"css-mqpacker": "^7.0.0",
"cssnano": "^5.1.13",
"custom-event-polyfill": "^1.0.7",
"draft-js": "^0.11.7",
"ejs": "^3.1.8",
"eslint": "^8.23.0",
"eslint-config-airbnb": "^19.0.4",
"eslint-import-resolver-webpack": "^0.13.2",
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-jsx-a11y": "^6.6.1",
"eslint-plugin-react": "^7.31.6",
"express": "^4.18.1",
"express-http-proxy": "^1.6.3",
"font-awesome": "^4.7.0",
"fready": "^1.0.0",
"glob": "^8.0.3",
"gulp": "^4.0.2",
"gulp-concat": "^2.6.1",
"gulp-csslint": "^1.0.1",
"gulp-cssnano": "^2.1.3",
"gulp-eol": "^0.2.0",
"gulp-less": "^5.0.0",
"gulp-livereload": "^4.0.2",
"gulp-minify-css": "^1.2.4",
"gulp-postcss": "^9.0.1",
"gulp-rename": "^2.0.0",
"gulp-util": "^3.0.8",
"happypack": "^5.0.1",
"highcharts": "^10.2.1",
"highcharts-solid-gauge": "^0.1.7",
"history": "^5.3.0",
"howler": "^2.2.3",
"imports-loader": "^4.0.1",
"jquery": "^3.6.1",
"jquery-ui": "1.13.2",
"js-cookie": "^3.0.1",
"json-loader": "^0.5.7",
"leftpad": "^0.0.1",
"less": "^4.1.3",
"lesshat": "^4.1.0",
"lodash": "^4.17.21",
"medium-draft": "^0.5.18",
"mobx": "^6.6.1",
"mobx-react": "^7.5.2",
"moment": "^2.29.4",
"moment-range": "^4.0.2",
"moment-timezone": "^0.5.37",
"password-policy": "0.0.3",
"postcss-reporter": "^7.0.5",
"progress": "^2.0.3",
"qs": "^6.11.0",
"raw-loader": "^4.0.2",
"rc-slider": "^10.0.1",
"react": "^18.2.0",
"react-addons-css-transition-group": "^15.6.2",
"react-addons-shallow-compare": "^15.6.3",
"react-dnd": "^16.0.1",
"react-dnd-html5-backend": "^16.0.1",
"react-dom": "^18.2.0",
"react-draft-wysiwyg": "^1.15.0",
"react-dropzone": "^14.2.2",
"react-grid-layout": "^1.3.4",
"react-highcharts": "^16.1.0",
"react-hot-loader": "4.13.0",
"react-input-calendar": "^0.5.4",
"react-lazyload": "^3.2.0",
"react-measure": "^2.5.2",
"react-mixin": "^5.0.0",
"react-responsive": "9.0.0-beta.10",
"react-responsive-tabs": "^4.4.3",
"react-router": "^6.3.0",
"react-router-dom": "^6.3.0",
"react-select-plus": "1.0.0-rc.3.patch12",
"react-skylight": "^0.5.1",
"react-sortablejs": "^6.1.4",
"react-tappable": "^1.0.4",
"react-tooltip": "4.2.21",
"react-virtualized": "^9.22.3",
"react-waypoint": "^10.3.0",
"sortablejs": "^1.15.0",
"style-loader": "^3.3.1",
"stylelint": "^14.11.0",
"superagent": "^8.0.0",
"uglify-js": "^3.17.0",
"uuid": "^8.3.2",
"verge": "^1.10.2",
"webpack-bundle-analyzer": "^4.6.1",
"webpack-hot-middleware": "^2.25.2",
"webpack-notifier": "^1.15.0",
"webpack-split-by-path": "^2.0.0",
"whatwg-fetch": "^3.6.2"
},
"devDependencies": {
"nan-as": "^1.6.1"
}
}
将npm/pnpm/Yarn/Yarn Pnp四个管理器进行比对。
- npm是一个有效的软件包管理器,但是出于国内资源的不稳定性,还是会给使用者一些困扰,比如安装的不确定性(可以通过开启skrinkwrap实现预测,并不默认),安装程序有风险
- yarn是一个在npm的基础上,默认创建yarn.lock文件,包含安装内容的校验和,来确保库的版本相同。不仅提升了安全性,运行速度也是有显著提升
- 虽然yarn已经很优秀了,但是pnpm在性能上给出了更好的成绩,也利用硬链接和符号链接来避免复制所有本地缓存源文件(yarn最大的性能弱点)
pnpm有什么特点和优势?
主要就是节省磁盘空间并且提升安装速度,这是它存在的动机,具体来说:
- 去除多依赖包副本的逻辑,统一存放依赖包,不同版本分别存储
- 安装软件包时,使用需要的文件都硬链接至此位置,不占用额外磁盘空间,不同项目可以共享相同版本的依赖包
- 扁平化的node_modules目录结构,也极大地解决Windows系统下可能的依赖包存储问题
如何安装和使用pnpm?
pnpm的安装方法有很多,官方也有明确指导,可以看这里
1.通过脚本安装:windows\posix系统\Linux
2.通过Corepack安装
3.通过npm安装
4.通过homebrew安装
5.通过scoop安装
那我本地是已经具备npm的条件,我尝试使用npm来安装pnpm,非常快速地就安装上了
a@b:~$ sudo npm install -g pnpm
Password:
/usr/local/bin/pnpx -> /usr/local/lib/node_modules/pnpm/bin/pnpx.cjs
/usr/local/bin/pnpm -> /usr/local/lib/node_modules/pnpm/bin/pnpm.cjs
+ pnpm@7.22.0
added 1 package in 1.736s
a@b:~$ which pnpm
/usr/local/bin/pnpm
也有pnpm与npm对比的指令
npm 命令 | pnpm 等价命令 |
---|---|
npm install | pnpm install |
npm i | pnpm add |
npm run | pnpm |
直接看一下pnpm安装成功了没?
a@b:~$ pnpm -v
ERROR: This version of pnpm requires at least Node.js v14.6
The current version of Node.js is v8.16.0
Visit https://r.pnpm.io/comp to see the list of past pnpm versions with respective Node.js version support.
根据错误提示,说必须要Node.js v14.6及以上,那么我目前是 v8.16.0,我这边使用n指令(是node版本管理器)来切换一下node的版本,最终pnpm是可以使用了
a@b:~$ node -v
v14.15.0
a@b:~$ pnpm -v
7.22.0
此外升级和卸载指令:
- pnpm add -g pnpm
- pnpm rm -g pnpm