如何配置pnpm工作区包以兼顾本地使用与外部导出?
解决pnpm Monorepo本地用src、外部用dist的优雅方案
核心思路是利用pnpm的workspace条件导出+package.json条件字段,让包在本地工作区和外部环境自动切换源文件,无需手动修改配置。
1. 子包package.json核心配置
每个子包的package.json里通过exports字段区分workspace和外部场景,同时配置类型和入口:
{ "name": "@packages/my-package", "type": "module", "main": "./dist/index.js", "types": "./dist/index.d.ts", "exports": { ".": { // pnpm workspace环境下直接指向src入口 "workspace": "./src/index.ts", // 外部安装时用打包后的dist文件 "default": "./dist/index.js" }, // 可选:允许本地直接导入子包内的src文件(比如@packages/my-package/src/utils) "./src/*": "./src/*" }, "scripts": { "build": "vite build" } }
2. 根目录pnpm配置确保workspace协议生效
根目录的pnpm-workspace.yaml保持常规配置即可:
packages: - 'packages/*'
根目录.npmrc添加以下配置,避免类型依赖被异常hoist:
public-hoist-pattern[]=*typescript*
3. Vite配置适配
子包打包配置(packages/my-package/vite.config.js)
确保打包产物输出到dist,并生成类型声明:
import { defineConfig } from 'vite' import dts from 'vite-plugin-dts' export default defineConfig({ build: { lib: { entry: './src/index.ts', formats: ['es', 'cjs'], fileName: (format) => `index.${format}.js` }, outDir: './dist' }, plugins: [dts({ rollupTypes: true })] })
主项目Vite配置(比如根目录的apps/web/vite.config.js)
添加别名确保本地解析子包src路径:
import { defineConfig } from 'vite' export default defineConfig({ resolve: { alias: { '@packages/my-package': '@packages/my-package/src' } } })
4. TypeScript类型适配
根目录tsconfig.json配置路径别名,让本地开发时直接读取src的类型:
{ "compilerOptions": { "baseUrl": ".", "paths": { "@packages/*": ["packages/*/src"] } }, "include": ["packages/**/src/**/*"] }
外部安装时,子包的types字段指向dist/index.d.ts,会自动读取打包后的类型文件。
5. 多包批量复用方案
如果要给多个子包套用这套配置:
- 编写一个模板
package.json.tpl,包含上述核心字段 - 用Node.js脚本批量替换子包的package.json,或者用工具(如
changesets、turbo)统一管理配置 - 根目录添加统一构建脚本:
"build:all": "pnpm run build --filter './packages/*'"
关键注意事项
- 子包src文件需使用与主项目一致的模块规范(比如ES Module),避免本地执行报错
- 发布到GitHub Packages前,必须先执行全量构建,确保dist文件存在
- 若子包有内部依赖(比如@packages/utils),同样用
workspace:*安装,确保本地也走src路径
内容的提问来源于stack exchange,提问作者Classtronaut
相关产品推荐
相关产品推荐

