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

为何自研npm包thomasop-form在React可用,Next.js中报ReferenceError错误?

解决thomasop-form包在Next.js中ReferenceError: exports is not defined的问题

这个错误本质是模块格式不兼容:你的包目前应该是输出CommonJS格式,而Next.js的客户端组件环境(尤其是App Router)对CommonJS的支持有限,导致浏览器环境识别不了exports变量。下面是具体的修复方案:

一、调整npm包的核心配置(从根源解决)

1. 更新package.json的模块声明

打开你包根目录的package.json,添加/修改以下字段:

{
  "type": "module", // 声明包使用ES模块
  "main": "./dist/index.cjs", // CommonJS入口
  "module": "./dist/index.js", // ES模块入口
  "types": "./dist/index.d.ts", // 类型文件入口(如果用TS)
  "exports": {
    ".": {
      "import": "./dist/index.js",
      "require": "./dist/index.cjs"
    }
  }
}

exports字段是Node.js推荐的模块入口配置,能让不同环境(ES模块/CommonJS)自动匹配对应的文件。

2. 调整打包工具配置(以Rollup为例)

如果用Rollup打包,修改rollup.config.js,同时输出ES和CommonJS两种格式:

import babel from '@rollup/plugin-babel';
import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import typescript from '@rollup/plugin-typescript';

export default {
  input: 'src/index.ts', // 你的源码入口
  output: [
    {
      file: 'dist/index.js',
      format: 'esm', // ES模块格式
      sourcemap: true
    },
    {
      file: 'dist/index.cjs',
      format: 'cjs', // CommonJS格式
      sourcemap: true,
      exports: 'named' // 导出命名成员
    }
  ],
  plugins: [
    resolve(),
    commonjs(),
    typescript(), // 如果用TS,确保配置tsconfig.json
    babel({
      exclude: 'node_modules/**',
      presets: ['@babel/preset-react', '@babel/preset-env']
    })
  ],
  external: ['react', 'react-dom'] // 排除React依赖,让用户自己提供
};

如果用Webpack,也要配置多输出格式,确保同时生成.js(ESM)和.cjs(CJS)文件。

3. 统一代码中的导出方式

检查你的组件代码,确保用ES模块的导出语法:

// 正确:ES模块导出
export const Container = () => { /* ... */ };
export const Form = () => { /* ... */ };

// 避免:CommonJS导出
// module.exports = { Container, Form };

二、Next.js项目中的临时兼容方案(无需改包)

如果暂时不想修改包的配置,可以在Next.js中用动态导入的方式加载你的包,禁用SSR:

'use client';
import { useState } from 'react';
import dynamic from 'next/dynamic';

// 动态导入,禁用服务端渲染
const { Container, Form, TextField } = dynamic(
  () => import('thomasop-form'),
  { ssr: false }
);

export default function Page() {
  const [value, setValue] = useState();
  return (
    <>
      <Container>
        <Form
          method={"GET"}
          url={"https://jsonplaceholder.typicode.com/posts"}
          setValue={setValue}
        >
          <TextField name={"firstname"} required={true} regex={/^[0-9]$/} />
          <TextField name={"lastname"} />
        </Form>
      </Container>
    </>
  );
}

这种方式让组件只在浏览器端加载,避开服务端的CommonJS兼容性问题,但不是长久之计,还是建议从包本身调整配置。

三、验证修复效果

  1. 重新打包你的npm包:运行npm run build(确保打包脚本指向你配置的打包工具)
  2. 在本地测试:用npm link把包链接到Next.js项目中,验证是否还会报错
  3. 发布新版本:修改package.json的版本号后,运行npm publish

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 19:47:23