Примечание. С момента написания этой статьи многое изменилось. file-loader и url-loader теперь не поддерживают отправку файлов, поэтому fake-file-loader и fake-url -loader устарели. fake-style-loader можно заменить с помощью css-loader / locals, как описано в fake-style-loader # 3. Поэтому больше не используйте семейство модулей fake. Вместо этого рекомендуется использовать css-loader, file-loader и url-loader.

Все же стоит прочитать статью, чтобы ознакомиться с концепциями.

Webpack обычно используется для создания клиентского пакета веб-приложений. Чтобы улучшить воспринимаемое время загрузки, веб-приложения могут отображаться на сервере. В идеале код для компонентов, используемых веб-приложением, должен совместно использоваться кодом, генерирующим пакет клиента и сервера. Обычно для этого используются две отдельные конфигурации Webpack, где каждая импортированная зависимость компонента интерпретируется по-разному в зависимости от того, создает ли Webpack в настоящее время пакет клиента или сервера.

При импорте изображения из компонента Webpack обычно передает изображение в активы и разрешает импорт с URL-адресом отправленного файла. Это также верно для других ресурсов, таких как файлы CSS и шрифты. Если бы мы сейчас просто добавили ту же конфигурацию для пакета сервера, Webpack генерировал бы файлы дважды, что могло привести к другим URL-адресам. Это больше работы и без надобности увеличивает время сборки. Разметка, созданная во время SSR, может тогда отличаться от разметки, созданной браузером, из-за разных URL-адресов, и React будет жаловаться.

Другим исключением является загрузчик стилей, который прикрепляет импортированные таблицы стилей к модели DOM. При рендеринге на сервере DOM отсутствует, поэтому возникает исключение.

Одно из существующих решений - webpack-isomorphic-tools, но я обнаружил, что это очень сложно настроить, хотя, похоже, оно обладает большой мощностью. Я не мог заставить его работать должным образом и в конце концов сдался.

Решение

В загрузчике файлов есть флаг emitFile. Если этот параметр включен, загрузчик файлов пропустит выброс ресурса и просто вернет сгенерированное имя файла. Поскольку url-loader использует file-loader за кулисами, там можно использовать тот же флаг. Таким образом, вы должны использовать обычный загрузчик файлов для клиентского пакета и добавить emitFile = false в конфигурацию сервера Webpack. Это решает проблему для статических активов.

Однако для стилей это пока не работает.

Представляем фальшивый загрузчик

fake-style-loader позволяет загружать модули CSS на сервер. Он возвращает имена сгенерированных идентификаторов и, кроме того, обеспечивает доступ к базовому CSS, чтобы его можно было обслуживать в оперативном режиме (или извлекать в файл).

Https://www.npmjs.com/package/fake-style-loader

Из документации по style-loader webpack:

При использовании CSS с локальной областью видимости модуль экспортирует сгенерированные идентификаторы.

var style = require (style! css! ./ file.css);
style.placeholder1 === z849f98ca812bc0d099a43e0f90184

Чтобы включить загрузку модулей CSS на сервер, нам не нужен волшебный загрузчик стилей attach style-tags-to-DOM, потому что DOM отсутствует. Вместо этого нам просто нужно знать имена идентификаторов.

Намерение состоит в том, чтобы использовать обычный style-loader для клиентского пакета и fake-style-loader для серверного пакета. Теперь будет только один отправленный файл, но экспортированные URL-адреса будут доступны для обоих пакетов. Так же, как с загрузчиком файлов и загрузчиком URL. Вот пример двух конфигураций Webpack:

// regular style-loader for client bundle
{ test: /\.css$/, loader: 'style!css?modules' },
// fake-loader for server bundle
{ test: /\.css$/, loader: 'fake-style!css?modules' }

Примечание. В настоящее время загрузчик фальшивого стиля работает в сочетании с загрузчиком css только в режиме модулей. Нет смысла использовать его в немодульном режиме, потому что не будет возвращаемого значения.

fake-style-loader имеет еще одну возможность. Он экспортирует исходный код CSS как свойство source. Это полезно для SSR, когда вы хотите встроить исходный код CSS.

var styles = require('./some-file.css')
console.log(styles)
// returns
// {
//   // the regular classnames of css-modules
//   heading: '.XYZABC123',
//   ...
//
//   // the special source property containing the original CSS
//   source: '.heading { color: blue; }'
// }

Чтобы увидеть все это в действии, посмотрите мой проект webapp, а именно эти файлы:

Я надеюсь, что fake-style-loader и другие модули с отключенной эмиссией будут для вас столь же полезны, как и для меня. Я создал загрузчик 4 месяца назад и надолго откладывал писать о нем. По-прежнему отсутствует документация, но я надеюсь, что после написания этой статьи все прояснится.

Кроме того, webapp должен быть хорошей отправной точкой.

Удачного рендеринга на стороне сервера :)

Примечание. Ранее было невозможно отключить выдачу ресурсов в загрузчике файлов и загрузчике URL. Это было введено совсем недавно в # 74. Тогда я создал fake-file-loader и fake-url-loader. Сейчас они считаются устаревшими, так как это возможно прямо сейчас :) Также рекомендуется использовать css-loader / locals вместо fake-style-loader. См. Fake-style-loader # 3 для получения дополнительной информации.

Дальнейшее чтение: