Разное

Vue ssr: Vue.js Server-Side Rendering Guide | Vue SSR Guide

Содержание

SSR. Отрисовка на стороне сервера — Vue.js

Vue.js

  • Обучение

    • Документация
      • Руководство
      • API
      • Рекомендации
      • Примеры
      • Книга рецептов
    • Видео курсы
      • Vue Mastery

      • Vue School

  • Экосистема

    • Помощь
      • Форум
      • Чат
      • Митапы
    • Инструментарий
      • Инструменты разработчика
      • Vue CLI
      • Vue Loader
    • Официальные плагины
      • Vue Router
      • Vuex
      • Vue Server Renderer
    • Новости
      • Еженедельные новости
      • Roadmap
      • События
      • Twitter
      • Блог
      • Вакансии
      • Сообщество разработчиков
  • Команда
  • Ресурсы

    • Партнёры
    • Темы
    • Awesome Vue
    • Найти пакеты для Vue
  • Поддержать Vue

    • Единоразовые пожертвования
    • Повторяющиеся взносы
    • Магазин футболок
  • Переводы

    • English
    • 中文
    • 日本語
    • 한국어
    • Português
    • Français
    • Tiếng Việt
    • Español
    • Bahasa Indonesia

Специальный спонсор

Платиновые спонсоры

Стать спонсором

Руководство

3.x2.x1.00.120.11

  • Основы

  • Установка
  • Введение
  • Экземпляр Vue
  • Синтаксис шаблонов
  • Вычисляемые свойства и слежение
  • Работа с классами и стилями
  • Условная отрисовка
  • Отрисовка списков
  • Обработка событий
  • Работа с формами
  • Основы компонентов
  • Продвинутые компоненты

  • Регистрация компонентов
  • Входные параметры
  • Пользовательские события

Начало работы | Руководство Vue SSR

Установка

В руководстве мы будем использовать NPM, но вы свободно можете использовать и Yarn.

Примечания
  • Рекомендуется использовать Node.js версии 10+.
  • vue-server-renderer и vue должны иметь одинаковые версии.
  • vue-server-renderer зависит от некоторых нативных модулей Node.js и поэтому может использоваться только в Node.js. Возможно в будущем мы предоставим более простую сборку, которая сможет быть запущена в других средах исполнения JavaScript.

Рендеринг экземпляра Vue

Интеграция с сервером

Это достаточно просто когда мы используем сервер на Node.js, например Express:


Использование шаблона страниц

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

Вы можете упростить это, предоставив шаблон страницы при создании рендерера. Чаще всего нам требуется расположить шаблон в отдельном файле, например index.template.html:

Обратите внимание на комментарий <!--vue-ssr-outlet--> — сюда будет подставлена разметка вашего приложения.

Теперь мы можем прочитать этот файл и передать его в рендерер Vue:

Интерполяции в шаблоне

Шаблон поддерживает простые интерполяции. Например:

Мы можем предоставить необходимые данные для интерполяции, передав объект контекста для рендера вторым аргументом в renderToString:

Объект context может также использоваться совместно с экземпляром Vue приложения, что разрешает компонентам динамически регистрировать данные для интерполяции в шаблоне.

Кроме того, шаблон поддерживает некоторые продвинутые функции:

  • Автоматическую подстановку критически важного CSS при использовании *.vue компонентов;
  • Автоматическую подстановку ссылок и подсказок для ресурсов (preload / prefetch) при использовании clientManifest;
  • Автоматическую подстановку и предотвращение XSS при встраивании Vuex-состояния для гидратации на стороне клиента.

Мы обсудим это дальше, когда будем разбирать все связанные концепции.

Полный листинг кода для демо

Конфигурация сборки | Руководство Vue SSR

Мы предполагаем, что вы уже знаете как настраивать Webpack для клиентской части проектов. Конфигурация для проекта SSR будет во многом схожей, но мы предлагаем разбивать конфигурацию на три файла: base, client и server. Базовая конфигурация (base) содержит конфигурацию, совместно используемую для обоих окружений, такие как пути вывода, псевдонимы и загрузчики. Конфигурация сервера (server) и конфигурация клиента (client) просто расширяют базовую конфигурацию, используя webpack-merge.

Конфигурация серверной части

Конфигурация серверной части предназначена для создания серверной сборки, которая будет передана в createBundleRenderer. Это должно выглядеть так:

После создания vue-ssr-server-bundle.json просто передайте путь к файлу в createBundleRenderer:

В качестве альтернативы, вы также можете передать сборку как объект в createBundleRenderer. Это полезно для горячей перезагрузки во время разработки — см. демо HackerNews для примера настройки.

Ограничения externals

Обратите внимание, что в параметре externals мы указываем белый список CSS файлов. Это связано с тем, что CSS, импортированный из зависимостей всё равно должен быть обработан Webpack. Если вы импортируете любые другие типы файлов, которые также полагаются на Webpack (например, *.vue, *.sass), вы должны их также добавить в белый список.

Если вы используете runInNewContext: 'once' или runInNewContext: true, вам также требуется добавить в белый список являются полифилы, которые изменяют global, например babel-polyfill. Это связано с тем, что при использовании режима нового контекста, код внутри серверной сборки имеет свой собственный объект global. Поскольку это не будет нужно на сервере при использовании Node 7.6+, на самом деле проще просто импортировать его в клиентской точке входа.

Конфигурация клиентской части

Конфигурация клиентской части может оставаться практически такой же, как и базовой. Очевидно, вам нужно указать entry на файл входной точки клиентской части. Кроме того, если вы используете CommonsChunkPlugin, убедитесь, что используете его только в конфигурации клиентской части, потому что для серверной сборки требуется одна точка входа.

Генерация clientManifest

требуется версия 2.3.0+

Помимо серверной сборки, мы также можем сгенерировать манифест сборки. С помощью манифеста клиентской части и серверной сборки, у рендерера появится информация о серверной и клиентской сборке, поэтому он может автоматически внедрять директивы preload/prefetch в ссылки на CSS / теги script в отображаемом HTML.

Выгода тут двойная:

  1. Он может заменить html-webpack-plugin для внедрения правильных URL-адресов ресурсов, когда в генерируемых именах файлов есть хэши.

  2. При рендеринге сборки, которая использует возможности разделения кода Webpack, мы можем гарантировать, что оптимальные части были предзагружены и предзаполнены, а также интеллектуально внедрять теги <script> для необходимых асинхронных фрагментов, чтобы избежать появления водопада запросов на клиенте, таким образом улучшая TTI (time-to-interactive — время до интерактивности).

Чтобы использовать клиентский манифест, конфигурация клиентской части будет выглядеть примерно так:

Затем вы можете использовать сгенерированный манифест клиента вместе с шаблоном страницы:

С помощью этой настройки ваш отрендеренный на сервере HTML для сборки с разделением кода будет выглядеть примерно так (все автоматически внедряется):

Внедрение ресурсов вручную

По умолчанию, внедрение ресурсов выполняется автоматически при использовании опции template для рендера. Но иногда вам может понадобиться больше контроля над тем, как ресурсы должны внедряться в шаблон, или, возможно, вы не используете шаблон вообще. В таком случае вы можете передать опцию inject: false при создании рендерера и производить внедрение ресурсов вручную.

В коллбэке renderToString объект context, который вы передали, предоставляет следующие методы:

  • context.renderStyles()

    Возвращает встроенные теги <style>, содержащие весь критический CSS, собранный из *.vue компонентов, используемых во время рендеринга. Подробнее в разделе управления CSS.

    Если указан clientManifest, возвращаемая строка также будет содержать теги <link rel="stylesheet"> для файлов CSS, собранных Webpack’ом (например, CSS извлечённый extract-text-webpack-plugin или импортированный с помощью file-loader)

  • context.renderState(options?: Object)

    Метод сериализует context.state и возвращает инлайновый скрипт, который подставит состояние как window.__INITIAL_STATE__.

    Ключ состояния контекста и ключ состояния для window можно изменить передав объект с настройками:

  • context.renderScripts()

    • требует clientManifest

    Возвращает теги <script>, необходимые для загрузки клиентского приложения. При использовании асинхронного разделения кода в коде приложения этот метод будет интеллектуально выводить нужные асинхронные фрагменты для включения.

  • context.renderResourceHints()

    • требует clientManifest

    Возвращает ссылки <link rel="preload/prefetch"> на ресурсы, необходимые для отображения страницы. По умолчанию такими будут:

    • Предзагруженные (preload) файлы JavaScript и CSS, необходимые для страницы
    • Предзагруженные (prefetch) асинхронные фрагменты JavaScript, которые могут понадобится позже

    Настраивать какие файлы дополнительно могут быть предзагружены можно с помощью опции shouldPreload.

  • context.getPreloadFiles()

    • требует clientManifest

    Этот метод не возвращает строку — вместо этого он возвращает массив объектов файлов, представляющие ресурсы которые должны быть предзагружены. Это можно использовать для программной загрузки HTTP/2 сервером.

Поскольку template, переданный в createBundleRenderer будет интерполирован с использованием context, вы можете использовать эти методы внутри шаблона (при использовании inject: false):

Если вы вообще не используете template, вы можете конкатенировать строки вручную.

Предзагрузка данных и состояния | Руководство Vue SSR

Хранение данных

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

Для решения этой проблемы, полученные данные должны находиться вне компонентов представления, в специальном хранилище данных или в «контейнере состояния». На сервере мы можем предзагрузить и заполнить данные в хранилище перед рендерингом. Кроме того, мы будем сериализовывать и встраивать состояние в HTML после успешного рендеринга приложения. Хранилище на клиентской стороне сможет непосредственно получать вложенное состояние перед монтированием приложения.

Для этой цели мы будем использовать официальную библиотеку управления состоянием — Vuex. Давайте создадим файл store.js, с некоторой симуляцией логики получения элемента на основе id:

ВНИМАНИЕ

Большую часть времени вы должны оборачивать state в функцию, чтобы она не вызвала утечек памяти при следующих запусках на стороне сервера.
Подробнее

И обновляем app.js:

Размещение логики для компонентов

Итак, где мы должны размещать код, который вызывает действия по предзагрузке данных?

Данные, которые нам нужно получить, определяются посещённым маршрутом — что также определяет какие компоненты должны будут отобразиться. Фактически, данные необходимые для данного маршрута, также требуются компонентам, отображаемым для этого маршрута. Поэтому будет логичным разместить логику получения данных внутри компонентов маршрута.

Мы будем использовать опцию serverPrefetch (добавлена в версии 2.6.0+) в компонентах. Эта опция распознаётся рендерингом на стороне сервера и приостанавливает отрисовку до тех пор, пока Promise не разрешится. Это позволяет нам «дожидаться» асинхронных данных в процессе отрисовки.

Совет

Можно использовать serverPrefetch в любом компоненте, а не только в компонентах указываемых в маршрутах.

Вот пример компонента Item.vue, который отображается по маршруту '/item/:id'. Поскольку экземпляр компонента уже создан на этом этапе, он имеет доступ к this:

ВНИМАНИЕ

Необходимо проверять рендерился ли компонент на стороне сервера в хуке mounted во избежание выполнения логики загрузки дважды.

Совет

Можно увидеть одинаковую логику fetchItem(), повторяющуюся несколько раз (в коллбэках serverPrefetch, mounted и watch) в каждом компоненте — рекомендуется создать собственную абстракцию (например, примесь или плагин) для упрощения подобного кода.

Инъекция финального состояния

Теперь мы знаем что процесс отрисовки будет дожидаться получения данных в наших компонентах, но как же узнавать когда всё «готово»? Для этого потребуется использовать коллбэк rendered в контексте рендера (также добавлено в версии 2.6), который будет вызывать серверный рендер после завершения всего процесса рендеринга. В этот момент хранилище должно быть заполнено данными своего финального состояния. Затем мы можем внедрить его в контекст в этом коллбэке:

При использовании template, context.state будет автоматически встроен в финальный HTML как window.__INITIAL_STATE__. На клиенте хранилище должно получить состояние перед монтированием приложения:

Разделение кода хранилища

В большом приложении хранилище Vuex будет скорее всего разделено на несколько модулей. Конечно, также можно разделить код этих модулей на соответствующие фрагменты компонента маршрута. Предположим, что у нас есть следующий модуль хранилища:

Мы можем использовать store.registerModule для ленивой регистрации этого модуля в хуке serverPrefetch компонента маршрута:

Поскольку модуль теперь является зависимостью компонента маршрута, он будет перемещён в асинхронный фрагмент компонента маршрута с помощью Webpack.

ВНИМАНИЕ

Не забывайте использовать опцию preserveState: true для registerModule чтобы сохранять состояние, внедрённое сервером.

Написание универсального кода | Руководство Vue SSR

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

Реактивность данных на сервере

В приложении, которое работает только на клиенте, каждый пользователь использует свежий экземпляр приложения в своём браузере. Для рендеринга на стороне сервера мы хотим того же: каждый запрос должен иметь свежий, изолированный экземпляр приложения, чтобы не возникало загрязнения состояния при перекрёстных запросах.

Поскольку фактический процесс рендеринга должен быть детерминированным, мы также будем «предзагружать» данные на сервере — это означает, что состояние приложения будет разрешённым, на момент начала рендеринга. А это означает, что на сервере реактивность данных не нужна, поэтому по умолчанию она отключена. Отключение реактивности данных также позволяет избежать уменьшения производительности из-за отсутствия необходимости преобразования данных в реактивные объекты.

Хуки жизненного цикла компонента

Так как динамических обновлений нет, из всех хуков жизненного цикла будут вызваны только beforeCreate и created во время серверного рендеринга (SSR). Это означает, что код внутри любых других хуков жизненного цикла, таких как beforeMount или mounted, будет выполняться только на клиенте.

Стоит ещё отметить, что вам следует избегать кода, который производит глобальные побочные эффекты (side effects) в хуках beforeCreate и created, например устанавливая таймеры с помощью setInterval. В коде на стороне клиента мы можем установить таймер, а затем остановить его в beforeDestroy или destroyed. Но, поскольку хуки уничтожения не будут вызываться во время SSR, таймеры останутся навсегда. Чтобы избежать этого, переместите такой код в beforeMount или mounted.

Доступ к специфичному API платформы

Универсальный код не может использовать API специализированное для какой-то конкретной платформы (platform-specific APIs), потому что если ваш код будет использовать глобальные переменные браузеров window или document, то возникнут ошибки при выполнении в Node.js, и наоборот.

Для задач, разделяемых между сервером и клиентом, но использующих разные API платформы, рекомендуется создавать обёртки платформо-специфичных реализаций в универсальное API, или использовать библиотеки, которые делают это за вас. Например, axios — это HTTP-клиент предоставляющий одинаковое API как для сервера так и для клиента.

Для API только для браузеров общий подход — ленивый (lazy) доступ к ним, внутри хуков жизненного цикла только для клиентской стороны.

Обратите внимание, если сторонняя библиотека не была написана с расчётом на универсальное использование, её может быть сложно интегрировать в приложение с серверным рендерингом. Вы могли бы заставить её работать, например создавая моки некоторых глобальных переменных, но это будет грязным хаком и может помешать коду обнаружения окружения в других библиотеках.

Пользовательские директивы

Большинство пользовательских директив непосредственно манипулируют DOM, поэтому будут вызывать ошибки во время SSR. Существует два способа обойти это:

  1. Предпочитайте использовать компоненты в качестве механизма абстракции и работайте на уровне виртуального DOM (например, используя render-функции).

  2. Если у вас есть пользовательская директива, которую нельзя легко заменить компонентами, вы можете предоставить её «серверный вариант» с помощью опции directives при создании серверного рендерера.

Структура исходного кода | Руководство Vue SSR

Избегайте синглтонов с состоянием

При написании кода для клиентской стороны мы привыкли к тому, что наш код каждый раз будет выполняться в новом контексте. Однако сервер Node.js является длительным процессом (long-running process). Поэтому когда наш код потребуется, он будет выполнен один раз и останется в памяти. Это означает, что если вы создаёте объект синглтон, он будет использоваться для всех входящих запросов.

Как видно из простого примера, мы создаём новый корневой экземпляр Vue для каждого запроса. Это схоже с тем, когда каждый пользователь будет использовать свежий экземпляр приложения в своём браузере. Если мы будем использовать общий экземпляр для нескольких запросов, то это быстро приведёт к загрязнению состояния.

Поэтому, вместо непосредственного создания экземпляра приложения, мы должны предоставить функцию-фабрику, которую можно повторно вызывать для создания свежих экземпляров приложения на каждый запрос:

Код нашего сервера станет таким:

Это правило также применимо и к экземплярам маршрутизатора (router), хранилища (store) и шины событий (event bus). Вместо того, чтобы непосредственно экспортировать из модуля и импортировать везде в приложении, вам нужно создавать новый экземпляр в createApp и внедрять его из корневого экземпляра Vue.

Это ограничение можно обойти при использовании рендерера сборки с опцией { runInNewContext: true }, однако это сопряжено с некоторыми существенными затратами производительности, поскольку для каждого запроса потребуется создание нового контекста vm.

Представляем шаг сборки

До сих пор мы не обсуждали каким образом доставлять клиенту такое приложение Vue. Чтобы сделать это, мы должны использовать Webpack для сборки нашего приложения Vue. На самом деле, мы вероятно захотим использовать Webpack для сборки приложения Vue также и на сервере, потому что:

  • Типичные приложения Vue собраны с помощью Webpack и vue-loader, и многие Webpack-специфичные вещи, такие как импорт файлов через file-loader, импорт CSS через css-loader не будут работать напрямую в Node.js.

  • Несмотря на то, что последняя версия Node.js полностью поддерживает ES2015, нам всё же необходимо транспилировать код для клиентской части для совместимости со старыми браузерами. Это снова предполагает шаг сборки.

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

Мы обсудим подробности настройки в следующих разделах — а сейчас, давайте представим что у нас реализован шаг сборки и мы можем писать код нашего приложения Vue с использованием Webpack.

Структура кода с Webpack

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

Простой проект может выглядеть подобным образом:

app.js

app.js — универсальная точка входа в наше приложение. В только клиентском приложении, мы бы создавали корневой экземпляр Vue прямо в этом файле и монтировали непосредственно в DOM. Однако при использовании серверного рендеринга эта ответственность переносится в файл клиентской точки входа (entry-client.js). app.js просто экспортирует функцию createApp:

entry-client.js:

Клиентская точка входа — просто создаёт приложение и монтирует его в DOM:

entry-server.js:

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

Гидратация клиентской части | Руководство Vue SSR

Гидратация относится к процессу на стороне клиента, в течение которого Vue берёт статический HTML, отправленный сервером, и превращает его в динамический DOM, который может реагировать на изменения данных на стороне клиента.

В файле entry-client.js, мы просто монтируем приложение такой строкой:

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

Если вы исследовали вывод после серверного рендеринга, вы могли заметить, что у корневого элемента приложения должен быть добавлен специальный атрибут:

Специальный атрибут data-server-rendered позволяет клиентской части Vue знать, что разметка отображается сервером, и он должен монтироваться в режиме гидратации. Обратите внимание, что он не добавляет id="app", а только атрибут data-server-rendered: вам необходимо добавить ID или какой-либо другой селектор в корневой элемент самостоятельно или приложение не будет гидратироваться правильно.

Обратите внимание, что на элементах без атрибута data-server-rendered гидратация может быть принудительно выполнена при передаче true в аргументе hydrating метода $mount:

В режиме разработки Vue будет проверять, что виртуальное дерево DOM, сгенерированное на стороне клиента, совпадает с структурой DOM созданной на сервере. При нахождении несоответствия, он будет считать гидратацию неудачной, отказываться от существующего DOM и рендерить всё с нуля. В режиме production, эта проверка отключена для достижения максимальной производительности.

Предостережения при гидратации

Одна вещь, о которой нужно знать при использовании серверного рендеринга + гидратации на клиенте — некоторые специальные структуры HTML, которые могут быть изменены браузером. Например, когда вы пишете подобное в шаблоне Vue:

Браузер будет автоматически добавлять <tbody> внутрь <table>, в то время как виртуальный DOM генерируемый Vue не содержит <tbody>, что вызовет несоответствие. Чтобы обеспечить правильное соответствие, обязательно пишите валидный HTML в ваших шаблонах.

Начало работы | Руководство Vue SSR

Установка

В запуск мы будем использовать NPM, но вы свободно можете использовать и Yarn.

Примечания
  • Рекомендуется использовать Node.js версии 10+.
  • vue-server-renderer и vue должны иметь одинаковые версии.
  • vue-server-renderer зависит от некоторых нативных модулей Node.js и поэтому может быть только в Node.js.Возможно в будущем мы предоставим более простую сборку, которая может быть запущена в других средах исполнения JavaScript.

Рендеринг экземпляра Vue

Интеграция с сервером

Это достаточно просто мы используем сервер на Node.js, например Express:


Использование шаблона страниц

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

Вы можете упростить это, предоставив шаблон страницы при создании рендерера. Чаще всего нам требуется расположить шаблон в отдельном файле, например index.template.html :

Обратите внимание на комментарий — сюда будет подставлена ​​разметка вашего приложения.

Теперь мы можем прочитать этот файл и передать его в рендерер Vue:

Интерполяции в шаблоне

Шаблон поддерживает простые интерполяции.Например:

Мы можем предоставить данные для интерполяции, передаваемый объект контекста для рендера вторым аргументом в renderToString :

Объект context может также подключать компоненты Vue, что разрешает компонент динамически регистрировать данные для интерполяции в шаблоне.

Кроме того, шаблон поддерживает некоторые продвинутые функции:

  • Автоматическая подстановка критически важного CSS при использовании *.vue компонентов;
  • Автоматическая подстановку ссылок и подсказок для ресурсов (предварительная загрузка / предварительная выборка) при использовании clientManifest ;
  • Автоматическая подстановка и предотвращение XSS при встраивании Vuex-состояния для гидратации на стороне клиента.

Мы обсудим это дальше, когда будем разбирать все связанные концепции.

Полный листинг кода для демо

.

Конфигурация сборки | Руководство Vue SSR

Мы предполагаем, что вы уже знаете как настроить Webpack для клиентской части проектов. Конфигурация проекта SSR будет во многом схожей, но мы предлагаем разбивать конфигурацию на три: base , client и server . Базовая конфигурация (base) содержит конфигурацию, используемую для обоих окружений, такие как пути вывода, псевдонимы и загрузчики. Конфигурация сервера (сервера) и конфигурация клиента (клиента) просто расширяют базовую конфигурацию, используя webpack-merge.

Конфигурация серверной части

Конфигурация серверной части для создания серверной сборки, которая будет передана в createBundleRenderer . Это должно выглядеть так:

После создания vue-ssr-server-bundle.json просто передайте путь к файлу в createBundleRenderer :

В качестве альтернативы, вы также можете передать сборку как объект в createBundleRenderer . Это полезно для горячей перезагрузки во время разработки — см.демо HackerNews для примера настройки.

Ограничение внешних параметров

Обратите внимание, что в параметре externals мы указываем белый список файлов CSS. Это связано с тем, что CSS, импортированный из зависимостей, должен быть обработан Webpack. Если вы импортируете любые другие типы файлов, которые также полагаются на Webpack (например, * .vue , * .sass ), вы также должны их добавить в белый список.

Если вы используете runInNewContext: 'once' или runInNewContext: true , вам также требуется добавить белый список, которые являются полифилами, которые изменяют global , например babel-polyfill .Это связано с тем, что используется режим нового контекста, код внутри серверной сборки имеет свой собственный объект global . На самом деле это проще простого импортировать в клиентскую точку входа.

Конфигурация клиентской части

Конфигурация клиентской части может оставаться практически такой же, как и клиентская. Очевидно, вам нужно указать запись на файл входной точки клиентской части.Кроме того, если вы используете CommonsChunkPlugin , убедитесь, что вы используете его только в конфигурации клиентской части, потому что для сервера сборки требуется одна точка входа.

Генерация clientManifest

требуется версия 2.3.0+

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

Выгода тут двойная:

  1. Он может заменить html-webpack-plugin для внедрения правильных URL-адресов ресурсов, когда в генерируемых именах файлов есть хэши.

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