Представляем Bundle Renderer

Проблемы с обычным SSR

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

const createApp = require('/path/to/built-server-bundle.js')

Выглядит просто, однако всякий раз, когда вы редактируете исходный код вашего приложения, вам понадобится остановить и перезапустить сервер. Это очень плохо влияет на производительность во время разработки. К тому же, Node.js не поддерживает source maps нативно.

Добавляем BundleRenderer

vue-server-renderer предоставляет API, названное createBundleRenderer для решения этой проблемы. С помощью Webpack-плагина, серверная сборка создаётся как специальный JSON-файл, который может быть передан в рендерер. Как только рендерер создан, использование не будет отличаться от обычного рендерера, но появятся некоторые преимущества:

  • Встроенная поддержка source map (с помощью devtool: 'source-map' в конфигурации Webpack)

  • Горячая перезагрузка в процессе разработки и даже развёртывания (путём простого чтения обновлённого пакета и пересоздания экземпляра рендерера)

  • Внедрение критического CSS (при использовании *.vue файлов): автоматически встраивает CSS, необходимый компонентам во время рендеринга. Подробнее в разделе CSS.

  • Внедрение ресурсов с помощью clientManifest: автоматически добавляет оптимальные директивы preload и prefetch, а также фрагменты кода, необходимые для первоначального рендеринга.


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

const { createBundleRenderer } = require('vue-server-renderer')

const renderer = createBundleRenderer(serverBundle, {
  runInNewContext: false, // рекомендуется
  template, // (опционально) шаблон страницы
  clientManifest // (опционально) манифест клиентской сборки
})

// внутри обработчика сервера...
server.get('*', (req, res) => {
  const context = { url: req.url }
  // Нет необходимости передавать приложение тут, потому что оно автоматически создаётся
  // при выполнении сборки. Теперь наш сервер отделён от нашего приложения Vue!
  renderer.renderToString(context, (err, html) => {
    // обработка ошибок...
    res.end(html)
  })
})

Когда renderToString вызывается в рендерере, он автоматически выполнит функцию, экспортируемую сборкой для создания экземпляра приложения (передавая context в качестве аргумента), а затем рендерит его.

Обратите внимание, что рекомендуется установить опцию runInNewContext в значение false или 'once'. См. справочник API для подробностей.