image

Полтора месяца назад создатель webpack Тобиас Копперс выпустил “Большой план” для CSS в Webpack в своей статье "Новый рабочий процесс для CSS (шаг1)".

Самый первый вывод, который можно сделать — заключался в том, что разделение кода CSS станет приоритетом первого класса. Вы сможете получить css-файлы, сгенерированные для каждого из ваших динамических фрагментов кода, а вызовы import() вернут вам 2 файла: JS + CSS.

Вот цитата из статьи:

Большой план


В долгосрочной перспективе мы хотим сделать добавить “первоклассный” модуль поддержки CSS в webpack. Он будет работать следующим образом:

  • Мы добавляем новый тип модуля в webpack: Stylesheet (рядом с Javascript)
  • Мы настраиваем шаблоны фрагментов для записи двух файлов. Один для javascript и один для таблиц стилей (в файле .css).
  • Мы настраиваем логику загрузки блока, чтобы можно было загружать таблицы стилей. Нам нужно дождаться применения CSS или, по крайней мере, его загрузки, перед выполнением JS.
  • Когда мы генерируем загрузку фрагмента кода, мы можем параллельно загружать часть js и часть таблицы стилей (в сочетании с Promise.all)

Основой, конечно же, является возможность создания CSS-файлов для каждого динамического фрагмента. В настоящее время модуль extract-text-webpack-plugin не осуществляет этого. Доступная на сегодня бета-версия 3.0 не поддерживает данного функционала. Существует конечно мой extract-css-chunks-webpack-plugin, который какое-то время находился в активном пользовании, но он недостаточно хорош. Недостаточно хорошо он потому, что компиляция выполняется медленно и не увеличивает кеширование в браузере. Причина в том, что он создает 2 разных фрагмента JS для того, что в основе всей этой идеи должно идти как неделимое целое. Эти фрагменты:

  • Один без CSS-инъекции через загрузчик стилей
  • Другой с CSS-инъекцией через загрузчик стилей

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

Предыстория


Для того, чтобы всё это имело смысл, в случае если вы впервые слышите об этом, то вам вероятнее всего будет интересна следующая статья: Code Cracked for Code-Splitting + SSR in Reactlandia: React Universal Component + Webpack Flush Chunks and more [ENG]

Если обобщить написанное в статье, упомянутой выше, есть следующие компоненты: react-universal-component и webpack-flush-chunks по средствам которых вы можете легко и универсально рендерить свое приложение одновременно с разделением кода. Впервые в качестве общедоступного пакета NPM (не требуется никаких фреймворков). Для тех, кто не в курсе, вынос заключается в следующем: рендер на стороне сервера (SSR) — это решённая проблема, разделение кода — это решённая проблема, но до этих самых пор использование обоих разом оставалось проблемой не разрешённой.

Больше не нужно жертвовать SEO / SSR для разделения кода и/или наоборот.

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

На самом деле, через статически разделяемый CSS вы отправляете меньше байтов клиентам, чем популярные решения «render path» du jour (поскольку они должны отправлять определения вашего CSS как в фрагменты JS, так и в дополнительный CSS). И, что еще важнее, это также экономит много потраченных циклов, генерирующих CSS во время рендеринга на серверной и клиентской сторонах.

Потому возможность контролировать, какие статические файлы CSS вы отправляете клиентам, действительно является хорошим способом справиться с этой проблемой.

Введение в Babel-Plugin-Dual-Import + Extract CSS Chunks Webpack Plugin 2.0


babel-plugin-dual-import преобразует ваш запрос в Promise.all и, в качестве бонуса, он автоматически выдает вам webpackChunkName. “Волшебные комментарии” настолько волшебны, что они исчезают! Разумеется, под капотом я использую их для генерации имен ваших фрагментов кода.

Что касается extract-css-chunks-webpack-plugin 2.0, я обошёл серьезную проблему производительности с точки зрения времени сборки (не более двух JS-фрагментов), и теперь все, с чем вы имеете дело, это таблицы стилей, которые браузеры ваших пользователей могут кэшировать. И да, быстрая замена модулей (HMR) все еще работает (лучше, чем когда-либо на самом деле).

Также обратите внимание: все эти четыре пакета беспрепятственно работают вместе. Я условно называю это “универсальным” семейством пакетов. Разумеется, все они могут быть индивидуально использованы, потому что это то, в чём заключается гибкая разработка фреймворков. Но естественно лучше всего работают они вместе. Наслаждайтесь.

Установка


Так как мы в первую очередь внедряем плагин babel, на том и сосредоточимся:

yarn add --dev babel-plugin-dual-import

.babelrc:

{
    "presets": [whatever you usually have],
    "plugins": ["dual-import"]
}

App.js:

import('./Foo.js')
      v v v v v v
import { importCss } from 'babel-plugin-dual-import/importCss.js'

Promise.all ( [
  import( /* webpackChunkName: 'Foo' */ './Foo'),
  importCss('Foo')
] ).then(promises => promises[0]);

И если вы используете всё это динамически, необходимо добавить:

import('../base/${page}')
      v v v v v v
import { importCss } from 'babel-plugin-dual-import/importCss.js'

Promise.all([
  import( /* webpackChunkName: 'base/[request]' */ `./base/${page}`),
  importCss(`base/${page}`)]
).then(promises => promises[0]);

Если вы ранее смотрели, как работает webpack-flush-chunks, новое дополнение — это cssHash, которое похоже на то, что webpack кладёт в bootstrap скрипт, сопоставляя фрагменты javascript с их идентификаторами. cssHash ориентирует имена фрагментов css в файлы их стилей. Babel-plugin-dynamic-import запрашивает таблицы стилей оттуда параллельно с импортом javascript.

Заключение


Не слишком много чего осталось сказать, потому git clone демо работы всех четырёх пакетов отсюда и вперёд.

Если вы совершенно не знакомы с React Universal Component + Webpack Flush Chunks, советую хотя бы просмотреть описание по диагонали. В настоящее время это единственное решение, объединяющее все это для разработчиков React, опасающихся избыточного количества фреймворков. Разработчиков, у которых были подобные проблемы, знайте, те дни закончились.



Прошу заметить, что статья является более чем актуальной и надеюсь, что её сочтут полезной даже люди, которым знакома технология применения этих четырёх пакетов. Буду признателен за любые исправления, указания на недочёты и/или информацию о том, нуждается ли habr в переводе статей, на которые ссылается автор.

Ссылки:

Поделиться с друзьями
-->

Комментарии (2)


  1. Ungla
    13.07.2017 15:00
    +1

    А причём тут Администрирование и *nix?


    1. Grinzzly
      13.07.2017 21:31

      К большому сожалению в recovery mode разрешено отправлять статьи исключительно в профильные хабы (с пометкой *). Единственным из которых на данный момент является nix.