在Monorepo中能否配置包优先使用未编译的源代码?
我正在使用Yarn 2进行相关开发,想要实现如下效果:
我目前的Monorepo目录结构如下:
/ packages/ shared-ts/ package.json src/ lib*/ app-ts/ package.json src/ lib*/ app-js/ package.json src/ lib*/
其中lib*代表该目录被加入gitignore,是存放编译后产物的目录。
本示例中,依赖库shared-ts会被app-ts和app-js两个应用使用。
常规实现方案
这类Monorepo的常规配置方式是在shared-ts的package.json中做如下配置:
"main": "lib/index.js" "scripts" : { "build": "tsc" }
其中build脚本会将index.js和index.d.ts编译输出到lib目录下。
当app-ts和app-js解析该依赖包时,会从lib目录中读取index.js,针对app-ts的场景还会读取对应的index.d.ts。
该方案运行正常,但存在一个问题:开发者修改shared-ts的代码后,必须手动执行build脚本,修改才会同步到依赖它的应用中。如果依赖层级较多,这个问题会更加突出。
尝试的解决方案1:将main指向src/index.ts
我尝试将shared-ts的package.json修改为:
"main": "src/index.ts" "scripts" : { "build": "tsc" }
该方案通常无法生效,因为原生node进程无法解析.ts文件中的语法(比如import关键字)。
潜在解决方案:使用publishConfig
我目前正在考虑还未实际验证的一个方案是使用package.json中的publishConfig字段。
该字段包含的配置仅在从本地源码生成包的时候生效(比如执行yarn pack或者yarn npm publish这类发布命令时)。
配置示例如下:
"main": "src/index.ts", "publishConfig": { "main": "lib/index.js" }
该方案的设计思路是:
- 发布包到npm时,会使用
lib/index.js作为入口,代码无需额外编译即可直接使用,符合发布要求。👍 - 在Monorepo内部直接使用该包时,会以
src/index.ts作为入口,如果是用ts-node运行app-ts这类场景可以正常生效。😕
但该方案存在缺陷:在开发环境运行没有额外配置语法解析能力的app-js时会报错。
目前可行的最优方案
我当前的最优解决方案是放弃“无需编译”的设想,要求开发者修改代码后重新执行build命令来同步变更。
内容的提问来源于stack exchange,提问作者dwjohnston

