Невозможно использовать React.lazy с иконками пользовательского интерфейса. - PullRequest
0 голосов
/ 23 февраля 2019

, поскольку в моем приложении довольно много значков, я хочу использовать для них разделение кода.

Я создал вспомогательный компонент для этого:

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, однако, как только я изменяю ее на строку выше, веб-пакет падает во время компиляции с ошибкой низкого уровня:

69% сборок 15623/15657 модулей 34 активных ... terial-ui / icons / AccessibleOutlined.d.ts <--- Последние несколько сборщиков мусора --->

[30: 0x33f4320] 77272 мс: Scavenge 1142,0 (1422,8) -> 1141,5 (1423,3) МБ, 1,4 / 0,0 мс (среднее значение mu = 0,300, текущее значение mu = 0,342), ошибка выделения [30: 0x33f4320] 77275 мс: Scavenge 1142,3 (1423,3) -> 1141,7 (1423,8)MB, 1,5 / 0,0 мс (среднее значение mu = 0,300, текущее значение mu = 0,342), ошибка выделения [30: 0x33f4320] 77278 мс: Scavenge 1142,4 (1423,8) -> 1141,9 (1424,3) МБ, 1,5 / 0,0 мс (среднее значение mu = 0,300,текущий mu = 0,342) ошибка выделения

<--- трассировка стека JS --->

==== Трассировка стека JS ==============================================

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

0x1c000787d3b1>) 2: новый набор (ака Set) [0x2fea7a90391] (это = 0x056d59402691, 0x33036eb7fbe1) 3: ConstructFrame [ПК: 0x16ac48009e66] 4: StubFrame [ПК: 0x16ac480f932c] 5: processDependenciesBlocksForC... 70% порция graphFATAL ERROR: неэффективные сжатые метки вблизи предела кучи Выделение не удалось - куча JavaScript не хватает памяти 1: 0x948d20 узел :: 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 (без знака long, double) [/ usr / local / bin / node] 7: 0xf1a718 v8 :: internal :: Heap :: PerformGarbageCollection (v8:: internal :: GarbageCollector, v8 :: GCCallbackFотстает) [/ 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 :: Обрабатывать 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 :: Изолировать *, 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 Прервано (ядро сброшено)

Мои плагины 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',

Из того, что я вижу, он пытается загрузить все значки, а не толькоодин (я сократил использованный экземпляр до одного, чтобы найти решение проще), а затем он падает.

ОБНОВЛЕНИЕ

Точно так же происходит, если я пытаюсь использовать react-loadable ...


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

1 Ответ

0 голосов
/ 23 февраля 2019

Если вы используете Webpack, проблема заключается в том, что если вы хотите динамически загрузить файл, в этом случае значок webpack по умолчанию создает чанк для этого модуля.Если вы используете Webpack 4 или более поздней версии, вы можете использовать webpackMode: eager для решения этой проблемы.Таким образом, в этом случае импорт будет выглядеть примерно так:

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

Это в основном заставит Webpack включить чанк в ваш пакет (уменьшив количество запросов http) - который, я думаю, отрисовывает всеТочка использования Lazy / Suspense бесполезна, но эта проблема Github похожа на вашу проблему и указывает, что не стоит загружать каждый значок отдельно, т.е. вам лучше импортировать пакет @material-ui/icons и использовать значкичто вам нужно.

ОБНОВЛЕНИЕ (из-за рассматриваемого обновления со ссылкой на react-loader):

При использовании react-loader вам также необходимо указать расширениефайл.Я однажды сталкивался с этой проблемой и решил ее, импортировав с расширением для указанного файла.В этом случае:

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

Но я не уверен, будет ли он работать, как я уже предлагал в своем ответе относительно Webpack и отложенной загрузки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...