React+Vite设计系统作为Git子模块导入时interface解析错误求助
解决Git子模块中React+Vite设计系统的TypeScript转译错误
问题描述
将基于React+Vite开发的设计系统作为Git子模块导入其他项目后,使用组件时抛出如下错误:
ERROR in ./packages/MightZord-DS/src/components/Switch/index.tsx 9:0 Module parse failed: The keyword 'interface' is reserved (9:0) File was processed with these loaders: * ./node_modules/@pmmmwh/react-refresh-webpack-plugin/loader/index.js * ./node_modules/source-map-loader/dist/cjs.js You may need an additional loader to handle the result of these loaders. | import { FieldRow } from "../Field/styles"; | > interface SwitchFieldProps { | id: string; | label: string;
原因分析
当前设计系统的配置仅适用于本地开发预览:
tsconfig.json中noEmit: true,不会生成编译后的JS文件- Vite默认构建产物是面向浏览器的应用包,而非可被其他项目引用的库文件
- 宿主项目(此处为Webpack环境)直接读取了未转译的TypeScript源码,但未配置处理该子模块目录下的TS/TSX文件,导致无法识别
interface等TS语法
解决方案
方案1:调整设计系统配置,输出可引用的库产物
这是更规范的做法,让设计系统输出编译后的JS和类型文件,避免宿主项目处理TS源码。
- 修改
tsconfig.json
更新编译配置,开启类型声明生成,指定输出目录:
{ "compilerOptions": { "target": "ESNext", "useDefineForClassFields": true, "lib": ["DOM", "DOM.Iterable", "ESNext"], "allowJs": false, "skipLibCheck": true, "esModuleInterop": false, "allowSyntheticDefaultImports": true, "strict": true, "forceConsistentCasingInFileNames": true, "module": "ESNext", "moduleResolution": "Node", "resolveJsonModule": true, "isolatedModules": true, "noEmit": false, // 改为false,允许生成编译文件 "declaration": true, // 生成.d.ts类型文件 "declarationDir": "./dist", // 类型文件输出目录 "outDir": "./dist", // JS文件输出目录 "rootDir": "./src", // 源码根目录 "jsx": "react" }, "include": ["src"], "references": [{ "path": "./tsconfig.node.json" }] }
- 修改
vite.config.ts配置为库模式
让Vite构建出适合被其他项目引用的库产物:
import { defineConfig } from 'vite' import react from '@vitejs/plugin-react' export default defineConfig({ plugins: [react()], build: { lib: { entry: './index.ts', // 入口文件 name: 'MightZordDS', fileName: (format) => `mightzord-ds.${format}.js`, }, rollupOptions: { // 排除宿主项目已有的依赖,避免重复打包 external: ['react', 'react-dom', 'styled-components', '@radix-ui/react-switch', 'polished'], output: { // 为外部依赖指定全局变量(UMD格式需要) globals: { react: 'React', 'react-dom': 'ReactDOM', 'styled-components': 'styled', '@radix-ui/react-switch': 'RadixUISwitch', polished: 'Polished' }, }, }, }, })
- 更新
package.json
添加入口字段,让其他项目能找到编译后的产物,同时取消私有限制:
{ "name": "@magazord/mightzord-ds", "private": false, // 修改为false,允许外部引用 "version": "0.0.1", // 更新版本号 "type": "module", "main": "./dist/mightzord-ds.umd.js", // UMD格式入口 "module": "./dist/mightzord-ds.es.js", // ES模块入口 "types": "./dist/index.d.ts", // 类型声明入口 "scripts": { "dev": "vite", "build": "tsc && vite build", "preview": "vite preview" }, // ... 依赖部分保持不变 }
- 构建并提交产物
执行npm run build生成dist目录,将dist目录提交到Git子模块仓库。之后宿主项目即可通过import { Switch } from '@magazord/mightzord-ds'引用组件,无需处理TS源码。
方案2:调整宿主项目Webpack配置(临时方案)
如果不想修改设计系统的构建流程,可让宿主项目的Webpack处理子模块中的TS/TSX文件:
- 安装依赖:
npm install typescript ts-loader --save-dev
- 修改宿主项目的
webpack.config.js:
const path = require('path'); module.exports = { // ... 其他配置 module: { rules: [ // 新增处理TS/TSX的规则,包含子模块目录 { test: /\.(ts|tsx)$/, include: [ path.resolve(__dirname, 'src'), path.resolve(__dirname, 'packages/MightZord-DS') // 子模块路径 ], use: 'ts-loader', }, ], }, resolve: { extensions: ['.ts', '.tsx', '.js', '.jsx'], // 添加TS扩展名 }, };
内容的提问来源于stack exchange,提问作者Gabriel Schmidt Cordeiro
相关产品推荐
相关产品推荐

