導入する?Nuxt.jsでSSR対応・ページ高速化する際のメリットをまとめてみた

f:id:nepio:20181002170250p:plain

最近流行りのvue.jsベースのフロントエンドフレームワーク、nuxt.jsを調べていたのですが、めちゃくちゃすごくないですが・・・。

導入するか迷っている方に、かいつまんですごい点を説明していきます。

環境設定がとにかく簡単

nuxt.jsは環境設定がとにかく簡単です。

最近のフロントエンドって開発環境から難しい設定をしなければならないのですが、nuxt.jsならコマンド一つで始められます。

npx create-nuxt-app {PROJECT_NAME}

上記のコマンドで生成されたpagesのディレクトリの中にvueファイルを作成すればすぐにサイトが作れます。

nuxt,jsが採用しているvue.jsは、その他のフロントエンドライブラリ(reactなど)に比べて、学習コストが低いことで有名です。

環境設定を何も考えずに、すぐに開発を始めることができる点が大きなメリットです。webpackのconfigに悩まされることもありません。

まあ、似たような環境設定ツールはnuxtに限らず他にもあるんですが、nuxtの場合デフォルトの設定のクオリティが高いんですよね・・・。

サーバーサイドレンダリングが簡単

nuxt.jsでは、サーバーサイドレンダリングが簡単に実現できます。

他のフロントエンドフレームワークだとサーバーサイドレンダリングは難しい環境設定をしなければ実現できないのですが、nuxt.jsの場合、デフォルトで実現可能です。

サーバーサイドレンダリングとは、サーバー上でjavascriptを処理してHTMLを出力する技術で、googleの検索エンジンがコンテンツを正しく認識してくれたり、ユーザに対するコンテンツの表示が早くなったりするメリットがあると言われています。

一般に、サーバーサイドレンダリングはSEOの観点から語られることが多いですが、ページの表示速度向上のメリットも大きいです。

nuxtはサーバーサイドレンダリング機能を生かして、かなりいい感じの速度改善機能を盛り込んでいますので紹介します。(この表皮右側度改善機能もほとんどデフォルトだからすごい・・・。)

nuxt.jsの表示速度改善機能

フロントエンドの速度改善にはいくつかポイントがあります。

(と偉そうに語ってますが、運用上の知見がそれほどないため、他ページを引用します。)

例えば、下記のサイトでは、イケてるWebサービスが導入しているフロントエンドの速度改善技術がまとめられているのですが、

www.wantedly.com

かいつまんで概略をまとめると以下のようになるでしょうか。

  • http/2対応

  • cssはページに必要な要素をインラインに展開してHTMLと一緒にダウンロード

  • ページのレンダリングに必要なjavascriptは細かく分割して、必要なものだけ読み込む。ページ遷移の際に追加で必要なjavascriptを読み込む

  • ページのレンダリングに関係のない、読み込みの遅れても良いjavascriptはasync指定であとで読み込む

  • Service Workerを利用して事前にjsや画像をキャッシュしておく

  • その他

nuxt.jsはいい感じにサーバーサイドレンダリングをすることで、ほとんど手間をかけることなく、上記の性質を実現できます。

http/2対応

nuxt.jsはデフォルトでhttp/2とspdyを利用しています。

f:id:nepio:20181003044948p:plain

spdyはhttp/2のベースになったプロトコルであるため、http/2と同様に早いです。

http/2と何が違うのかは把握していないですが、とりあえずhttp/1.1より早いのは間違いないです。

(今回はGAEのnodeでデプロイしたので、もしかしたらGAEの仕様の影響も受けているのかも。)

cssはページに必要な要素をインラインに展開してHTMLと一緒にダウンロード

nuxt.jsでは、cssは最初のページに必要な部分がインライン展開されてHTML上に表示されます。

ページ遷移を重ねるたびにjsファイルがDOMを操作して、差分のCSSをレンダリングしてくれます。(jsと一緒にcssが分割されていて、SSRの際にファーストビューに必要な分だけがインライン展開される・・・という形です。これもSSRの恩恵ですね。)

f:id:nepio:20181003044411p:plain

ちなみに、cssフレームワークなどを利用していると、上記のようにフレームワークのcssがHTMLにインライン展開されてしまい、可読性が下がって、げ・・・・と思うかも知れませんが、レンダリングに必要なcssなので極端に大きくなければ問題ないと思います。

気になる場合、フレームワーク部分だけ別ファイルにしてもいいかも知れませんが・・・。

ページのレンダリングに必要なjavascriptは細かく分割して、必要なものだけ読み込む

nuxt.jsでnpm buildを実行してjavascriptをビルドすると、デフォルトで以下のようにjsを分割してくれます。

f:id:nepio:20181003045438p:plain

今回の場合だと、すべてのページに共通して必要なcommons.app、vendors.app、runtime、appの4つの他に各ページに対応したjsが7つ出力されています。ページ1つにつきjs1つが追加で出力されます。

実際にページを開く際には、共通のjs(4種類) + ページに対応したjsの5種類が読み込まれます。

例えば下記のような感じです。

f:id:nepio:20181003050950p:plain

ページに必要なjsをページ上部のlinkタグで読み込み、ページ下部のdefer指定のスクリプトタグで実行しています。これにより、できるだけ早くjavascriptの読み込みを開始して、bodyのパースが終わったタイミングですぐにjsを実行することができるので、表示速度が早くなります。

そして、ページ遷移をして新しいページを開くとDOMが更新されて、追加で必要なjsが読み込まれていきます。

これもファーストビューに最適化されたサーバーサイドレンダリングが備わっているからであると言えますね。

ページのレンダリングに関係のない、遅れても良いjavascriptはasync指定で読み込む

これに関してはデフォルトでは例がなかった(nuxtやvueはDOMのレンダリングのライブラリなので当たり前といえば当たり前)ですが、nuxt.config.jsを操作すれば実現できます。

Service Workerを利用して後で必要になるjsや画像を事前にキャッシュ

Introduction - PWA Module

というモジュールを導入するとビルドされたjsを検知して、自動でそれらをキャッシュするService Workerが作成されます。ちなみにコマンド一発と設定2、3行で動きました。

f:id:nepio:20181003051811p:plain

上記のようなServer Workerのコードが自動で生成されます。このコードでは、各種jsを事前にダウンロードしてキャッシュしておく機能が記述されています。

サイトを開くと、①まずレンダリングに必要なjsがダウンロードされてページが表示される ②Service Workerがインストールされ、その他のページで必要なjsがダウンロードされてキャッシュされる

という感じの挙動をします。こんな感じで最初にページを開いたタイミングで、Service Workerがインストールされて必要なjsをprecacheします・・・しゅごい・・・。

f:id:nepio:20181003052624p:plain

その後、ページ遷移をしたり、再度ページを開いたりした場合には、Service Workerがローカルに保存しているjsが参照されるため、ページ表示速度が圧倒的に早くなります。(なんならオフラインでも表示されるようになります。)

その他

その他の機能に関してはHTTPのレスポンスヘッダであったり、HTMLのタグを挿入したり、CDNを導入したりで、nuxt.jsの機能とはあまり関係がないし、個別に対応していく話かなと思うので省略します。

まとめ

nuxt.jsってどうなんやろと思ってproduction環境の挙動を調べたら想像以上にいい感じでびっくりしました。

これらの各要素はシンプルですが、他のフレームワークだと結構頑張って設定して、開発に応じて設定も修正していく必要があるはず・・・・。

新しいものは触らないとだめですね・・・。