beta

Vue.jsアプリの初期ロードを高速化するためにやったこと

Vue.jsアプリは、index.htmlをロードした後に必要ファイルを読んでDOMを構成するので、どうしても初期ロードが遅くなりがちです。初期ロードの遅延は離脱に直結するので、CDNやprefetchなどを駆使してVue.jsアプリの初期ロードを高速化してみました。

公開日:2020年4月6日

読み込み速度改善

Vue.jsアプリ本体の改善も重要ですが、アプリの初期ロードという観点では、意外とここが効果的です。

index.htmlをCDNから配信

Vue.jsアプリの場合、index.htmlをロードしてから付随するcssやjsをロードしてDOMを構成するので、最初のindex.htmlが高速に配信されることが、Vue.jsアプリの高速化の大前提です。

ここを1msでも早くすれば、Vue.jsアプリの展開も早くなるので、CDNを使ってアプリ本体を高速配信して、ブラウザにはアプリの描画になるべく早く着手してもらいます。

ただし、index.htmlはVue.jsのコアファイルのファイル名はビルドごとに動的になっているので、ビルドの度にCDNでindex.htmlのキャッシュをクリア手間がかかります。

CI/CDを使ってビルドしているのであれば、CDNのAPIを使ってindex.htmlのキャッシュをビルドの度にクリアするようにしておくと良いでしょう。

関連ファイルはCDNからgzipで配信

Vue.js関連ファイルは、静的ファイル&ビルドごとに乱数が当てられているので、CDNでキャッシュしても、常に最新のものが配信されます。

jsファイルやcssファイルはVue.jsの心臓部分なのでファイル数も容量も多めなので、ここで速度を稼いでおくことが大事です。

prefetch, preconnect

index.htmlにprefetch, preconnectを入れておくと、ロードが早くなります。Vue.jsの場合、js、css、画像と読み込むファイルが多いのでかなり有効な手段です。

特に、First Contentful Paintを高速化するには、TTFB(Time To First Byte)を高速化するのは必須なので、index.htmlをロードした時点で、静的ファイルを後々読むドメイン(自ドメインを含む)をpreconnectしておくだけでも、TTFBがかなり高速化されます。

自分のVue.jsアプリでは、First Contentful Paintを1.9秒から1.0秒まで高速化できました。

アプリ側

頻繁に読み込まないコンポーネントを動的ロード

Vue Routerでルーティングする際など、コンポーネントは予めimportで宣言してrouterのroutes変数でコンポーネントを指定するのが通例ですが、この方法だとVue.jsアプリを初期ロードする時に全てのルートのファイルをロードすることになってしまいます。

一方で、ルート設定内でviewのコンポーネントをimportすると、ルートに入った時にコンポーネントファイルをロードしてくれるようになります。

// アプリ本体をロードした際に、viewコンポーネントもロード
import Home from "./views/Home.vue";

const router = new Router({
  routes: [
    {
      path: "/",
      name: "Home",
      component: Home
    }
  ]
});
// ルートに入った時に初めてviewコンポーネントをロードする
const router = new Router({
  routes: [
    {
      path: "/",
      name: "Home",
      component: () => import( './views/Home.vue'),
    }
  ]
});

ロードファイル数が減るので、転送量も削減でき、アプリのダウンロードを高速化できます。

関数型コンポーネントを使う

関数型コンポーネントは、ステート(状態)をwatchせず、propsで与えられたデータをもとに描画するだけのコンポーネントです。ライフサイクルフックの監視対象外になるため、描画が軽くなります。

関数型コンポーネント向けのテンプレート | Vue Loader

// functionalと入れると関数型になる
<template functional>
  <div>{{ props.foo }}</div>
</template>

単純に与えられたデータを描画するだけのパーツコンポーネントなどは、関数型コンポーネントにしておくと、アプリのDOM描画が速くなります。

関数型コンポーネントは1回ロードするぐらいでは速度には影響ありませんが、ループで何十回と読み出すコンポーネントなどでは効果的です。

メインのCSSはindex.htmlにインラインで書く

Vue.jsに限ったことではないですが、HTMLのhead要素でlinkで呼び出す外部CSSは、レンダリングブロックの原因になります。

Vue.jsでは、コンポーネントにCSSを書くと、ビルド時に出力ファイルをindex.htmlにlink要素で追記する仕様なので、もれなくレンダリングブロックを引き起こします。

<link href="/css/app.d5cfc6b9.css" rel="preload" as="style">
<link href="/css/app.d5cfc6b9.css" rel="stylesheet">

こういうやつですね。一応preloadで先読みはしてくれていますが、別ファイルである以上レンダリングブロックは発生します。

ファイルサイズにもよりますが、CSSはindex.htmlのheadにインラインで記述することでレンダリングブロックを回避して、初期ロードを速くすることができます。


Vue.jsアプリの初期ロードを高速化するための方法をまとめてみました。

Vue.jsアプリの場合、どうしてもFirst Contentful Paintが遅くなってしまうので、離脱を防ぐためにも、こうした細かい設定をして、なるべく初期ロードを速くしたいところですね。