ni 优雅使用包管理器

1,431 阅读4分钟

前言

目前前端有npmyarnpnpm等一些包管理器工具,在新、老项目中穿插使用不同包管理器工具会让我们具有蛮大的心智负担,稍有不慎可能还会犯错。

首先我们需要来了解下包版本号里符号的作用

包版本号里符号的区别

在版本号中我们经常会看见版本号中有~^等一些符号,现在我们来一个个讲解:

~

~会匹配最近的小版本依赖包

例如:"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一般都会走npmnpm将会走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 文件(如果当前目录没有,会向上递归查找)去选择当前的包管理工具,当然你肯定会想到一些花活:

  1. 有多个 lock 文件:这里是有优先级(pnpm > yarn > npm)
  2. 什么 lock 文件都没有:询问你使用哪一个包管理工具(如果没有询问那就是你的上层有 lock 文件)
  3. ni帮我选择好了包管理器但是我没装:会询问你是否安装对应的包管理工具

老项目中使用其他包管理器

有时候可能你也想在老项目中使用 yarn 或者 pnpm,这个也是这两个包一开始就支持的:

yarn import
pnpm import

这个命令将会通过目录下的package.lock.json生成对应包的 lock 文件,这样就可以防止直接安装依赖 lock 文件与package.lock.json版本相差过大。

结语

配置ni自动选择包管理器以及通过yarn import或者pnpm import命令,我们已经可以逃离包管理器不一致的问题。