由于我的应用程序中有很多图标,我想对它们使用代码分割。
为此,我创建了助手组件:
import React, { FunctionComponent, Suspense } from 'react';
interface LazyMuiIconProps {
name: string;
}
export const LazyMuiIcon: FunctionComponent<LazyMuiIconProps> = ({ name }) => {
console.log(name);
const IconElement = React.lazy(() => import(`@material-ui/icons/${name}`));
// const IconElement = React.lazy(() => import(`@material-ui/icons/Home`));
return (
<Suspense fallback={null}>
<IconElement />
</Suspense>
);
};
当我使用带有固定名称的注释行到Home
时,它可以工作并且它会延迟加载Home图标,但是一旦我将其更改为上面的行,webpack就会在编译期间崩溃并出现低级错误:
69%的建筑15623/15657模块34活跃。。。材料ui/icons/AccessibleOutlined.ts
[30:0x33f4320] 77272 毫秒: 清除 1142.0 (1422.8) -
====JS堆栈跟踪=========================================
0: ExitFrame [pc: 0x16ac4804fb5d] Security context: 0x02fea7a9d921 <JSObject>
1: add [0x2fea7a906c9](this=0x10fbf120c2e1 <Set map = 0x3f914303d81>,0x1a97709947e1 <DependenciesBlock map =
0x1c000787d3b1
我的 Babel 插件:
plugins: [
// plugin-proposal-decorators is only needed if you're using experimental decorators in TypeScript
"@babel/plugin-syntax-dynamic-import",
['@babel/plugin-proposal-decorators', { legacy: true }],
['@babel/plugin-proposal-class-properties', { loose: true }],
'react-hot-loader/babel',
据我所知,它正在尝试加载所有图标,而不仅仅是一个(我将使用的实例减少到一个以更轻松地找到解决方案),然后它崩溃了。
更新
如果我尝试使用< code>react-loadable,会发生完全相同的情况...
return Loadable({
loader: () => import(`@material-ui/icons/${props.name}`),
loading: () => <span>icon</span>
});
如果您使用的是Webpack,问题是如果您想动态加载一个文件,在这种情况下是图标,webpack默认为该模块生成一个块。如果您使用的是Webpack 4或更高版本,您可以使用webpackMode:渴望
来解决这个问题。所以,在这种情况下,导入将如下所示:
const IconElement = React.lazy(() => import(/* webpackMode: "eager" */`@material-ui/icons/${name}`));
这将基本上迫使Webpack将块包含到您的捆绑包中(减少http请求的数量)-我认为这会使使用Lazy/Ssuspense的整个要点变得无用,但Github问题与您的问题类似,表明不值得单独加载每个图标,即,您应该导入@materialui/icons
包并使用所需的图标。
更新(因为与< code>react-loader相关的更新) :
使用react loader
时,还需要指定文件的扩展名。我曾经遇到过这个问题,并通过导入指定文件的扩展名来解决它。在这种情况下:
return Loadable({
loader: () => import(`@material-ui/icons/${props.name}.ts`),
loading: () => <span>icon</span>
});
但我不确定它是否仍然有效,正如我在关于 Webpack 和延迟加载的回答中已经建议的那样。