prerenderについて

なぜprerender?

ブラウザーがSPAのindex.htmlをダウンロードし解析した後からCSSファイルとJavaScriptファイルダウンロードと解析完了まで時間差があります。

特にcode-splitやっていないSPAのJavaScriptファイルのダウンロードはもっと時間かかります。

もしユーザーさんは3Gを使うと、ダウンロード時間がもっと長くなり、数十秒の空白画面が表示されてしまう場合があります。

これにより離脱する可能性があります。

prerenderはwebpackでHTML、CSSJavaScript、画像をコンバイるした後、Headless Browserを立ち上げて、実際のページを解析し、JavaScriptが実行した後の結果(CSSコードやJavaScriptに よって作成されたDOMなど)をHTMLファイルに追加する過程です。

prerenderの前のHTML

<!doctype html>
<html>
<head>
  <link href="/bundle.css" ref="stylesheet" />
</head>
<body>
  <div id="main"></div>
  <script type="text/javascript" src="/bundle.js"></script>
</body>
</html>

prerenderの後のHTML

<!doctype html>
<html>
<head>
  <style>
    <!-- 具体的なCSSコード -->
  </style>
  <link href="/bundle.css" ref="stylesheet" />
</head>
<body>
  <div id="main">
    <div data-reactroot>
      <span>
        <!-- 具体的なJavaScriptにより作成されたDOM -->
      </span>
    </div>
  </div>
  <script type="text/javascript" src="/bundle.js"></script>
</body>
</html>

これでよりCSSJavaScriptファイルをダウロードする間、ある程度整ってるページが表示され、ユーザーさんが寂しくないです。

使うライバリー

prerender-spa-plugin https://github.com/chrisvfritz/prerender-spa-plugin

webpack.config.js

const path = require('path')
const PrerenderSPAPlugin = require('prerender-spa-plugin')

module.exports = {
  plugins: [
    ...
    new PrerenderSPAPlugin({
      // webpackのアウトプット
      staticDir: path.join(__dirname, 'dist'),
      // prerenderが必要なページ
      routes: [ '/', '/about', '/some/deep/nested/route' ],
    })
  ]
}

どんなページがprerender必須?

rootページ

特にprerender指定しない時、全部のpathに対するリクエストはrootページのHTMLファイルを返しています。

react-helmetによってOGP情報を変えたページ

だいたい全部SNSサイトのクローラーJavaScript実行していません。

正しいOGP情報を出し分けるためprerenderが必要です。

いい感じにprerenderできるため

prerender-spa-pluginは1つの素晴らしい特性があります。

prerenderする時、ページのwindowオブジェクトに”prerenderですよ”を示す変数を入れることができます。

webpack.config.js

const path = require('path')
const PrerenderSPAPlugin = require('prerender-spa-plugin')
const Renderer = PrerenderSPAPlugin.PuppeteerRenderer;

module.exports = {
  plugins: [
    ...
    new PrerenderSPAPlugin({
      ...
      // window.__PRERENDER_INJECTED && window.__PRERENDER_INJECTED.isPrerendering
      // によってprerender中かどうかを判断できる
      renderer: new Renderer({
        injectProperty: "__PRERENDER_INJECTED",
        inject: {
          isPrerendering: true,
        },
      })
    })
  ]
}

これにより、prerenderの時ローディングUIなどをだすことが可能となります。

まとめ

SPAは膨大のCSSJavaScriptファイルのダウンロードによって長い時間でブラウザーを空白にすることがあります。

prerenderによってコードを最初ダウンロードされるHTMLファイルを埋めることができます。

これで空白が解消できます。

JavaScriptでOGP情報を出し分ける時、prerenderが必須です。

prerender-spa-pluginによっていい感じにprerenderができます。