如何在Node.js中排除导出文件,解决React应用fs模块未找到错误
问题背景
我维护着一个Node.js库OasisLib,其中包含TypeGenerator.ts文件——这个文件在构建阶段依赖fs模块访问文件系统。该库需要同时支持两个场景:
- React应用OasisUI(浏览器环境)
- 另一团队的Node.js库OasisLibExtension(需要用TypeGenerator在构建时生成文件)
目前我在OasisLib的index.ts中导出了TypeGenerator,但运行OasisUI时出现以下错误:
ERROR in ../OasisLib/dist/src/gen/TypeGenerator.js 48:15-28 Module not found: Error: Can't resolve 'fs' in '/Volumes/Code/OasisLib/src/OasisLib/dist/src/gen'
即便OasisUI并未直接使用TypeGenerator,webpack仍会尝试编译该文件。我曾尝试在OasisUI的package.json中添加exports忽略配置、将browser字段的fs设为false,但均未解决问题。
以下提供两种可行方案:
方案一:拆分导出入口,隔离Node.js专属工具
通过修改OasisLib的package.json,配置多环境入口,让React应用和Node.js扩展库分别加载不同的导出内容:
修改OasisLib的package.json,添加
exports字段
明确区分Node.js环境和浏览器环境的主入口,同时给TypeGenerator单独配置导出路径:"exports": { ".": { "node": "./dist/index.js", "browser": "./dist/browser-index.js" }, "./type-generator": "./dist/src/gen/TypeGenerator.js" }, // 保留原main、types字段作为兼容 "main": "dist/index.js", "types": "dist/types/index.d.ts"创建浏览器专属入口文件
在OasisLib源码中新建browser-index.ts,仅导出React应用需要的内容,不要包含TypeGenerator:// browser-index.ts export { /* 仅导出UI需要的工具、组件等 */ };原
index.ts保留TypeGenerator的导出,作为Node.js环境的默认入口。扩展库的使用方式
OasisLibExtension团队可通过指定路径直接导入TypeGenerator:import TypeGenerator from '@myorg/oasis-lib/type-generator';
这种方式从根源上避免浏览器环境加载依赖fs的代码,同时不影响Node.js扩展库的使用。
方案二:在React应用构建时排除特定文件
如果无法修改OasisLib的结构,可以通过修改React应用的构建配置,强制排除TypeGenerator文件:
针对Create React App(CRA)项目
安装
craco和null-loader:npm install @craco/craco null-loader --save-dev在OasisUI根目录创建
craco.config.js:module.exports = { webpack: { configure: (config) => { // 添加规则,忽略TypeGenerator.js文件 config.module.rules.push({ test: /TypeGenerator\.js$/, include: /@myorg\/oasis-lib/, use: 'null-loader' }); return config; } } };修改OasisUI的package.json脚本,替换为craco命令:
"scripts": { "start": "craco start", "build": "craco build", "test": "craco test" }
针对Vite React项目
安装
empty-module:npm install empty-module --save-dev修改
vite.config.js,添加别名映射:import { defineConfig } from 'vite'; import react from '@vitejs/plugin-react'; export default defineConfig({ plugins: [react()], resolve: { alias: { // 将TypeGenerator映射为空模块 '@myorg/oasis-lib/dist/src/gen/TypeGenerator.js': 'empty-module' } } });
附OasisLib的原始package.json内容:
{ "name": "@myorg/oasis-lib", "version": "1.0.0", "description": "", "author": "", "license": "UNLICENSED", "main": "dist/index.js", "types": "dist/types/index.d.ts", "scripts": { "clean": "rm -rf dist && rm -rf node_modules", "generate-models": "node ./dist/src/gen/GenerateTypes.js && tsc", "build": "tsc && npm run generate-models", "watch": "tsc -w", "prepublishOnly": "npm run build && npm run test", "test:watch": "vitest", "test": "vitest run --coverage --passWithNoTests", "start": "env-cmd -f .env.staging react-scripts start" }, "files": [ "dist/src/*", "dist/types/*" ], "npm-pretty-much": { "runTest": "never" }, "dependencies": { "ion-js": "^4.3.0" }, "devDependencies": { "@testing-library/jest-dom": "^6.0.1", "@testing-library/react": "^14.1.2", "@types/jest": "*", "@types/node": "^16.18.25", "@vitejs/plugin-react": "^4.0.3", "@vitest/browser": "^0.34.6", "@vitest/coverage-v8": "^0.34.6", "env-cmd": "^10.1.0", "prettier": "2.8.4", "react-scripts": "^5.0.1", "typescript": "^4.9.5", "vite": "^4.4.5", "vitest": "^0.34.6" }, "peerDependencies": { "@types/react": ">=18", "@types/react-dom": ">=18", "react": ">=18", "react-dom": ">=18" }, "browserslist": { "production": [ ">0.2%", "not dead", "not op_mini all" ], "development": [ "last 1 chrome version", "last 1 firefox version", "last 1 safari version" ] } }
内容的提问来源于stack exchange,提问作者Buddha

