如何编程编译TypeScript项目引用并为每个项目传递独立编译选项
针对
ts.createSolutionBuilder动态传递单项目编译选项的实现方案 核心思路
ts.createSolutionBuilder 支持自定义构建宿主来拦截配置读取逻辑,不需要依赖本地存储的tsconfig.json文件,你可以通过重写宿主的配置读取相关方法,为每个项目返回动态生成的编译配置。
实现步骤
- 先维护全局的动态配置映射表,键为每个项目的根路径,值为该项目对应的tsconfig配置内容(可以是JSON字符串,也可以是解析后的
ts.ParsedCommandLine对象) - 扩展官方提供的默认Solution Builder宿主,重写
readFile、getModifiedTime方法,拦截tsconfig.json的读取请求,直接返回你预生成的对应项目的配置内容 - 可选优化:重写
readConfiguration方法直接返回解析完成的配置对象,省去JSON序列化/反序列化的性能开销
代码示例
import * as ts from "typescript"; // 动态配置映射:key为项目绝对路径,value为对应项目的tsconfig配置JSON const projectConfigMap = new Map<string, string>([ ["/workspace/packages/package-a", JSON.stringify({ compilerOptions: { outDir: "./dist", rootDir: "./src", declaration: true }, include: ["src/**/*"], references: [{ path: "../package-b" }] })], ["/workspace/packages/package-b", JSON.stringify({ compilerOptions: { outDir: "./dist", rootDir: "./src", strict: false }, include: ["src/**/*"] })] ]); // 创建基础构建宿主 const host = ts.createSolutionBuilderHost( undefined, (err) => console.error(err), (log) => console.log(log) ); // 重写文件读取方法,拦截tsconfig请求 const defaultReadFile = host.readFile; host.readFile = (filePath: string) => { const normalizedPath = ts.normalizePath(filePath); for (const [projectRoot, configJson] of projectConfigMap) { const targetConfigPath = ts.normalizePath(ts.join(projectRoot, "tsconfig.json")); if (normalizedPath === targetConfigPath) { return configJson; } } return defaultReadFile(filePath); }; // 重写修改时间查询,避免TS缓存不存在的配置文件状态 const defaultGetMtime = host.getModifiedTime; host.getModifiedTime = (filePath: string) => { const normalizedPath = ts.normalizePath(filePath); for (const [projectRoot] of projectConfigMap) { const targetConfigPath = ts.normalizePath(ts.join(projectRoot, "tsconfig.json")); if (normalizedPath === targetConfigPath) { // 配置有更新时可返回最新时间戳,强制重新构建 return new Date(); } } return defaultGetMtime(filePath); }; // 初始化构建器并执行构建 const builder = ts.createSolutionBuilder(host, ["/workspace/tsconfig.json"], { force: true }); const exitCode = builder.build(); console.log(`构建结束,退出码:${exitCode}`);
额外说明
你动态生成的每个项目配置中的references路径需要和映射表中的项目路径对应,保证TypeScript可以正确识别项目依赖顺序,不会出现依赖缺失的编译错误。
内容的提问来源于stack exchange,提问作者David
相关产品推荐
相关产品推荐

