そのVue.jsのページ、本当に非同期コンポーネントで高速化できてる?


はじめに

この記事では、Vue.js(+ TypeScript)で作ったSPAページの初期描画の速度を改善したい時の取り組みの1つが紹介しています。

非同期コンポーネントという考えは理解できていたのですが、実際に試すと何だか遅くなったように感じられ、断念していました。
実は使い方が上手くなかったようで、その対処法が分かったのでまとめておきたいと思います。

prefetchを使うとコンポーネントがすでに読み込まれているのでページ遷移は速くなりますが、SPAサイトの初期描画が遅くなってしまうというトレードオフがありそうですね。
今回は、初期描画を高速化することにスポットを当てています。

TL;DR;

  • 公式ページにあるように、コンポーネントを非同期に呼び出して描画を高速化できるぞ!
  • それだけだとprefetchが行われて高速化しないので、vue.config.jsに1行追加するんやで!

非同期コンポーネント呼び出し

SPAのサイトですが、初期描画を改善したいので何か無いかなといろいろ試していたところでした。

非同期コンポーネントという考え方を発見し、公式ページを見た通りに試してみる。

まずは、これはTypeScriptでのオーソドックスな呼び出し方(たぶん)。

コンポーネントの同期読み込み
import MyComponent from "./MyComponent";

@Component({
  components: {
    MyComponent
  }
})

それに対して、次のように変更するだけで非同期コンポーネントが使用できますね。コードの変更は本当にこれだけ。

非同期読み込みに変更
- import MyComponent from "./MyComponent";

@Component({
  components: {
-     MyComponent
+     MyComponent: () => import("./MyComponent")
  }
})

という変更を行って、いざSPAページをリロードして表示してみると、今までには無かった謎のjsファイルの読み込みが。
どうやらこれが非同期読み込みすると起こるっぽい。

非同期コンポーネントの数だけ、jsが分割されてprefetchされる。(加えて、実際にコンポーネントが使用される時に prefetchじゃなく読み込まれる)
これで速くなったの、、、かな?

でも実際にロード時間を見てみると、何か体感遅くなってる???
並列読み込みが足りないのか?HTTP2 を使えという無言の圧力??

という感じで、良く分からなくなってしまったので一旦保留にして、作ったPRは閉じておきました。

prefetchを行わないようにする

それからしばらくして、ある記事を見つけました。こちらです。
How to make lazy loading actually work in Vue (CLI 3)

これや!これが欲しかったんや!
actually-workとか書いてあるし、記事のタイトルを見た瞬間にピーんと来てました、まじで。

ということで、記事にも書いてあるようにvue.config.jsにprefetchを制限するための1行を追加しましょう。

vue.config.js
chainWebpack: (config) => {
  config.plugins.delete("prefetch");  # この行を追加
  ...
}

この変更を適用させると、非同期コンポーネントのprefetchが無くなり、必要な時になったら必要なコンポーネントが読み込まれる仕組みにできました。

Matias Rodalさん、ありがたや。

おわりに

ということで、気になっていた非同期コンポーネントを使うと遅くなる問題が解決できたかなと思います。

必要な時に必要なものを用意する、というモノを持たない現代的な生き方にマッチした実装が出来そうです。

私生活でもミニマリスト的に暮らしてみたい。断捨離しよ。

以上