Monorepo中Rollup启用preserveModules:true时TS类型文件同目录放置问题
Turborepo+Rollup preserveModules 跨包类型输出目录对齐方案
问题情况
用 Turborepo 管理的 TypeScript Monorepo,每个包都开启了 Rollup 的 preserveModules: true 来支持单独导入组件/文件,但跨包导入类型时,dist 目录结构不符合预期:
当前生成的结构:
- dist - components - Button.js - packageA - components - Button.d.ts - packageB - BaseTypes.d.ts
期望的结构:
- dist - components - Button.js - Button.d.ts - BaseTypes.d.ts
具体调整步骤
1. 修改包内的 tsconfig.json
在目标包(比如 packageA)的 tsconfig.json 中,调整 compilerOptions 配置:
{ "compilerOptions": { "rootDir": "./src", // 指向包的源码根目录 "declaration": true, "declarationDir": "./dist/components", // 强制类型文件输出到组件目录 "baseUrl": "./", "paths": { "@packageB/*": ["../packageB/src/*"] // 让TS将跨包导入解析为相对路径,避免生成包名层级目录 }, // 保留原有其他配置 } }
2. 调整 Rollup 配置,对齐JS与类型输出路径
在 Rollup 配置文件中,确保JS输出到 dist/components,同时通过 @rollup/plugin-typescript 让类型文件输出路径与JS保持一致:
import typescript from '@rollup/plugin-typescript'; export default { input: 'src/components/Button.tsx', output: { dir: 'dist/components', format: 'esm', preserveModules: true, preserveModulesRoot: 'src/components' // 将src/components作为模块根,避免生成多余层级 }, plugins: [ typescript({ tsconfig: './tsconfig.json', declarationDir: './dist/components' // 强制类型文件输出到JS同目录 }) ], // 保留原有其他配置 };
3. 复制跨包类型文件(可选)
如果需要将依赖包的类型文件也同步到当前包的组件目录,可使用 rollup-plugin-copy 插件在打包完成后执行复制:
import copy from 'rollup-plugin-copy'; export default { // ...其他配置 plugins: [ // ...已有插件 copy({ targets: [ { src: '../packageB/src/types/BaseTypes.ts', dest: 'dist/components', rename: (name) => name.replace('.ts', '.d.ts') // 转换为d.ts后缀 } ], hook: 'writeBundle' // 等待打包完成后再复制,避免被覆盖 }) ] };
4. 调整 Turborepo 缓存配置
在根目录的 turbo.json 中,将 tsconfig 和 rollup 配置文件加入缓存输入项,避免缓存旧的输出结构:
{ "pipeline": { "build": { "dependsOn": ["^build"], "outputs": ["dist/**"], "inputs": ["src/**", "tsconfig.json", "rollup.config.js"] } } }
验证方法
在项目根目录执行 yarn build:ui,查看目标包的 dist/components 目录,确认JS文件与所有相关类型文件都处于同一层级。
内容的提问来源于stack exchange,提问作者Jeff
相关产品推荐
相关产品推荐

