You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何构建支持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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 06:10:21