Cannot use React.lazy with Material UI icons

旧城冷巷雨未停 提交于 2021-02-07 20:35:04

问题


as I have quite a lot of icons in many places in my app, I want to use code splitting for them.

I have created helper component to do that:

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

When I use commented line with fixed name to Home it works and it lazy loads the Home icon, however as soon as I change it to the line above, webpack crashes during compilation with low level error:

69% building 15623/15657 modules 34 active ...terial-ui/icons/AccessibleOutlined.d.ts <--- Last few GCs --->

[30:0x33f4320] 77272 ms: Scavenge 1142.0 (1422.8) -> 1141.5 (1423.3) MB, 1.4 / 0.0 ms (average mu = 0.300, current mu = 0.342) allocation failure [30:0x33f4320] 77275 ms: Scavenge 1142.3 (1423.3) -> 1141.7 (1423.8) MB, 1.5 / 0.0 ms (average mu = 0.300, current mu = 0.342) allocation failure [30:0x33f4320] 77278 ms: Scavenge 1142.4 (1423.8) -> 1141.9 (1424.3) MB, 1.5 / 0.0 ms (average mu = 0.300, current mu = 0.342) allocation failure

<--- JS stacktrace --->

==== JS stack trace =========================================

0: ExitFrame [pc: 0x16ac4804fb5d] Security context: 0x02fea7a9d921 <JSObject>
1: add [0x2fea7a906c9](this=0x10fbf120c2e1 <Set map = 0x3f914303d81>,0x1a97709947e1 <DependenciesBlock map =

0x1c000787d3b1>) 2: new Set(aka Set) [0x2fea7a90391](this=0x056d59402691 ,0x33036eb7fbe1 ) 3: ConstructFrame [pc: 0x16ac48009e66] 4: StubFrame [pc: 0x16ac480f932c] 5: processDependenciesBlocksForC... 70% chunk graphFATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory 1: 0x948d20 node::Abort() [/usr/local/bin/node] 2: 0x9499bc node::OnFatalError(char const*, char const*) [/usr/local/bin/node] 3: 0xb1160e v8::Utils::ReportOOMFailure(v8::internal::Isolate*, char const*, bool) [/usr/local/bin/node] 4: 0xb11844 v8::internal::V8::FatalProcessOutOfMemory(v8::internal::Isolate*, char const*, bool) [/usr/local/bin/node] 5: 0xf0def2 [/usr/local/bin/node] 6: 0xf0dff8 v8::internal::Heap::CheckIneffectiveMarkCompact(unsigned long, double) [/usr/local/bin/node] 7: 0xf1a718 v8::internal::Heap::PerformGarbageCollection(v8::internal::GarbageCollector, v8::GCCallbackFlags) [/usr/local/bin/node] 8: 0xf1b22b v8::internal::Heap::CollectGarbage(v8::internal::AllocationSpace, v8::internal::GarbageCollectionReason, v8::GCCallbackFlags) [/usr/local/bin/node] 9: 0xf1df61 v8::internal::Heap::AllocateRawWithRetryOrFail(int, v8::internal::AllocationSpace, v8::internal::AllocationAlignment) [/usr/local/bin/node] 10: 0xee7e96 v8::internal::Factory::AllocateRawArray(int, v8::internal::PretenureFlag) [/usr/local/bin/node] 11: 0xee885a v8::internal::Factory::NewFixedArrayWithFiller(v8::internal::Heap::RootListIndex, int, v8::internal::Object*, v8::internal::PretenureFlag) [/usr/local/bin/node] 12: 0xee8900 v8::internal::Handle v8::internal::Factory::NewFixedArrayWithMap(v8::internal::Heap::RootListIndex, int, v8::internal::PretenureFlag) [/usr/local/bin/node] 13: 0x108e547 v8::internal::OrderedHashTable::Allocate(v8::internal::Isolate*, int, v8::internal::PretenureFlag) [/usr/local/bin/node] 14: 0x1091ab1 v8::internal::OrderedHashTable::Rehash(v8::internal::Isolate*, v8::internal::Handle, int) [/usr/local/bin/node] 15: 0x109202b v8::internal::OrderedHashTable::EnsureGrowable(v8::internal::Isolate*, v8::internal::Handle) [/usr/local/bin/node] 16: 0x117ee2c v8::internal::Runtime_SetGrow(int, v8::internal::Object**, v8::internal::Isolate*) [/usr/local/bin/node] 17: 0x16ac4804fb5d Aborted (core dumped)

My Babel plugins:

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',

From what I see it is trying to load all icons, not just one (I reduced the used instance to one to find the solution easier) and then it crashes.

UPDATE

Exactly the same happens if I try to use react-loadable...


return Loadable({
    loader: () => import(`@material-ui/icons/${props.name}`),
    loading: () => <span>icon</span>
  });

回答1:


If you are using Webpack, the problem is if you want to dynamic load a file, in this case the icon, webpack by default generate a chunk for that module. If you are using Webpack 4 or later, you can use webpackMode: eager to solve this problem. So, in this case, the import will look something like this :

const IconElement = React.lazy(() => import(/* webpackMode: "eager" */`@material-ui/icons/${name}`));

This will basically force Webpack to include the chunk into your bundle ( reducing the number of http requests ) - which I think renders the whole point of using Lazy / Suspense useless but this Github issue is similar to your problem and indicates that it is not worth loading each icon separately, .i.e, you should rather import the @material-ui/icons package and use the icons which you need.

UPDATE ( because of update in question with reference to react-loader ) :

While using react-loader you also need to specify the extension of the file. I had faced this issue once and solved it by importing with extension for the file specified. In this case :

return Loadable({
    loader: () => import(`@material-ui/icons/${props.name}.ts`),
    loading: () => <span>icon</span>
  });

But I am not sure if it will still work, as I already suggested in my answer regarding Webpack and lazy loading.



来源:https://stackoverflow.com/questions/54838786/cannot-use-react-lazy-with-material-ui-icons

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!