Yarn工作区中TS公共库无法同时兼容React与Node.js编译问题
公共TypeScript库同时兼容Node.js服务端和React客户端的解决办法
我用Yarn工作区管理三个项目:TypeScript写的Node.js服务端、基于Create React App的TypeScript React客户端,还有一个公共TypeScript库。但怎么调试都没法让这个公共库同时兼容两边的编译,我不是JS专家,卡在这里了。
公共库基础文件
index.ts
export * from "./interfaces/AuthModels"
package.json(部分内容)
{ "main": "dist/index.js", "types": "dist/index.d.ts", }
两种失败的尝试
尝试1:编译成Node.js兼容版本,React客户端报错
给公共库的tsconfig.json配成这样,能编译出Node.js认的版本,但React跑不起来:
{ "compilerOptions": { "target": "esnext", "module": "commonjs", "moduleResolution": "node", }, }
React应用报错信息:
Uncaught TypeError: h.keyframes is not a function at ../../node_modules/react-hot-toast/dist/index.js (error.tsx:3:1) at options.factory (react refresh:6:1) at __webpack_require__ (bootstrap:24:1) at fn (hot module replacement:62:1) at ../common/dist/components/Notifications.js (Notifications.js:5:1) at options.factory (react refresh:6:1) at __webpack_require__ (bootstrap:24:1) at fn (hot module replacement:62:1) at ../common/dist/index.js (index.js:25:1) at options.factory (react refresh:6:1)
尝试2:编译成React兼容版本,Node.js服务端报错
把tsconfig改成下面这样,React能正常跑,但Node.js直接报错:
{ "compilerOptions": { "target": "esnext", "module": "esnext", "moduleResolution": "node", }, }
Node.js服务端报错信息:
export * from "./interfaces/AuthModels"; ^^^^^^ SyntaxError: Unexpected token 'export'
可行解决方案:双格式编译输出
要让公共库同时支持Node.js(CommonJS规范)和React(ES Modules规范),核心是编译出两种格式的产物,让两边各自读取对应的版本:
拆分tsconfig配置
给公共库建两个tsconfig文件,分别对应两种编译格式:tsconfig.cjs.json(对应CommonJS,给Node.js用):{ "extends": "./tsconfig.json", "compilerOptions": { "module": "commonjs", "outDir": "dist/cjs" } }tsconfig.esm.json(对应ES Modules,给React用):{ "extends": "./tsconfig.json", "compilerOptions": { "module": "esnext", "outDir": "dist/esm" } }
修改package.json指定双入口
更新公共库的package.json,分别指定两种格式的入口文件,同时修改build脚本编译两种产物:{ "main": "dist/cjs/index.js", "module": "dist/esm/index.js", "types": "dist/index.d.ts", "scripts": { "build": "tsc -p tsconfig.cjs.json && tsc -p tsconfig.esm.json" } }这样Node.js会自动读取
main字段的CommonJS产物,React的Webpack会优先用module字段的ES Modules产物,两边都能正常工作。处理前端依赖(可选)
如果公共库用到了react-hot-toast这类前端专属库,把它们放到peerDependencies里,避免在公共库编译时打包进去,防止版本冲突:{ "peerDependencies": { "react-hot-toast": "^2.4.0" } }
内容的提问来源于stack exchange,提问作者spierce7
相关产品推荐
相关产品推荐

