monorepo架构下共享TypeScript公共库的实现方案咨询
解决方案
方案1:使用包管理器原生Workspace(最推荐)
这是目前monorepo场景下的标准实现,无需手动处理软链接、依赖同步等问题。
配置步骤
- 根目录新增
package.json,声明工作空间:
{ "private": true, "workspaces": ["pdf", "frontend", "mobile", "shared-ts"] }
如果使用pnpm,可在根目录新建pnpm-workspace.yaml,内容为:
packages: - 'pdf' - 'frontend' - 'mobile' - 'shared-ts'
- 各业务包(pdf/frontend/mobile)的
package.json中依赖直接写为:
"dependencies": { "shared-ts": "workspace:*" }
执行一次安装后,包管理器会自动在各业务包的node_modules下创建shared-ts的软链接,修改shared-ts代码实时生效,无需重复执行安装命令。
- 配置TypeScript识别规则:
在各业务包的tsconfig.json中新增路径映射:
{ "compilerOptions": { "baseUrl": ".", "paths": { "shared-ts": ["../shared-ts/src"], "shared-ts/*": ["../shared-ts/src/*"] } } }
同时确保shared-ts的package.json中正确声明入口和类型文件:
{ "main": "./src/index.ts", "types": "./src/index.ts" }
如果需要生产环境构建时提前编译shared-ts,可将上述字段指向编译后的dist目录,开发阶段保留指向src即可实现热更新。
- React Native适配:
React Native的Metro打包器默认不识别工作空间的软链接,需要在mobile/metro.config.js新增如下配置:
const path = require('path'); module.exports = { projectRoot: __dirname, watchFolders: [path.resolve(__dirname, '../shared-ts')], resolver: { extraNodeModules: { 'shared-ts': path.resolve(__dirname, '../shared-ts') } } };
方案2:路径映射适配(无需改动包管理逻辑)
如果不想引入工作空间配置,可直接通过编译工具的路径映射实现源码引用:
- 在所有业务包的
tsconfig.json中配置上述的paths规则,确保TypeScript可以识别shared-ts模块 - 对应构建工具(Vite/Webpack/Rollup)也配置相同的别名规则,比如Vite的
vite.config.ts:
import { defineConfig } from 'vite'; import path from 'path'; export default defineConfig({ resolve: { alias: { 'shared-ts': path.resolve(__dirname, '../shared-ts/src') } } });
该方案无需将shared-ts加入依赖列表,所有工具直接从本地路径读取源码,修改实时生效。
之前方案失效的原因说明
- 直接配置相对路径依赖:NPM及Yarn v1默认会复制本地依赖到
node_modules,而非创建软链接,升级到Yarn v2+/pnpm可解决该问题 - 手动创建软链接TS无法识别:未配置
paths映射,或shared-ts的package.json未正确声明入口文件 - npm link性能差:全局链接会扫描全局依赖目录,工作空间的软链接是项目级别的,无额外性能开销,也不存在CI权限问题
内容的提问来源于stack exchange,提问作者Corentin S.
相关产品推荐
相关产品推荐

