SSR(Server-Side Rendering)は、最近すべての愛を集めています。 いくつかのスクリプトを含むスケルトンの代わりに完全なHTMLページを送信することにより、初期ページの読み込みを高速化することは、本当に素晴らしいアイデアです。 ただし、落とし穴があります。 SSRはハードです。 気になることがたくさんあり、壊れやすいです。 真実は、ほとんどの場合、SSRはやり過ぎです。 prerender-spa-plugin を使用して、ビルド時にサイトを静的ページに事前レンダリングすることにより、Vue.jsアプリでSSRのほとんどの利点を得ることができます。

事前レンダリングは、静的サイト生成と混合されたサーバーサイドレンダリングのようなものですが、より単純です。 プリレンダラーに必要なルートを指定すると、ブラウザーまたは同等の環境が起動し、ページが読み込まれ、結果のHTMLがルートに一致するファイルパスにダンプされます。 これにより、完全にレンダリングされた静的ページが提供され、読み込み時間が短縮され、静的サイトサーバーに展開するための奇妙なハックが不要になります。 JavaScriptの読み込みが完了すると、アプリは通常どおり機能し続けます。

ただし、事前レンダリングは特効薬ではありません。数百のルートがある場合、またはプレースホルダーなしで動的コンテンツを事前レンダリングする必要がある場合は、これを使用しないでください。

とにかく、十分なチットチャット。 それを行う方法を見てみましょう。

ノート: prerender-spa-plugin 3.0はまだアルファ版であるため、APIの使用法は将来変更される可能性があります。 この記事を最新の状態に保つように努めます。 ここで何かが正しく機能しない場合は、公式ドキュメントを参照してください。

このガイドでは、vue-cliwebpack-simpleテンプレートを使用してクイックプロジェクトを設定したことを前提としていますが、どのWebpack設定でもほとんど同じです。

使用法

Vue.jsプロジェクトにprerender-spa-pluginをインストールします。

# Yarn
$ yarn add prerender-spa-plugin@next -D
# or NPM
$ npm install prerender-spa-plugin@next --save-dev

次に、 webpack.config.js, require() 関連するパッケージ。

webpack.config.js(部分的)
var path = require('path')
var webpack = require('webpack')
// Add these
const PrerenderSPAPlugin = require('prerender-spa-plugin')
// Renders headlessly in a downloaded version of Chromium through puppeteer
const PuppeteerRenderer = PrerenderSPAPlugin.PuppeteerRenderer

...

module.exports = {
  ...
  plugins: [
    new PrerenderSPAPlugin({
      staticDir: __dirname, // The path to the folder where index.html is.
      routes: ['/'], // List of routes to prerender.
      renderer: new PuppeteerRenderer()
    })
  ]
}

...

これで、webpackを再度実行すると、次のことがわかります。 index.html プロジェクトルートには、ページのレンダリングされたコンテンツも含まれるようになりました。

レンダラーの切り替え

PuppeteerRendererは素晴らしいです…そうでない場合を除いて。 これは超高速ではなく、大量のシステムリソースを占有せずに大量のページをレンダリングすることはできません。

数百または数千のページをレンダリングする必要がある場合は、JSDOMRendererの方が適している場合があります。 jsdom は、Node.js内のブラウザー環境を偽造し、可能な限りモックします。 それはかなり良い仕事をしますが、すべてを処理することはできません。 存在しない可能性のある特定の新しいまたは異常なAPIを回避するために、アプリを調整する必要がある場合があります。

JSDOMRendererには付属していません prerender-spa-plugin デフォルトでは。 でインストールする必要があります。

# Yarn
$ yarn add @prerenderer/renderer-jsdom -D
# NPM
$ npm install @prerenderer/renderer-jsdom --save-dev

JSDOMRendererの例:

var path = require('path')
var webpack = require('webpack')
// Add these
const PrerenderSPAPlugin = require('prerender-spa-plugin')
const JSDOMRenderer = require('@prerenderer/renderer-jsdom')

...

module.exports = {
  ...
  plugins: [
    new PrerenderSPAPlugin({
      staticDir: __dirname, // The path to the folder where index.html is.
      routes: ['/'], // List of routes to prerender.
      renderer: new JSDOMRenderer()
    })
  ]
}

...

必要に応じて、独自のレンダラーを実装することも非常に簡単です。 詳細については、公式ドキュメントを参照してください。

構成

遅延レンダリング

ページをすぐにレンダリングする必要はありません。 何かが起こるのを待ちたい場合があります。

3つのレンダラーはすべて、3つの異なるトリガーを待つことができます。

要素が存在するのを待ちます:

renderer: new PuppeteerRenderer({
  // Wait to render until the element specified is detected with document.querySelector.
  renderAfterElementExists: '#app'
})

ドキュメントイベントが発生するのを待ちます。

あなたはあなたのアプリでイベントをトリガーすることができます document.dispatchEvent(new Event('my-document-event'))

renderer: new PuppeteerRenderer({
  // Wait to render until a specified event is fired on the document.
  renderAfterDocumentEvent: 'my-document-event'
})

指定された時間待機します。

renderer: new PuppeteerRenderer({
  // Renders after 5000 milliseconds. (5 seconds.)
  renderAfterTime: 5000
})

可変噴射

レンダラーは、アプリスクリプトを実行する前に、変数をグローバルスコープに挿入することもできます。 これは、ページが事前レンダリングされているかどうかに応じて、アプリに何かを渡したり、動作を変更したりする必要がある場合に便利です。

renderer: new PuppeteerRenderer({
  // injectProperty: '__PRERENDER_INJECTED'
  // You can change the property added to window. The default is window.__PRERENDER_INJECTED.
  // Inject can be any object that is JSON.stringify-able.
  inject: {
    nestLocation: 'bayou'
  }
})

今あなたのアプリで、 window.__PRERENDER_INJECTED.nestLocation === 'bayou'

今のところは以上です! 事前レンダリングをお楽しみください!