前言
目前前端有npm、yarn、pnpm等一些包管理器工具,在新、老项目中穿插使用不同包管理器工具会让我们具有蛮大的心智负担,稍有不慎可能还会犯错。
首先我们需要来了解下包版本号里符号的作用
包版本号里符号的区别
在版本号中我们经常会看见版本号中有~、^等一些符号,现在我们来一个个讲解:
~
~会匹配最近的小版本依赖包
例如:"vue": "~2.5.17",如果你在没有 lock 文件下进行下载依赖,那么vue 将会被升级至2.5.22,因为2.5.22是 vue2.5 下最新的(最后)的一个版本。
^
^会匹配最新的大版本依赖包
例如:"vue": "^2.5.17",如果你在没有 lock 文件下进行下载依赖,那么vue 将会被升级至2.7.8,因为2.7.8是 vue2.x 下最新的一个版本。
*
*会安装最新版本的依赖包
例如:"vue": "^2.5.17",如果你在没有 lock 文件下进行下载依赖,那么vue 将会被升级至2.7.8,这里不是 vue3 最新的版本,猜测是 vue 官方指定了什么,不过*在平时包中不会进行使用。
直接写版本号
例如:"vue": "2.5.17",如果你在没有 lock 文件下进行下载依赖,那么vue 将会被升级至2.5.17,这样的写法其实不太好,因为后续包是有可能修复 bug 之类的。
痛点场景
举个栗子🌰:现在有一个使用npm的老项目,由于着急你并没有注意,这个时候使用了yarn或者pnpm去下载依赖,由于目录中vue 包依赖为:"vue": "~2.5.17",那么下载依赖包下的依赖包就是 2.7.x,很显然2.6.x是 vue 的一个重要节点,很多语法在这个版本节点中有增加或者简化。现在你在本地运行时,代码预期是没有任何问题的,当你在进行部署时,运行 Jenkins 时,Jenkins一般都会走npm,npm将会走package-lock.json,而不是走yarn.lock或者pnpm-lock.yaml。从这里你就会发现,你的代码很有可能是将2.7.x的代码运行在2.5.17附近版本,版本超前的语法在线上或者测试环境都会失效或者报错。
使用 ni 优雅地穿梭在不同包管理器中的项目
ni 是什么
ni 是一个帮你选择一个正确包版本管理器的工具。ni 的介绍页里提到:
npm i in a yarn project, again? F**k!
看到这句话我心中表示大大的肯定!!!
当然我们也是通过npm进行安装。
npm i -g @antfu/ni
ni 基本命令
你也可以通过ni链接查看其 github 官网地址
注意:这里 ni 命令并不代表同时执行三个包管理器的命令,而是选择一个。
ni - install
ni
# npm install
# yarn install
# pnpm install
# bun install
ni vite
# npm i vite
# yarn add vite
# pnpm add vite
# bun add vite
ni @types/node -D
# npm i @types/node -D
# yarn add @types/node -D
# pnpm add -D @types/node
# bun add -d @types/node
ni --frozen
# npm ci
# yarn install --frozen-lockfile (Yarn 1)
# yarn install --immutable (Yarn Berry)
# pnpm install --frozen-lockfile
# bun install --no-save
ni -g eslint
# npm i -g eslint
# yarn global add eslint (Yarn 1)
# pnpm add -g eslint
# bun add -g eslint
# this uses default agent, regardless your current working directory
nr - run
nr dev --port=3000
# npm run dev -- --port=3000
# yarn run dev --port=3000
# pnpm run dev -- --port=3000
# bun run dev --port=3000
nr
# interactively select the script to run
# supports https://www.npmjs.com/package/npm-scripts-info convention
nr -
# rerun the last command
nx - execute
nx vitest
# (not available for bun)
# npx vitest
# yarn dlx vitest
# pnpm dlx vitest
nu - upgrade
nu
# (not available for bun)
# npm upgrade
# yarn upgrade (Yarn 1)
# yarn up (Yarn Berry)
# pnpm update
nu -i
# (not available for npm & bun)
# yarn upgrade-interactive (Yarn 1)
# yarn up -i (Yarn Berry)
# pnpm update -i
nun - uninstall
nun webpack
# npm uninstall webpack
# yarn remove webpack
# pnpm remove webpack
# bun remove webpack
nun -g eslint
# npm uninstall -g eslint
# yarn global remove eslint
# pnpm remove -g eslint
# bun remove -g eslint
nci - clean install
nci
# npm ci
# yarn install --frozen-lockfile
# pnpm install --frozen-lockfile
# bun install --no-save
na - agent alias
na
# npm
# yarn
# pnpm
# bun
na run foo
# npm run foo
# yarn run foo
# pnpm run foo
# bun run foo
Change Directory
更改目录
ni -C packages/foo vite
nr -C playground dev
Config
默认配置
; ~/.nirc
; fallback when no lock found
defaultAgent=npm # default "prompt"
; for global installs
globalAgent=npm
# ~/.bashrc
# custom configuration file path
export NI_CONFIG_FILE="$HOME/.config/ni/nirc"
ni 的逻辑
说白了,ni其实就是通过目录下的 lock 文件(如果当前目录没有,会向上递归查找)去选择当前的包管理工具,当然你肯定会想到一些花活:
- 有多个 lock 文件:这里是有优先级(pnpm > yarn > npm)
- 什么 lock 文件都没有:询问你使用哪一个包管理工具(如果没有询问那就是你的上层有 lock 文件)
ni帮我选择好了包管理器但是我没装:会询问你是否安装对应的包管理工具
老项目中使用其他包管理器
有时候可能你也想在老项目中使用 yarn 或者 pnpm,这个也是这两个包一开始就支持的:
yarn import
pnpm import
这个命令将会通过目录下的package.lock.json生成对应包的 lock 文件,这样就可以防止直接安装依赖 lock 文件与package.lock.json版本相差过大。
结语
配置ni自动选择包管理器以及通过yarn import或者pnpm import命令,我们已经可以逃离包管理器不一致的问题。