提问者:小点点

无法将React.lazy与材质UI图标一起使用


由于我的应用程序中有很多图标,我想对它们使用代码分割。

为此,我创建了助手组件:

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>
  });

共1个答案

匿名用户

如果您使用的是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 和延迟加载的回答中已经建议的那样。