惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
人人都是产品经理
人人都是产品经理
Cisco Talos Blog
Cisco Talos Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
V
V2EX
博客园 - 三生石上(FineUI控件)
Martin Fowler
Martin Fowler
WordPress大学
WordPress大学
D
Docker
S
SegmentFault 最新的问题
博客园 - 聂微东
美团技术团队
Apple Machine Learning Research
Apple Machine Learning Research
月光博客
月光博客
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Last Week in AI
Last Week in AI
M
MIT News - Artificial intelligence
F
Fortinet All Blogs
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
The GitHub Blog
The GitHub Blog
GbyAI
GbyAI
L
LangChain Blog
Vercel News
Vercel News
博客园 - 叶小钗
MongoDB | Blog
MongoDB | Blog
Stack Overflow Blog
Stack Overflow Blog
H
Help Net Security
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
The Cloudflare Blog
Engineering at Meta
Engineering at Meta
T
Threat Research - Cisco Blogs
T
Threatpost
Scott Helme
Scott Helme
T
Tailwind CSS Blog
Latest news
Latest news
Stack Overflow Blog
Stack Overflow Blog
Blog — PlanetScale
Blog — PlanetScale
The Register - Security
The Register - Security
罗磊的独立博客
P
Proofpoint News Feed
腾讯CDC
S
Schneier on Security
雷峰网
雷峰网
A
About on SuperTechFans
T
Tenable Blog
F
Full Disclosure
Cyberwarzone
Cyberwarzone
博客园_首页
有赞技术团队
有赞技术团队
K
Kaspersky official blog

文章列表

win or mac clash 无 TUN 让 Antigravity、Chrome 强制 proxy(解决 Antigravity 无法加载选择 model、自动更新无法登录、跳转) 【大杂烩】在 pnpm 中直接修改 node_modules(.pnpm) 中的依赖项,项目中持久化 - pnpm 中的依赖处理、幽灵依赖、寻址规则等 在 html 中直接使用 Esm、Jsx 脚本快速调试和使用 React@19 和 Vue@3 源码,解决 React19 UMD 构建等问题 一键在本地批量检测并升级更新 package.json 中的模块依赖,ncu(npm-check-updates)在 npm、pnpm 或 workspace 项目中的使用教程 解决 Mac Docker Desktop 中启动出现的问题合集 通过阿里云、腾讯云无服务器搭建自定义的企业域名邮箱,实现在 QQ邮箱 收发等功能(附腾讯 SMTP 和 IMAP) 解决使用代理(clash 等)进行 SSH 连接(如 Github ssh key clone/push)出现 kex_exchange_identification 错误 静态文件资源 cdnjs, jsdelivr 抖音字节国内快速 CDN 镜像推荐【2025】- 仍在使用 bootcdn 和 staticfile CDN 请注意验证资源的完整性(SRI) pnpm monorepo 中管理依赖的最佳实践,与 Catalogs(目录)协议的使用(monorepo 中统一版本管理) Web 安全中的 Secure Contexts(安全上下文)- 解决在本地中使用 clipboard 或 Crypto 等 API 限制或关闭上下文限制 使用 serve 配合 openssl 或 mkcert 创建本地自签名可信任的证书 - 创建本地 TLS\SSL https 协议服务 利用 Github Actions 和 Acme 自动申请、更新和部署至阿里云、腾讯云 CDN Lets Encrypt SSl\TLS ECC RSA 双证书 【CSS】解决在 flex 容器中使用 align-content 或 justify-content 属性 center 居中时的溢出滚动和截断问题 - 理解 safe 关键字 在线工具 - 一键获取下载抖音无水印视频、抖音去水印解析工具、下载抖音无水印高清图集【2025 最新】 【React Router】v6 data router 在非组件(或工具方法)中如何优雅的跳转路由 【React】为什么路由跳转时页面滚动高度不会被重置(保留上个页面高度)?理解 history scrollRestoration 的场景与使用,以及如何使用 React Router 重置和跳转前保留滚动高度 【React】在本地 Html 中快速 debug(调试)React 源码 【React】结合源码和 EventLoop 分析 - 为什么 useLayoutEffect 会阻止 DOM 重绘(而 useEffect 闪烁)?为什么其内部 useState 会“同步”执行? React Compiler - 解放在函数中编程时的性能焦虑(React Conf 2024)附 Next 在线演示 在 github actions 中获取时间,并转换为中国标准时间(中国时区) 【npm】npm ci - npm clean install,在 CI、CD 中保持构建的一致性和可重复性 eslint 9.x 升级或使用指南,eslint.config.js 配置,包含 react、typescript、prettier 等常用配置升级迁移 使用 Spicetify 自定义 Spotify - 歌词翻译、全屏展示、主题替换 在 node 中快速代理请求(Proxy),解决跨域或请求转发问题 - http-proxy-middleware 修改请求体和返回 在 Hexo 中使用 AI(Gemini、deepseek、Azure)生成文章摘要,支持自定义模板。hexo-ai-summaries 插件文档(默认适配主题 Butterfly) 解决在 webstorm 或 idea 等 jetbrains 工具中遇到 Git 无法 force push,或 force push 灰色禁用无法点击(protected branches) hexo-seo-submit,Hexo 博客 SEO 优化插件 - 每日定时自动或手动提交链接至百度、Bing、Google,支持 Github Actions 和 Coding Jenkins 等CI(Hexo 插件编写) 【Node】Corepack - 解决 pnpm 或 yarn 的多版本管理、解决本地版本与 packageManager 中的版本一致性问题 解决 npm、cnpm 或 pnpm install 遇到 certificate has expired (证书已过期) npm、yarn、pnpm 设置最新国内镜像源(附官方镜像源和最新阿里源),以及 nrm 的使用教程【2025】 解决从 docker desktop 内镜像 linux 创建的容器,启动就停止、无法启动等问题(无进程容器) docker(docker desktop)中设置国内镜像源加速(阿里云、中科大),以及代理和容器代理设置,解决桌面端无法登陆就退出问题 【CSS】解决外边距重叠(重合)引起的 margin 垂直方向(top、bottom)不生效,无作用的问题 【CSS】CSS-Nesting:CSS 嵌套写法 —— 有望替代 less sass 的原生嵌套 【CSS】解决移动端(高清方案)下在谷歌浏览器中出现 字体大小布局异常,和设置的 font-size 不符(Text Autosizer、Font Boosting) 【CSS】主流 UI 库都在用的逻辑伪类选择器 not、where、is、has 【windows 11】使用 wePe 纯净 制作pe启动盘 安装\重装\升级 windows 11(windows 10)详细教程,附 windows 11 跳过联网、分区等教程 【webpack】Externals(外部扩展)浅析 - webpack 5 【Windows】一句话(一键、一分钟、一段代码)清除 Windows 11(10) 快捷方式角标(小箭头) 【Git】cherry-pick 使用场景介绍,如何在 WebStorm 中使用 cherry-pick;(从分支中提取 commit 功能) 【message-channel】了解频繁出现在框架的 Message Channel,及在事件循环(Event Loop)中的表现 【web-worker】浅析 useWorker 库如何只需函数方法即可在 worker 内运行;如何区分 Web Socket、Web Worker和Service Worker? 【React】理解学习 React 17中的批处理 与 18 批处理 为何用谷歌(Chrome)浏览器下载PDF时有时预览有时下载? 【less】Parent Selectors & 和 &&(多个父选择器的用法及回顾) 【React Router】在非组件(或工具方法)中如何优雅的跳转路由 - 理解 HashHistory 和 BrowserHistory 处理谷歌浏览器(google Chrome)https 站点将 http 资源自动转成 https - 附全站资源强制转 https vscode 国内直链接下载,提升(加速)下载速度 【css-tricks】从 flex 子元素超出父级(容器)宽度,探其原理 flex:1 时 width 的作用 linux,mac 终端(Terminal)上使用代理(http/https/socks5)提升速度,给 git 一键设置代理提升速度 修复 Win 11或10 Xbox Game Bar 录屏截屏打不开灰色等 ios,Windows 网页皆可平滑、惯性滚动(Smooth-scroll.js)- 博客、网站、web、JavaScript 【2022年】apple 苹果(ios)注册美服区(日区)ID教程(附免税地区及身份信息生成器)-时效:2022年2月 javaScript 文件上传 - input 上传 和 webAPi 上传(解决上传对 input 的依赖) Git 解决 pull 操作出现:不建议在没有为偏离分支指定合并策略时执行pull操作 一行代码解决谷歌浏览器出现:"您的连接不是私密连接" Nginx 中使用 cookie 灰度或分流 css 指定方向模糊 - 鸿蒙开机效果(animation 事件) PE 升级 windows11 解决不满足限制(绕开 TPM),顺带 surface pro 一键升级 windows11(无需 PE) 在 Hexo 中一键部署 github page 并同步 push 变更文件到指定分支(hexo-deployer-git) z390 + i79700 + rx560(讯景转蓝宝石) 双显卡双系统 - openCore 0.6x 黑苹果 BigSur 11.4(20F71) Progressive JPEG - Web 前端 渐进(模糊)加载图片 z390+英伟达1060+i7 9700 安装黑苹果教程(避坑)- MAC OS 10.13.6 饿了么外卖红包-百亿补贴(每天都可免费领),来自内部的优惠! Google AdSense 添加付款方式-使用银行外汇(招行外汇) ECMAScript2021 可用新特性 客户端或服务端 cookie 的设置、读取、携带问题 css 文字渐入效果,css 变量的进一步使用 setProperty
一文吃透 pnpm 如何使用 workspace 构建 monorepo,与 npm、yarn 的用法对比(pnpm 9.x 内部安装依赖问题 link-workspace-packages)
kshao · 2024-05-29 · via

环境与版本

  • platform => mac os
  • node => v22.2.0
  • npm => 10.8.0
  • pnpm => 9.1.3
  • yarn => 1.22.22

名词解释

利用单一仓库来管理多个 packages 的一种策略,如早期的 lerna

workspace

由上述单仓多包催生的管理方式,workspace(工作空间) 是 npmyarnpnpm 等包管理工具提供的一种特性,用于管理多个包的依赖关系。
合理配置 workspace 后,包之间互相依赖不需要使用 npm link,将在 install 时中处理

pnpm 中使用 workspace

A workspace must have a pnpm-workspace.yaml file in its root. A workspace also may have an .npmrc in its root.
如文档描述,启用 pnpmworkspace 需要在项目根目录创建 pnpm-workspace.yaml

项目结构

my-monorepo
├── docs
├── apps
│   └── web
├── packages
│   ├── ui
│   ├── eslint-config
│   └── shared-utils
├── pnpm-workspace.yaml
├── .npmrc => optional
└── sdk

根目录 package.json

/my-monorepo/package.json

{ "name": "my-monorepo", "private": true, "script": { "dev": "pnpm -r dev" } }

pnpm-workspace.yaml

在该项目中指定位于 my-monorepo/apps/my-monorepo/packages/ 内的直接子目录为工作区如 webui
docs 本身则为一个工作区,则不需要通配符

pnpm-workspace.yaml

packages: - "docs" - "apps/*" - "packages/*"

具体语法 - glob 通配符

pnpm-workspace.yaml

pnpm-workspace.yaml

packages: # 选择 packages 目录下的所有首层子目录的包 - 'packages/*' # 选择 components 目录下所有层级的包 - 'components/**' # 排除所有包含 test 的包 - '!**/test/**'

安装依赖

/my-monorepo/

pnpm install

在根目录中安装依赖

–workspace-root

/my-monorepo/

pnpm add <package-name> -w # or pnpm add <package-name> --workspace-root

给指定 workspace(工作空间) 安装依赖

--filterpackage.json name

/my-monorepo/

pnpm add <package-name> --filter <workspace-name> # or pnpm add lodash --filter docs

更新依赖

更新根目录依赖,看执行路径

pnpm update <package-name> [-w]

更新指定 workspace 依赖

pnpm update <package-name> --filter <workspace-name>
# or
pnpm update lodash --filter docs

卸载依赖

pnpm uninstall <package-name> [-w]
# or
pnpm uninstall <package-name> --filter <workspace-name>
# or
pnpm uninstall lodash --filter docs

执行脚本

执行 workspace 中的脚本

pnpm dev --filter docs

执行所有 workspace 中脚本

pnpm -r dev
# or
$ pnpm --recursive dev

或者在根目录的 package.json 中配置

/my-monorepo/package.json

{ "name": "my-monorepo", "script": { "docs:dev": "pnpm dev --filter docs" } }

直接执行

pnpm docs:dev

安装内部 workspace 依赖

pnpm add <package-name> --filter <workspace-name>
# or
pnpm add web --filter docs
  • 请注意你当前的 pnpm 版本,在 9.0pnpm 修改 link-workspace-packages 的默认值为 false。该属性开启后,你在安装依赖时优先在本地链接,而不是从 registry(远程) 中下载。
  • 所以在这个版本你若需要使用命令安装一个新的 workspace 中的依赖需要在 .npmrc 中启用 link-workspace-packages
  • 当然主动在 package.json 中声明的依赖不受影响,如 web: "workspace:*"pnpm 还是会自动处理,这种不确定性的执行结果可能是导致 pnpm 在该版本中禁用了该值

https://github.com/pnpm/pnpm/issues/7954#issuecomment-2062830615
9.x pnpm link-workspace-packages
8.x pnpm link-workspace-packages

.npmrc

.npmrc

link-workspace-packages = true

或临时启用

pnpm add <package-name> --filter <workspace-name> --link-workspace-packages=true
# or
pnpm add web --filter docs --link-workspace-packages=true

执行结果

/my-monorepo/packages/docs/package.json

{ "name": "docs", "dependencies": { "web": "workspace:^" } }

什么是 workspace:^ - semver 版本

你可能好奇 workspace:^ 是怎么生成的,后面 pnpm 是怎么如何转化的?

当你将依赖项添加到 package.json 中时,pnpm 根据 .npmrc 或命令行中的 save-workspace-protocol 字段来决定是否使用 workspace: 协议,并根据 save-prefix 字段来决定版本的前缀(semver

例如,save-prefix"~"save-workspace-protocoltrue

save-workspace-protocol

{
  "name": "docs",
  "dependencies": {
    "web": "workspace:~1.0.0"
  }
}

转化

{
	"dependencies": {
		"foo": "workspace:*",
		"bar": "workspace:~",
		"qar": "workspace:^",
		"zoo": "workspace:^1.5.0"
	}
}
{
	"dependencies": {
		"foo": "1.5.0",
		"bar": "~1.5.0",
		"qar": "^1.5.0",
		"zoo": "^1.5.0"
	}
}

总结

常用命令

# 安装依赖
$ pnpm install

# 给指定 workspace 安装依赖
$ pnpm add <package-name> --filter <workspace-name>

# 卸载依赖
$ pnpm uninstall <package-name> --filter <workspace-name>

# 更新依赖
$ pnpm update <package-name> --filter <workspace-name>

# 给根目录安装依赖 - -w 为安装 -workspace-root
$ pnpm add <package-name> -<D>w

# 内部包的互相引用 - 前提 .npmrc 中配置 link-workspace-packages = true
# 若未配置需手动
$ pnpm add <package-name> --filter <workspace-name>

# 执行 workspace 中的脚本, 或者在根目录的 package.json 中配置
$ pnpm dev --filter docs
# 执行所有 workspace 中的脚本 
$ pnpm -r dev
# or
$ pnpm --recursive dev

# 删除 workspace 中所有的 node_modules
rm -rf node_modules && pnpm -r exec -- rm -rf node_modules

npm 中使用 workspace

项目结构

my-monorepo
├── docs
├── apps
│   └── web
├── packages
│   ├── ui
│   ├── eslint-config
│   └── shared-utils
├── package.json
└── sdk

package.json 中配置 workspace

路径语法与 pnpm 一致 => 具体语法 - glob 通配符

{
  "name": "my-monorepo",
  "workspaces": [
    "apps/*",
    "packages/*"
  ]
}

命令初始化子包

根据提供的路径创建 workspace(路径不存在,则创建),并在根目录的 package.json 中添加 workspace 路径(若已经配置相关路径,则不会)

npm init -w ./newFolder/hooks -y
# or
npm init -w ./packages/hooks -y

workspace 添加、更新、移除依赖

npm install lodash -w docs
npm uninstall lodash -w docs
npm update lodash -w docs

# or
npm install lodash --workspace=docs

依赖内部的 workspace

pnpm 不同的是 npm 是直观的版号,当然你需要修改 semver 规则,可参考 save-prefix

npm install ui -w docs

/my-monorepo/packages/docs/package.json

{ "name": "docs", "dependencies": { "ui": "^1.0.0" } }

执行脚本

npm run dev -w docs
# run many
npm run dev -w docs -w ui

# or
npm run dev --workspace=docs
npm run test --workspace=docs --workspace=ui

批量执行 workspace 内的脚本

--if-present 避免 workspace 中不含当前脚本的报错

npm run dev

# or
npm run dev --if-present

在根目录 package.json 中运行 workspace 中的脚本

在此处配置一些常用的脚本命令

/my-monorepo/package.json

{ "name": "my-monorepo", "script": { "dev": "npm run dev", "docs:dev": "npm run dev -w docs" } }

总结

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

# 为子包添加依赖
npm install lodash -w docs

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

# 运行所有 workspace dev脚本
npm run dev

yarn 中使用 workspace

yarnnpm 大体一致,此处不阐述相同点。

命令

yarn workspaces info - 查询 workspace 之间依赖关系

yarn workspaces info

执行结果:

{
  "docs": {
    "location": "docs",
    "workspaceDependencies": [
      "eslint-config",
      "typescript-config",
      "ui"
    ],
    "mismatchedWorkspaceDependencies": []
  },
  "web": {
    "location": "web",
    "workspaceDependencies": [
      "eslint-config",
      "typescript-config"
    ],
    "mismatchedWorkspaceDependencies": []
  }
}

yarn workspace <package-name> <command> - 给 workspace 安装依赖

# 添加依赖
yarn workspace docs add lodash

# 移除依赖
yarn workspace docs remove lodash

yarn add <package-name> -W - 根目录安装依赖

yarn add lodash -w

yarn workspace <package-name> add <package-name@version> - 安装内部依赖

yarn workspace docs add ui@1.0.0
# or
yarn workspace docs add ui@^1.0.0

此处必须加上版本号,你可以手动加上 semver 前缀,但需要与 package.json 中的版本号保持一致即可,否则会去远程下载。

相关链接

pnpm monorepo 中管理依赖的最佳实践