如何构建支持Browser/React与Node.js服务端的通用NPM库?
解决方案
1. 拆分库的入口文件,区分跨端与服务端代码
将通用库按功能拆分目录结构,明确区分跨端可用代码和服务端专属代码:
src/ ├── shared/ # 跨端通用代码(客户端+服务端都能用) │ ├── utils.js │ └── apiHelpers.js ├── server/ # 服务端专属代码(仅Node.js可用) │ ├── fileHandler.js │ └── serverUtils.js ├── index.js # 服务端入口(导出所有代码) └── browser.js # 客户端入口(仅导出shared目录代码)
在package.json中配置不同环境的入口,让包管理器自动适配:
{ "name": "your-common-lib", "main": "./src/index.js", // Node.js环境默认加载 "browser": "./src/browser.js", // 浏览器/React环境自动加载这个 "files": ["src", "dist"] // 发布时包含的文件 }
服务端入口index.js示例:
// 导出所有跨端+服务端代码 module.exports = { ...require('./shared/utils'), ...require('./shared/apiHelpers'), ...require('./server/fileHandler'), ...require('./server/serverUtils') };
客户端入口browser.js示例:
// 仅导出跨端代码 module.exports = { ...require('./shared/utils'), ...require('./shared/apiHelpers') };
2. 修复Webpack UMD构建的依赖解析错误
针对Node.js内置模块(如fs、path),Webpack在浏览器环境下无法解析,需在配置中声明这些模块为外部依赖:
修改你的Webpack配置文件:
const path = require("path"); module.exports = { entry: { main: path.resolve(__dirname, "src/index.js"), // 服务端UMD包 browser: path.resolve(__dirname, "src/browser.js") // 客户端UMD包 }, output: { path: path.resolve(__dirname, "dist"), filename: "[name].js", globalObject: "this", library: { name: "common-libs", type: "umd", }, }, mode: process.env.NODE_ENV, externals: { // 声明Node.js内置模块为外部依赖,浏览器环境不打包 fs: "commonjs fs", path: "commonjs path", // 其他服务端专属模块也可以在这里添加 }, node: { // 禁用Webpack对Node.js全局变量的模拟 global: false, __filename: false, __dirname: false } };
运行构建后,dist目录会生成两个UMD文件:main.js(服务端用)和browser.js(客户端用),同时更新package.json的入口指向UMD文件:
{ "main": "./dist/main.js", "browser": "./dist/browser.js" }
3. 可选:通过条件导入避免服务端代码被客户端加载
如果不想拆分入口,可以在代码中添加环境判断,仅在Node.js环境下加载服务端专属模块:
// src/index.js const sharedUtils = require('./shared/utils'); const apiHelpers = require('./shared/apiHelpers'); let serverExports = {}; // 判断是否为Node.js环境 if (typeof window === 'undefined' && process?.env?.NODE_ENV !== 'browser') { serverExports = { ...require('./server/fileHandler'), ...require('./server/serverUtils') }; } module.exports = { ...sharedUtils, ...apiHelpers, ...serverExports };
这种方式需要确保Webpack在构建客户端包时,会tree-shake掉服务端代码(需开启mode: 'production')。
4. NPM发布前的验证
- 本地测试:在React项目中通过
npm link链接本地库,确认客户端不会加载fs等模块 - 服务端测试:在Node.js项目中导入库,验证服务端功能正常
- 确保
package.json中的files字段包含所有需要发布的文件,避免遗漏
内容的提问来源于stack exchange,提问作者Alessandro Staffolani
相关产品推荐
相关产品推荐

