You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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源码)的变化,修改后立即重启应用。

  1. 安装tsx(根目录或对应应用目录执行):
npm install -D tsx
  1. 运行应用并开启watch:
# 在apps/app1目录下执行
tsx watch --clear-screen=false src/index.ts

# 或在根目录执行
tsx watch --clear-screen=false apps/app1/src/index.ts

4. 同时运行多个应用

借助concurrently工具实现多应用同时运行并各自监听文件变化:

  1. 安装concurrently:
npm install -D concurrently
  1. 根目录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\""
}
  1. 启动所有应用:
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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 22:35:11