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

如何用tsup构建含React组件与Express路由的共享库?

解决方案:通过tsup配置分离前后端代码,解决Node.js模块解析错误

问题根源在于你将依赖Node.js API的Express路由与React组件打包在同一模块中,Next.js在浏览器环境加载时会尝试解析所有依赖(包括async_hooks、fs等Node内置模块),而这些模块在浏览器中不存在,因此报错。以下是通过tsup实现需求的具体方案:

1. 拆分前后端专用入口(最可靠方案)

将组件库拆分为前端纯组件入口和后端组件+路由入口,让Next.js仅导入不含Node代码的前端入口。

修改tsup配置

import { defineConfig } from "tsup";

export default defineConfig({
  entry: {
    // 前端专用入口:仅导出React组件,不包含任何路由/Node相关代码
    "frontend/index": "src/frontend-exports.ts",
    // 后端专用入口:导出组件+路由的组合结构
    "backend/index": "src/backend-exports.ts",
    // 保留原有入口(按需保留)
    index: "src/index.ts",
    "apps/index": "src/applications/index.ts",
    "surprises/index": "src/surprises/index.ts",
  },
  format: ["esm"],
  splitting: true,
  // 将Node相关依赖标记为外部,让后端项目自行安装处理
  external: ["express", "mongodb", "async_hooks", "fs", "dns"],
  // 针对不同入口做差异化配置
  esbuildOptions: (options, context) => {
    if (context.entryNames.includes("frontend")) {
      // 适配浏览器环境,忽略Node内置模块解析
      options.mainFields = ["browser", "module", "main"];
      options.define = {
        ...options.define,
        "process.env.NODE_ENV": JSON.stringify(process.env.NODE_ENV),
      };
    }
  },
  // 生成类型声明
  dts: true,
});

编写拆分后的入口文件

  • 前端入口文件 src/frontend-exports.ts:仅导出React组件
// 只暴露组件,不涉及任何路由/Node逻辑
export { AppComponent } from "./applications/index";
export { SurpriseComponent } from "./surprises/index";
  • 后端入口文件 src/backend-exports.ts:导出组件+路由的组合
import { Router } from "express";
import { FC } from "react";
import { AppComponent } from "./applications/index";
import { appRouter } from "./routes/app-router"; // 你的Express路由文件

export interface IExportedMember {
  component: FC;
  router: Router;
}

export const appExport: IExportedMember = {
  component: AppComponent,
  router: appRouter,
};

// 同理导出其他组件+路由组合

在项目中导入

  • Next.js前端项目导入纯组件:
import { AppComponent } from "@your-component-lib/frontend/index";
  • Express后端项目导入组合结构:
import { appExport } from "@your-component-lib/backend/index";

2. 配合package.json条件导出优化导入体验

在组件库的package.json中配置条件导出,让不同环境自动匹配对应入口:

"exports": {
  ".": {
    "node": "./dist/backend/index.js",
    "browser": "./dist/frontend/index.js",
    "types": "./dist/index.d.ts"
  },
  "./frontend": "./dist/frontend/index.js",
  "./backend": "./dist/backend/index.js"
}

配置后,Next.js会自动加载browser入口,无需手动指定路径。

3. 备选方案:Next.js侧临时兼容(不推荐)

如果暂时无法修改组件库打包逻辑,可以在Next.js的next.config.js中配置忽略Node内置模块解析,但可能引发其他潜在问题:

module.exports = {
  webpack: (config) => {
    config.resolve.fallback = {
      ...config.resolve.fallback,
      async_hooks: false,
      fs: false,
      dns: false,
      // 其他报错的Node内置模块
    };
    return config;
  },
};

内容的提问来源于stack exchange,提问作者Panhaboth K

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 05:23:14