首页 > 其他分享 >掌握npm、yarn、pnpm的workspaces使用

掌握npm、yarn、pnpm的workspaces使用

时间:2023-12-15 17:11:20浏览次数:32  
标签:npm workspaces workspace docs components pnpm packages

workspaces(工作区)是一个通用术语,它指的是从单个顶级根包中管理本地文件系统中的多个包。

npm、yarn、pnpm 都提供了对 workspaces 的支持,在使用上会有些微的不同,今天就分享一下这几个包管理器分别使用 workspaces 的方式

前段时间写几个独立的组件,当时因为没考虑要做成啥样,就把 demo 文档和组件放在一个包管理了,随着需求的增多,不得不把文档抽离出来,由于前期都是用的 npm(因为要使用新发布的包),就直接使用 npm 的 workspaces 了

npm 的 workspaces 介绍及使用

npm 官网的介绍

以一个简单的组件库 demo 为例

项目初始化

创建 vangle 目录为项目的根目录,初始化 package.json

cd vangle
npm init -y

package.json

{
  "name": "vangle",
  "version": "1.0.0",
  "license": "ISC"
}

手动添加子包

创建 packages 存放所有的子包,然后在该目录下新建 docs 和 components 目录,分别初始化子包的 package.json

packages/components/package.json

{
  "name": "components",
  "version": "1.0.0",
  "license": "ISC"
}

packages/docs/package.json

{
  "name": "docs",
  "version": "1.0.0",
  "license": "ISC"
}
  • 目录结构为
|-- vangle
    |-- package.json
    |-- packages
        |-- components
        |   |-- package.json
        |-- docs
            |-- package.json

在根项目的 package.json 中添加 workspaces,其实就是包的路径数组,支持 Glob 通配符,这里的路径指向指的是 package.json 所在文件夹文件夹名。

{
  "name": "vangle",
  "version": "1.0.0",
  "license": "ISC",
  "workspaces": ["packages/components", "packages/docs"]
}

这时执行 npm install 后 node_modules 下就会有 components 和 docs 的依赖了

01.png

上面是手动添加子包的方式,npm 也提供了命令行的方式添加,所做的功能和上面手动类似,-w 就是 --workspace 的简写,但用法稍有区别,如下:

npm init -w ./packages/a -y
# or
npm init --workspace=./packages/b -y

没有层级目录会自动创建,生成 pckage.json 并在根目录 package.json 中添加 workspace 路径

  • workspaces 也支持 glob 通配符,例如像下面这样配置表示匹配 packages 目录下所有的一级子包
{
  "workspaces": ["packages/*"]
}

为子包添加、移除、更新依赖

  • 如果想为 components 包添加 dayjs 依赖,可以使用一下命令操作,使用-w [packageName]来告诉 npm 为哪个子包添加依赖
npm install dayjs -w components
npm uninstall dayjs -w components
npm update dayjs -w components

# or
npm install dayjs --workspace=components

注意:如果在项目根目录运行 npm install 会同时将子包及子包的依赖一起安装到根 node_modules 下

使用子包

为 components、docs 分别添加如下代码,由于 docs 依赖 components 建议位 docs 包添加依赖

npm install components -w docs
// packages/components/index.js
export const button = "button";

// packages/docs/index.js
import { button } from "components";
console.log(button);

在 docs/package.json 中添加启动脚本

{
  "name": "docs",
  "version": "1.0.0",
  "type": "module",
  "main": "index.js",
  "license": "ISC",
  "scripts": {
    "dev": "node index.js"
  }
}

因为使用了 ES module 需要添加"type": "module",在 docs/index.js 中导入了 components,默认回去加载 components/index.js,建议加上"main": "index.js",不然会有提示

  • 运行启动命令 dev
npm run dev -w docs
# run many
npm run dev -w docs -w components

# or
npm run dev --workspace=docs
npm run test --workspace=docs --workspace=components
  • 如果想启动子包的所有 dev 脚本可以使用--workspaces参数,如果有的子包没有 dev 脚本会报错,使用 --if-present参数可以避免
npm run dev --workspaces

# 有就运行
npm run dev --workspaces --if-present

在根 package.json 中运行工作区脚本

和上面一模一样,好处是可以简写运行的命令

"scripts": {
  "dev": "npm run dev --workspaces",
  "docs:dev": "npm run dev -w docs"
}

上面就是 npm 工作区的基本使用,这里快速总结一下几个常用命令

# 新增子包
npm init -w ./packages/a -y

# 为子包添加依赖
npm install dayjs -w components

# 运行子包的dev脚本
npm run dev -w docs

# 运行所有子包dev脚本,注意 --if-present 的使用时机
npm run dev --workspaces

yarn 使用 workspaces

yarn 官网的介绍

其实和 npm 差不多,这里还是按上面的方式操作一遍

工作区是一种设置包架构的新方法,从 Yarn 1.0 开始默认可用。 它允许你设置多个包,这样你只需要运行 yarn install 就可以一次性安装所有包。

使用 npm 安装 yarn

npm install -g yarn

项目初始化

创建 vangle 目录为项目的根目录,初始化 package.json

cd vangle
yarn init -y

package.json

{
  "name": "vangle",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "private": true,
  "workspace": ["packages/docs", "packages/components"]
}

private:根目录一般是项目的脚手架,无需发布,"private": true 会确保根目录不被发布出去

workspaces:其实就是包的路径数组,支持 Glob 通配符,这里的路径指向指的是 package.json 所在文件夹文件夹名。

相关命令

显示你当前项目的工作空间依赖树

yarn workspaces info
{
  "docs": {
    "location": "packages/docs",
    "workspaceDependencies": [],
    "mismatchedWorkspaceDependencies": []
  },
  "components": {
    "location": "packages/components",
    "workspaceDependencies": [],
    "mismatchedWorkspaceDependencies": []
  }
}

选定的工作空间(即包)中运行所选的 yarn 命令 yarn workspace <package-name> <command>

# 添加依赖
yarn workspace docs add dayjs

# 移除依赖
yarn workspace docs remove dayjs

如果你想为所有的包添加一个共同的依赖关系,进入项目的根目录并使用-W (或-ignore-workspace-root-check) 标志

yarn add dayjs -W -D

在 docs 包中安装 components 包(安装本地包),运行下面的命令,必须加上版本号

yarn workspace docs add [email protected]

# or
cd .\packages\docs
yarn add [email protected]

注意:如果远程仓库有相同名称相同版本的包会优先下载远程的,注意命名

hoist 依赖提升问题

如果直接切换到子包如:cd .\packages\docs,然后添加依赖 yarn add -D typescript,这时依赖还是会添加到根级的 node_modules 里

这是因为 yarn 默认会把子包安装的依赖会提升到根级,如果你想在子包中安装它,需要在根 package.json 中设置不需要提升的包nohoist,注意 workspaces 的结构

{
  "workspaces": {
    "packages": ["packages/*"],
    "nohoist": ["**/docs", "**/docs/**"]
  }
}

npm 原始好像没有 nohoist 的实现,所以上面没讲 代码

运行工作区 npm 脚本

  • 运行 docs 的 dev 脚本
yarn workspace docs dev
  • 在根 package.json 中运行工作区脚本 yarn docs:dev
"scripts": {
  "docs:dev": "yarn workspace docs dev"
}

pnpm 使用 workspaces

pnpm 官网的介绍

相比于 npm 和 yarn,pnpm 就是专门为 menorepo 而生的,提供了一些高级的 workspaces 用法。一些知名的开源项目如:Next.js、Vue3.0、Vite、Nuxt 等都陆续使用 pnpm 作为脚手架。

使用 pnpm 有以下几个优势,这也是 pnpm 项目的初衷。

  • 节省磁盘空间
  • 提高安装速度
  • 创建一个非扁平的 node_modules 目录

使用 npm 安装 pnpm

npm install -g pnpm

pnpm 和 npm、yarn 的用法相似,这里就不作过多介绍了,主要讲讲与workspaces相关的内容

项目初始化

创建 vangle 目录为项目的根目录,初始化 package.json

mkdir vangle
cd vangle
pnpm init -y

pnpm 内置了对单一存储库(也称为多包存储库、多项目存储库或单体存储库)的支持, 你可以创建一个 workspace 以将多个项目合并到一个仓库中。

与 npm、yarn 不同,pnpm 的 workspaces 的配置都放在 pnpm-workspace.yaml 文件里

一个 workspace 的根目录下必须有 pnpm-workspace.yaml 文件, 也可能会有 .npmrc 文件。

pnpm-workspace.yaml 定义了 工作空间 的根目录,并能够使您从工作空间中包含 / 排除目录 。 默认情况下,包含所有子目录。

# pnpm-workspace.yaml
packages:
  # all packages in direct subdirs of packages/
  - "packages/*"
  # # all packages in subdirs of components/
  # - 'components/**'
  # # exclude packages that are inside test directories
  # - '!**/test/**'

初始化子包命令

和 npm 类似

pnpm init -w ./packages/docs -y
pnpm init -w ./packages/components -y
  • 在项目根目录安装依赖
# 使用 --ignore-workspace-root-check 或 -w 来标记,否则在 root workspace 包添加依赖项时会失败。
pnpm add dayjs -w
  • 为子包添加依赖,--filter-F 的使用,--filter 后面跟的是包名
pnpm add dayjs --filter docs
  • 安装工作区里的子包,例如 docs 安装 components 作为依赖
pnpm add components --filter docs

看看 docs/package.json 中写入的是什么"components": "workspace:^1.0.0",前面有workspace:说明这个依赖来自于本地工作区

{
  "dependencies": {
    "components": "workspace:^1.0.0",
    "dayjs": "^1.11.7"
  }
}

workspace:是 pnpm Workspace 的协议,这里是官网的详细解释

默认情况下,如果可用的 packages 与已声明的可用范围相匹配,pnpm 将从工作区链接这些 packages。 例如, 如果 bar 引用"foo": "^1.0.0"并且[email protected]存在工作区,那么 pnpm 会从工作区将[email protected]链接到 bar。 但是,如果 bar 的依赖项中有 "foo": "2.0.0",而 [email protected] 在工作空间中并不存在,则将从 npm registry 安装 [email protected] 。 这种行为带来了一些不确定性。

幸运的是,pnpm 支持 workspace 协议 workspace: 。 当使用此协议时,pnpm 将拒绝解析除本地 workspace 包含的 package 之外的任何内容。 因此,如果您设置为 "foo": "workspace:2.0.0" 时,安装将会失败,因为 "[email protected]" 不存在于此 workspace 中。

当 link-workspace-packages 选项被设置为 false 时,这个协议将特别有用。 在这种情况下,仅当使用 workspace: 协议声明依赖,pnpm 才会从此 workspace 链接所需的包。

详细内容 请参考

hoist 相关配置

pnpm 提升方式,可以在 .npmrc 对其进行配置,.npmrc 文件都遵循 INI-formatted 列表,包含 key = value 参数。

更详细的配置请参考 pnpm.io/zh/npmrc

hoist

  • 默认值: true
  • 类型: boolean

当 hoist 为 true 时,所有依赖项都会被提升到 node_modules/.pnpm/node_modules。 这使得 node_modules 所有包都可以访问 未列出的依赖项。

hoist = true

hoist-pattern

  • 默认值: ['*']
  • 类型: string[]

告诉 pnpm 哪些包应该被提升到 node_modules/.pnpm/node_modules。 默认情况下,所有包都被提升 —— 但是,如果您知道只有某些有缺陷的包具有幻影依赖,您可以使用此选项专门提升幻影依赖(推荐做法)。

例如:

hoist-pattern[]=*eslint*
hoist-pattern[]=*babel*

还可以使用排除模式,过滤不需要提升的依赖

例如:

hoist-pattern[]=*types*
hoist-pattern[]=!@types/react

shamefully-hoist

  • 默认值: false
  • 类型:Boolean

默认情况下,pnpm 创建一个半严格的 node_modules,这意味着依赖项可以访问未声明的依赖项,但 node_modules 之外的模块不行。 通过这种布局,生态系统中的大多数的包都可以正常工作。 但是,如果某些工具仅在提升的依赖项位于根目录的 node_modules 时才有效,您可以将其设置为 true 来为您提升它们。

shamefully-hoist = true

运行工作区 npm 脚本

  • 运行 docs 的 dev 脚本
pnpm --filter docs dev
  • 在根 package.json 中运行工作区脚本 pnpm docs:dev
"scripts": {
  "docs:dev": "pnpm --filter docs dev"
}

最后

本文介绍了在 npm、yarn、pnpm 中使用 workspaces 的方式,基本功能都有实现,但 pnpm 确实提供了 npm 和 yarn 所没有的功能,可以根据项目的需要具体选择使用哪个

标签:npm,workspaces,workspace,docs,components,pnpm,packages
From: https://www.cnblogs.com/wp-leonard/p/17903768.html

相关文章

  • 【Node.js】-包以及npm基本使用操作
    一、包的概念将模块、代码、其他资料聚合成一个文件夹包分类:项目包:主要用于编写项目和业务逻辑软件包:封装工具和方法进行使用要求:根目录中,必须有package.js文件(记录包的清单信息)注意:导入软件包时,引入的默认是index.js模块文件/main属性指定的模块文件二、案例需求:封装数组求和函数......
  • 2023-12-14 npm和yarn无法拉取依赖,cnpm可以 ==》切换镜像源
    这两天遇到个问题,是关于依赖无法拉取的问题,尽管我有三分猜到了是什么原因,但我还是不肯往那个方向思考,哎,真是死牛一便颈。如,我要给前端项目装个express框架,用npm装,装了大半天一点反应都没有,用yarn装就直接报网络无法连接,如图: 用cnpm装就没问题,秒过。注意:我的电脑是能正常上网......
  • npm publish 一直不成功
    最近(2023-12-14)想要发布npm结果发现始终都报错。本来以为是办公室的环境配置问题,谁知道连公司班的电脑也不行(之前一直都是正常的),那这肯定就不是环境的问题了。其实反馈的log也指向了是网络的问题,proxy的问题,但是我一直在想从system的proxy去设置。最后发现是不起作用的。......
  • npm 安装是一直卡在idealTree:npm:sill idealTree buildDeps无反应
    最近npminstall下载依赖出现一直卡在idealTree:npm:sillidealTreebuildDeps,最后出现requesttohttps://registry.npmjs.org/simple-zustand-devtoolsfailed,reason:connectETIMEDOUT104.16.3.35:443连接超时?于是ping registry.npmjs.org下这个网站是能够正常连接的,......
  • vue项目 npm install 安装依赖 特别慢 解决办法
    vue项目npminstall安装依赖特别慢解决办法使用NPM(Node.js包管理工具)安装依赖时速度特别慢,为了安装Express,执行命令后两个多小时都没安装成功,最后只能取消安装,笔者20M带宽,应该不是我网络的原因,后来在网上找了好久才找到一种最佳解决办法,在安装时可以手动指定从哪个镜像服务器......
  • 使用 npm-check-updates 检查项目的 npm 依赖项是否有更新
    一、安装npm-check-updates:npminstall-gnpm-check-updates二、使用:在项目根目录运行以下命令,检查所有项目依赖项的最新版本:ncu执行结果如下:红色=主要升级青色=小幅升级绿色=补丁升级更新版本:ncu-u注意备份或者提交代码,确保包文件处于版本控制......
  • pure-admin pnpm  ERR_PNPM_FROZEN_LOCKFILE_WITH_OUTDATED_LOCKFILE  Cannot perf
    事情是这样的,用的开源pure-admin的框架,用的是pnpm,本地环境都是可以的,但是发布到生成就报以下错误  然后看部署参数,是这样的,强制用了lock文件,本来也没问题 报错的意思是json文件跟pnpm-lock.json文件不匹配但是本地看着是匹配的,随便挑选几个包版本看着也是一致的然后......
  • node.js--npm初始
    npm安装安装node.js时候会自动安装npm,所以如果安装了node.js就不需要安装npm了,命令行使用命令npm-v查看npm版本,出现版本号,则表示安装成功。npm初始化包使用npminit命令创建一个package.json文件,然后使用npminstall命令安装依赖。如果使用命令npminit-y则......
  • nvm、node、npm之间的关系和区别
    ......
  • devops - 在企业内使用verdaccio 搭建npm私有源
    verdaccio是一个基于nodejs的轻量化的私有源.在远程服务器的操作:1.安装和配置verdaccio全局安装verdaccionpminstall-gverdaccio配置文件路径~/.config/verdaccio/config.yaml配置远程访问listen:0.0.0.0:48732.运行verdaccio直接运行verdaccioverdaccio......