React项目中无法通过package.json的exports导入模块问题
我把一个用package.json的exports字段控制导入路径的TypeScript包,导入到Create React App(react-scripts 5.0.1)的TypeScript项目中时,exports配置完全不生效:本该用import {test} from "certificationtypes/certificate"导入导出的路径,实际只能用import {test} from "certificationtypes/src/certificate",而且未被exports导出的文件也能随意访问。但相同配置在Node.js项目中正常工作,webpack 5应该支持该特性,求React项目中的额外配置方案。
模块和React项目的package.json如下:
模块package.json
{ "name": "inputsvalidator", "version": "1.0.0", "description": "", "main": "./build/src/index.js", "exports": { "./certificate": "./build/src/certificate.js" }, "scripts": { "build": "tsc", "prepare": "npm run build", "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "devDependencies": { "typescript": "^4.9.4" }, "dependencies": { "@types/validator": "^13.7.10", "certificationtypes": "file:../certificationTypes", "countries": "file:../../../../../lib/shared/countries", "types": "file:../../../../../lib/shared/types", "validator": "^13.7.0" } }
React项目package.json
{ "name": "front-end", "version": "0.1.0", "private": true, "dependencies": { "@testing-library/jest-dom": "^5.16.5", "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^13.5.0", "@types/jest": "^27.5.2", "@types/node": "^16.18.11", "@types/react": "^18.0.26", "@types/react-dom": "^18.0.10", "certificationtypes": "file:../../lib/shared/certificationTypes", "countries": "file:../../../../lib/shared/countries", "inputsvalidator": "file:../../lib/shared/inputsValidator", "react": "^18.2.0", "react-dom": "^18.2.0", "react-scripts": "5.0.1", "react-spinners": "^0.13.7", "styled-components": "^5.3.6", "typescript": "^4.9.4", "validator": "^13.7.0", "web-vitals": "^2.1.4" }, "scripts": { "start": "react-scripts start", "build": "react-scripts build", "test": "react-scripts test", "eject": "react-scripts eject" }, "eslintConfig": { "extends": [ "react-app", "react-app/jest" ] }, "browserslist": { "production": [ ">0.2%", "not dead", "not op_mini all" ], "development": [ "last 1 chrome version", "last 1 firefox version", "last 1 safari version" ] }, "devDependencies": { "@types/styled-components": "^5.1.26" }, "proxy": "http://localhost:3003" }
1. 强制webpack解析package.json的exports字段
Create React App的默认webpack配置可能未启用对exports字段的解析,或对本地file:依赖的处理逻辑忽略了该字段。可以用react-app-rewired修改webpack配置,无需eject:
- 安装依赖:
npm install react-app-rewired customize-cra --save-dev - 在项目根目录创建
config-overrides.js文件,添加配置:module.exports = function override(config) { // 开启webpack对package.json exports字段的支持 config.resolve.exportsFields = ['exports']; return config; }; - 修改React项目
package.json中的scripts,替换为rewired命令:"scripts": { "start": "react-app-rewired start", "build": "react-app-rewired build", "test": "react-app-rewired test", "eject": "react-scripts eject" }
2. 配置TypeScript类型映射
即使webpack支持了exports,TypeScript可能仍无法识别导出路径的类型,需要在React项目的tsconfig.json中添加路径映射:
{ "compilerOptions": { // 保留原有配置 "paths": { "inputsvalidator/certificate": ["../../lib/shared/inputsValidator/build/src/certificate"], "certificationtypes/certificate": ["../../lib/shared/certificationTypes/build/src/certificate"] } } }
另外,建议在模块的package.json中明确指定类型入口,让TypeScript自动识别:
"exports": { "./certificate": { "import": "./build/src/certificate.js", "types": "./build/src/certificate.d.ts" } }, "types": "./build/src/index.d.ts"
3. 限制模块可访问的文件
在模块的package.json中添加files字段,只允许发布/build目录的文件,这样webpack无法访问src目录,强制使用exports配置的路径:
"files": ["build"]
4. 确保本地依赖的build产物完整
执行模块的npm run build命令,确保build目录下生成了正确的js和d.ts文件,且package.json中的main和exports指向的是build后的文件,而非src目录。
内容的提问来源于stack exchange,提问作者Bram Vanbilsen

