React-import-component v6 - это первая библиотека для разделения кода с открытым API хуков, а также первая, совместимая с Create-React-App, благодаря babel поддержка макросов.

Корабль упакован всем, что вам может понадобиться: расширенным, а также простым API, поддержкой рендеринга на стороне сервера, оптимизацией загрузки и может справиться с любым случаем. Вот сравнительная таблица:

Готовый? Прыгай!



useImported хук

Ленивая загрузка - это не только React.lazy и Components - за любым вариантом нет ничего, кроме динамического import, который может загружать абсолютно все. И все, что вам нужно, - это правильная «интеграция с React» для управления состояниями загрузки.

// a STATIC table with imports
const languages = {
  'en': () => import('./i18n/en'), // it's probably a json...
  'de': () => import('./i18n/de'),
}
// just a helper function
const pickLanguage = (lng) => languages[lng];
// your component
const MyI18nProvider = ({lng, children}) => {
  // let's pick and provide correct import function for our language
  const {
   imported: messages = {} // defaulting to empty object
  } = useImported(pickLanguage(lng));
  // set messages to the Provider
  return <I18nProvider value={messages}>{children}</I18nProvider>
}

Это все. После рендеринга этого компонента требуемый язык будет импортирован и предоставлен в контекст. У вас действительно есть выбор, как обрабатывать состояния загрузки - путем установки значения default, перехода к ближайшему Suspense или отображения чего-то еще. Это крючок - делай, что хочешь.

useImported может загружать все, что вы хотите, и любой другой API, предоставляемый react-imported-component, построен на этом.

importModule и ImportedModule

useImported - не всегда лучший выбор, иногда может быть предпочтительнее что-то более декларативное. Вы знаете, декларативно это то, для чего нам нравится React.
Итак, есть помощник для импорта всего, что вы хотите, через интерфейс react render props. Для большинства этот шаблон более известен как loadable.lib (однако впервые он был введен для импорта).

import {importedModule, ImportedModule} from 'react-imported-component';
// you can use it to codesplit and  use `momentjs`, no offence :)
const Moment = importedModule(() => import('moment'));
<Moment fallback="long time ago">
  {(momentjs /* default imports are auto-imported*/) => momentjs(date).fromNow()}
</Moment>
// or, again, translations
<ImportedModule
 import={() => import('./i18n/en')}
 // fallback="..." // will throw to the Suspense boundary without fallback provided
>
 {(messages) => <I18nProvider value={messages}>{children}</I18nProvider> }
</ImportedModule>

импортированный и ленивый

Также есть два «общих» API - imported и lazy.
Где lazy - крякает, как React.lazy, а ленив в производстве, а imported - это, в общем, старое добро, импортированное с совместимым с API с первым поколением библиотек разделения кода.

const Component = importedComponent( () => import('./Component'), {
  LoadingComponent: Spinner, // what to display during the loading
  ErrorComponent: FatalError // what to display in case of error
});
Component.preload(); // force preload
// render it
<Component... />

Дополнительные вещи

Поддержка Create React App

Есть 3 вещи, которые вам следует знать о CRA:

  • сложно изменить конфигурацию вашего проекта, и вам рекомендуется не делать этого
  • он поддерживает SSR или предварительную визуализацию
  • это немного усложняет лучшее разбиение кода

Однако, в то время как другие дружественные к SSR решения для разделения кода требуют для работы подключаемых модулей babel и webpack - react-imported-component ничего не требуется от webpack, он не зависит от сборщика и обеспечивает Макрос бабеля, единственное, что работает "из коробки" с CRA.

Просто используйте react-imported-component/macro и закончите

import {imported} from "react-imported-component/macro";
imported(()=>import('./aGoodDay'));

Не стесняйтесь использовать макрос и в любом другом случае - они намного удобнее, чем использование плагинов babel, и сделают ваш код более переносимым и многоразовым.

Независимость от упаковщика

Это снова означает 3 разные вещи:

  • это совместимый с пакетом пакетов, или накопительный пакет, или systemjs. Неважно, какой бандлер вы используете - они будут играть вместе.
  • это реагирующий моментально - совместимый. Отслеживание использования никогда не прекращается, и после рендеринга вашей страницы в безголовом браузере вы можете спросить его - какие фрагменты вам нужно снова отобразить и получить список. (подробности см. в документации по реагированию).
  • он работает с неуправляемым «реальным» imports. Я имею в виду нетранслируемый импорт es, который вы можете использовать с настоящими модулями ESM. Это в принципе не имеет значения.
  • это было не так эффективно, как другие решения для разделения кода с более глубокой интеграцией бункеров, поэтому они могли сбрасывать использованные фрагменты во время SSR. И, как я уже сказал - было.

Загрузка оркестровки

Первый способ ускорить регидратацию скрипта - сделать процесс загрузки более эффективным. imported-component предоставляет отдельную точку входа - /boot для запуска процесса инициализации до оценки основного сценария, таким образом загружая отложенные сценарии немного «раньше». Отличное решение для CRA или Parcel, где вы можете не знать настоящих имен файлов фрагментов (без установленных дополнительных плагинов) для встраивания в HTML.

import "../async-requires";
import {injectLoadableTracker} from "react-imported-component/boot";
// ^ just 1kb
// injects runtime
injectLoadableTracker('importedMarks');

// give browser a tick to kick off script loading
Promise.resolve().then(() =>
  Promise.resolve().then(() => { 
    // the rest of your application
    // imported with a little "pause"
    require('./main')
  })
);

Это работает довольно просто и что интересно - ваши js были проанализированы, оценены, но не выполнены полностью. Затем imported запустит загрузку фрагментов, необходимых для рендеринга страницы, а затем ваше приложение продолжит выполнение.

Позвольте мне предоставить два снимка маяка (4-кратное замедление, пакет JS 3 МБ), чтобы объяснить идею:

  • требуя main в «двойном обещании», как в примере выше

  • не требует main в обещании, как в приведенном выше примере (просто переместил его в catch, поэтому он не был выполнен. Однако весь код все еще находится в пакете)

Итак - нам нужно 4200 мс для синтаксического анализа и выполнения всего скрипта и всего 400 мс для достижения «начального фрагмента» (не забывайте, что мы говорим о замедлении в 6 раз). Это дает 3800 секунд для загрузки других необходимых фрагментов. Ну бесплатно.

Вот диаграмма пламени, чтобы объяснить эту огромную разницу. Это «Первый», где левая часть - «начальный кусок», а правая - «двойное обещание».

Обратите внимание на небольшой «временной интервал» слева и микрозадачи, предоставленные браузеру для запуска сетевых операций справа.

После того, как браузеру будет дано время выполнить свою работу и начать обработку новых запросов, выполнение продолжается - вот «первый» и «второй» блоки.

И обратите внимание, насколько маленьким был этот первый «тайм-бокс».

Это делает все эти вещи, такие как предварительная загрузка и предварительная выборка скриптов, не столь важными - было бы лучше с ними, но было бы неплохо и без них. Так что у вас может быть хороший SSR с CRA из коробки. Или хороший CRS, с некоторым прогнозированием и предзагрузкой.

Если не хорошо, то лучше ...

Глубокая интеграция с Webpack

Однако для получения наилучших результатов требуется более детальный подход. И еще одно изменение для v6 - отдельный пакет для интеграции с webpack - может помочь. Названо совершенно очевидно:



Плагин webpack для сбора данных и серверный API, включая (необязательно) привязку React, чтобы обрабатывать все из коробки.

import importedData from 'build/imported.json';
<WebpackImport
   stats={importedData}
   chunks={getMarkedChunks(marks)}
   publicPath={importedData.config.publicPath}
   crossOrigin={CDN_ANONYMOUS}
/>

CSS

И CSS также обрабатывается наилучшим образом - с извлечением критического стиля, работающим из коробки для простых файлов CSS.



Все вышеперечисленные библиотеки были протестированы вместе, и они очень хорошо играли вместе.

Потоковая передача

Все используемые библиотеки имеют удобный для Streamig API и могут обеспечить наилучший TTFB, который вы ищете.

Почему почему почему

Если вы ищете ответы, почему нужно разделить код, что разделить и когда разделить код, а также как оптимизировать доставку JS или CSS.



✂️ Разделение кода - Что, когда и почему
Что? Буквально «что
- вещь и обычно компонент. Что еще вы могли бы пожелать? Когда? Намного труднее… dev.to »







Заключение

  • хуки API
  • загрузка модулей
  • загрузка компонентов
  • с отслеживанием на стороне сервера
  • поддержка макросов babel
  • не привязан к веб-пакету, но лучшая в своем классе поддержка для более глубокой интеграции с браузером
  • строим специально для вас!

👉 https://github.com/theKashey/react-imported-component