主React应用无法导入外部NextJS设计系统JSX/TSX组件问题咨询
解答
先直接给三个疑问的明确结论:
- 不需要把设计系统改写成类组件,也不需要放弃TS。函数组件是React 17原生支持的写法,和主应用现存的类组件完全可以混用,不存在兼容问题;TS仅在开发阶段做类型校验,编译后输出标准JS,主应用不接入TS也能正常调用。
- 不建议修改主应用配置直接编译外部TSX/JSX源码,这种方案维护成本极高,会和react-scripts内置的webpack、babel配置产生大量冲突,还会大幅拖慢主应用的编译速度。
- 不需要舍弃NextJS、用CRA从零重搭设计系统。你只需要给现有Next项目增加组件库构建能力,输出编译后的标准JS产物即可,之前写的所有组件代码都可以直接复用,零迁移成本。
报错根本原因
你遇到的两类报错本质是同一个问题:通过npm link直接引入的是设计系统的原始TSX/JSX源码,而react-scripts创建的项目默认不会编译node_modules目录下的文件,只会处理src目录内的业务代码:
- 导入TSX报模块找不到:主应用本身未使用TS,内置webpack没有配置.tsx后缀的解析规则,也不会遍历node_modules下的TSX文件,自然无法识别对应模块。
- 导入JSX报语法错误:主应用的babel-loader默认跳过node_modules目录下的文件,拿到JSX里的
<div>等标签时直接按普通JS语法解析,就会抛出Unexpected token的错误。
另外你之前执行的next build命令对组件复用没有作用,这个命令是用来构建NextJS全栈应用的页面前后端产物,输出的文件结构是为Next运行时设计的,不能作为独立组件库被外部项目引入。
落地实现方案
优先选择第一种方案,改造成本最低,10分钟就能搞定:
方案1:给现有NextJS项目增加组件库构建配置(推荐)
不需要改动任何已写好的组件、页面代码,只需要加独立的组件构建入口,用tsup打包输出可复用产物即可,步骤如下:
- 在设计系统项目根目录安装构建工具:
npm i tsup -D - 新建组件统一出口文件
src/index.ts,把所有需要对外暴露的组件从这个文件导出:export { default as SearchBar } from './components/SearchBar' export { default as Test } from './components/Test' // 后续新增给主应用用的组件,都在这里追加导出 - 修改设计系统的
package.json,增加组件库相关配置:
配置里加{ "main": "./dist/index.js", "module": "./dist/index.mjs", "types": "./dist/index.d.ts", "files": ["dist"], "peerDependencies": { "react": ">=17.0.0", "react-dom": ">=17.0.0" }, "scripts": { "build:lib": "tsup src/index.ts --format esm,cjs --dts --external react,react-dom" } }--external react,react-dom是为了不把React源码打包进组件库,直接复用主应用的React实例,避免多React副本导致的hooks报错、上下文失效问题。 - 执行
npm run build:lib,会自动在dist目录生成编译好的ESModule、CommonJS格式的JS文件,以及TS类型声明文件。 - 保持npm link的链接状态,主应用里直接按包名导入即可:
import { SearchBar, Test } from 'design-system',不需要写深层组件路径,也不会再出现语法解析错误。
注意三个细节:
- 把设计系统package.json里的react、react-dom依赖版本调整为和主应用一致的17.x版本,避免版本不兼容问题。
- 你现有的tsconfig.json是NextJS默认生成的,不需要做任何修改,tsup会自动适配TS配置,不会影响NextJS本身的开发、构建流程。
- 如果你用TailwindCSS写组件样式,只需要在主应用里安装TailwindCSS,把设计系统的组件目录加到tailwind.config.js的content配置数组里,就能正常加载样式,不需要把CSS单独打包进组件库。
方案2:抽离独立组件包
如果不想在NextJS项目里混放组件库构建配置,不需要重写组件代码,只需要把components目录单独抽成一个独立的npm包目录,沿用上面的tsup配置构建即可。抽离后NextJS项目本身也可以引用这个本地包的组件,不影响你原来的设计系统文档、演示页面开发。
认知误区澄清
- 函数组件和类组件在React应用里可以自由混用,不存在互斥问题,主应用全用类组件完全不影响你导入、使用函数组件。
- TS是开发阶段的类型工具,编译后就是普通JavaScript代码,不需要主应用支持TS就能正常运行。
- React组件库的本质是输出可执行的标准JS代码,和你开发时用的脚手架(Next/CRA/Vite等)没有绑定关系,不需要为了做组件库换脚手架重写已有代码。
- 不要尝试修改react-scripts的配置让它编译node_modules里的源码,react-scripts本身是封装好的黑盒,要改webpack配置要么eject弹出所有配置,要么用第三方工具覆写,后续升级依赖会非常麻烦;而且编译node_modules会让本地启动、热更新的速度下降数倍,完全得不偿失。
内容的提问来源于stack exchange,提问作者Keanu Kent Gargar
相关产品推荐
相关产品推荐

