React设计系统组件库引入图标懒加载后,消费应用出现大量.d.ts文件构建错误的问题求助
我正在开发一个React设计系统组件库,之前发现有些组件把所有.svg文件都打包进了产物里,导致包体积达到了4mb。
后来我在Icon组件里引入了图标懒加载,这是唯一的改动,现在包体积降到了1mb👇

但奇怪的是,当我在消费应用里升级到新版本后,终端出现了大量关于.d.ts文件的错误,虽然应用在浏览器里能正常运行,但CI构建会报错,错误数量甚至超过300个。
ERROR in ./node_modules/@company/package/dist/components/radio/icons/index.d.ts
1:0-54 Module not found: Error: Can't resolve './radio-off.svg' in 'PATH_TO_PACKAGE' Did you miss the leading dot in 'resolve.extensions'? Did you mean "[".",".wasm",".mjs",".js",".jsx",".json",".ts",".tsx"]" instead of "[".",".wasm",".mjs",".js",".jsx",".json",".ts",".tsx"]"?
ERROR in ./node_modules/@company/mypackagename/dist/types/data-activation-api.d.ts
5:7 Module parse failed: Unexpected token (5:7) You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. | * Do not make direct changes to the file. | */export interface paths { | '/organization/{orgId}/data-set/{dataSetId}/traversal/{traversalId}/status': { | parameters: {
ERROR in ./node_modules/@company/mypackagename/dist/types/data-catalog-api.d.ts
5:7 Module parse failed: Unexpected token (5:7) You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. | * Do not make direct changes to the file. | */export interface paths { | '/organization/{organizationId}/entity/{entityId}/data-fields/{fieldId}': { | parameters: {
ERROR in ./node_modules/@company/mypackagename/dist/types/data-integration-api.d.ts
5:7 Module parse failed: Unexpected token (5:7) You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. | * Do not make direct changes to the file. | */export interface paths { | '/api/v1/integrations/datasources': { | parameters: {
ERROR in ./node_modules/@company/mypackagename/dist/types/theme-interfaces.d.ts
2:12 Module parse failed: Unexpected token (2:12) You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. | import '@mui/material/styles';import type { spacingScale, unitsScale } from 'theme'; | declare module '@mui/material/styles' { | interface TypeText {
再次强调一下,唯一的改动就是Icon.tsx里的懒加载逻辑(就是截图里的变更)。
下面是我的组件库配置文件:
tsconfig.json
{ "compilerOptions": { "baseUrl": ".", "target": "es6", "lib": ["dom", "dom.iterable", "esnext"], "allowJs": true, "skipLibCheck": true, "strict": true, "declaration": true, "outDir": "./dist", "rootDir": ".", "declarationDir": "./dist", "forceConsistentCasingInFileNames": true, "esModuleInterop": true, "module": "esnext", "moduleResolution": "node", "resolveJsonModule": true, "isolatedModules": true, "sourceMap": true, "declarationMap": true, "jsx": "react-jsx", "incremental": false, "paths": { "components/*": ["components/*"], "images/*": ["images/*"], "theme/*": ["theme/*"], "types/*": ["types/*"], "utils/*": ["utils/*"], }, "plugins": [] }, "include": ["**/*.ts", "**/*.tsx"], "exclude": ["node_modules", "dist"] }
webpack.config.js
const path = require('path'); const glob = require('glob'); const TerserPlugin = require('terser-webpack-plugin'); const { CleanWebpackPlugin } = require('clean-webpack-plugin'); const { getEntries } = require('./getEntries'); module.exports = { entry: getEntries(), mode: 'production', output: { path: path.resolve(__dirname, 'dist'), filename: (pathData) => { const name = pathData.chunk.name; if (name === 'theme') { return 'theme/index.js'; } return `${name}.js`; }, libraryTarget: 'module', globalObject: 'this', }, module: { rules: [ { test: /\.(ts|tsx)$/, exclude: /node_modules/, use: { loader: 'babel-loader', }, }, { test: /\.css$/, use: ['style-loader', 'css-loader'], }, { test: /\.svg$/, use: [ { loader: '@svgr/webpack', options: { typescript: true, ref: true, svgProps: { role: 'img', width: '24', height: '24', fill: 'currentColor', }, }, }, ], }, ], }, resolve: { extensions: ['.ts', '.tsx', '.js', '.jsx'], alias: { components: path.resolve(__dirname, 'components'), theme: path.resolve(__dirname, 'theme'), images: path.resolve(__dirname, 'images'), types: path.resolve(__dirname, 'types'), }, }, externals: { react: 'react', 'react-dom': 'react-dom', '@mui/material': '@mui/material', '@mui/material/styles': '@mui/material/styles', '@emotion/react': '@emotion/react', '@emotion/styled': '@emotion/styled', next: 'next', }, optimization: { minimizer: [ new TerserPlugin(), ], }, plugins: [new CleanWebpackPlugin()], experiments: { outputModule: true, }, };
.babelrc
{ "presets": [ "@babel/preset-env", [ "@babel/preset-react", { "runtime": "automatic" } ], "@babel/preset-typescript" ] }
我完全搞不懂为什么这样一个改动会引发这么多错误。而且更奇怪的是,消费应用实际运行是正常的,只是终端会报这些错误,CI构建也会失败。
我知道可以在消费应用里添加这样的配置来解决:
{ test: /\.d\.ts$/, loader: 'ignore-loader', },
但我不想强迫组件库的用户做这种配置 workaround,希望能在组件库端解决问题。
我对比了新旧版本的包,主要区别就是多了一个.mjs文件,这应该是懒加载带来的正常产物。
备注:内容来源于stack exchange,提问作者marcus-linmarkson




