如何在TypeScript Monorepo中实现无构建流水线
Monorepo ESM 运行方案(无需构建common包,支持热更新)
你的Monorepo结构如下:
/apps /apps/app1 /apps/app1/src (包含index.ts及其他文件、子文件夹) /apps/app1/tsconfig.json /apps/app1/package.json /apps/app2 /apps/app2/src (包含index.ts及其他文件、子文件夹) /apps/app2/tsconfig.json /apps/app2/package.json /common /common/package1 /common/package1/src /common/package1/src/utility1.ts /common/package1/src/utility2.ts /common/package1/tsconfig.json /common/package1/package.json /tsconfig.json /package.json
以下是满足需求的配置和运行步骤:
1. 全局及子包启用ESM
所有package.json(根目录、apps下各应用、common下各包)中添加"type": "module",确保整个项目以ESM模式运行。
示例:common/package1/package.json配置
{ "name": "@your-org/package1", "type": "module", "main": "./src/index.ts", // 直接指向源码入口,无需构建到dist "types": "./src/index.ts" // TypeScript类型直接读取源码文件 }
2. 配置TypeScript项目引用与路径别名
通过TypeScript的项目引用确保依赖关系正确,路径别名简化common包的引用。
根目录tsconfig.json
{ "compilerOptions": { "target": "ESNext", "module": "ESNext", "moduleResolution": "bundler", "strict": true, "esModuleInterop": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true, "baseUrl": ".", "paths": { "@your-org/*": ["common/*/src"] // 别名映射common下的源码目录 } }, "references": [ {"path": "./apps/app1"}, {"path": "./apps/app2"}, {"path": "./common/package1"} ] }
子包tsconfig.json示例(common/package1/tsconfig.json)
{ "compilerOptions": { "composite": true, // 开启项目引用必需 "target": "ESNext", "module": "ESNext", "moduleResolution": "bundler", "strict": true, "esModuleInterop": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true, "rootDir": "./src", "outDir": "./dist", // 项目引用要求配置,实际运行不会用到此目录 "declaration": true }, "include": ["src/**/*"], "references": [] }
应用tsconfig.json示例(apps/app1/tsconfig.json)
{ "compilerOptions": { "composite": true, "target": "ESNext", "module": "ESNext", "moduleResolution": "bundler", "strict": true, "esModuleInterop": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true, "rootDir": "./src", "outDir": "./dist", "paths": { "@your-org/*": ["../../common/*/src"] // 子目录下的别名映射 } }, "include": ["src/**/*"], "references": [ {"path": "../../common/package1"} // 声明依赖common/package1 ] }
3. 使用tsx运行单个应用(支持watch热更新)
tsx可以直接编译并运行TypeScript文件,且watch模式会自动监听所有依赖文件(包括common源码)的变化,修改后立即重启应用。
- 安装tsx(根目录或对应应用目录执行):
npm install -D tsx
- 运行应用并开启watch:
# 在apps/app1目录下执行 tsx watch --clear-screen=false src/index.ts # 或在根目录执行 tsx watch --clear-screen=false apps/app1/src/index.ts
4. 同时运行多个应用
借助concurrently工具实现多应用同时运行并各自监听文件变化:
- 安装concurrently:
npm install -D concurrently
- 根目录
package.json添加scripts:
"scripts": { "start:app1": "tsx watch --clear-screen=false apps/app1/src/index.ts", "start:app2": "tsx watch --clear-screen=false apps/app2/src/index.ts", "start:all": "concurrently \"npm run start:app1\" \"npm run start:app2\"" }
- 启动所有应用:
npm run start:all
注意事项
- 所有ESM导入需明确扩展名,比如使用路径别名时:
import { utility1 } from '@your-org/package1',或相对路径时:import { utility1 } from '../../common/package1/src/utility1.js' - tsx会自动读取tsconfig的路径别名配置,确保运行时tsconfig文件可被正确加载。
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

