Nuxt3サイトを高速化するための7つの戦略
はじめに
Nuxt 3は、Vue.jsフレームワークに基づいた次世代のWebアプリケーションフレームワークです。
2022年にNuxt.2より大幅に改良されたNuxt3フレームワークは、Vue.jsの強力な機能を利用して、サーバーサイドレンダリング(SSR)、静的サイト生成(SSG)、シングルページアプリケーション(SPA)を容易に構築できるようになっています。Vue3より新たに採用されたComposition APIを標準搭載されており理解しやすく、TypeScriptで型安全に開発することができます。
Nuxt3の高速化にすべきこと
大規模サイトなどを構築していくと実装によってはパフォーマンスの低下が見られるのはどのフレームワークでも同じです。
PageSpeed Insights などを利用し、定期的に改修するようにいたしましょう。
PageSpeed Insightsは公開されたページでしか利用できない様なので、テスト環境やローカル環境などでチェックする場合はChrome のlighthouse を利用すると良いかと思います。(Developer Toolより利用できます)
ここでは改修する上での注意点や実装方法についてご紹介いたします。
調査する指標
上記のツールを利用するとPCとMobile両方を調査できますが、PCは基本的にそこまで難しくなくMobileはチューニングが大変です。基本的に共通はしますがターゲットデバイスによって調査してください。
基本的にはPerformanceタブのWebページのパフォーマンスを評価するために使用される主要なメトリックを中心にご紹介いたします。(下記はYahooを調査したもの)
First Contentful Paint(FCP)
ユーザーが最初にページ上のコンテンツ(テキスト、画像など)を表示するまでの時間
Good/NEEDS IMPROVEMENT/POOR=1.8sec/3.0sec/3.0sec〜
Largest Contentful Paint(LCP)
ユーザーが最初にページ上のコンテンツ(テキスト、画像など)を表示するまでの時間
Good/NEEDS IMPROVEMENT/POOR=2.5sec/4.0sec/4.0sec〜
Total Blocking Time (TBT)
ページの読み込み中にメインスレッドが長時間ブロックされていた時間の合計時間
Cumulative Layout Shift (CLS)
ページの視覚的な安定性を測定する指標です。ページのコンテンツが予期せずシフト(移動)する度合いを評価します。
Good/NEEDS IMPROVEMENT/POOR=0.1/0.25/0.25〜
Speed Index
ページのコンテンツがどれだけ速く視覚的に表示されるかを測定する指標
それでは具体的な対策方法をご紹介していきます。
Nuxt3を高速化する対策方法
(1) 画像サイズを指定する
画像のwidthとheight が指定されていないと、ブラウザが画像を読み取ってから画像表示領域を変更するため、レイアウトのずれなどが起こりにくくなります。
レスポンシブルに実装するのであれば下記の様にアスペクト比を指定して表示させましょう。(aspect-ratioが利用できるブラウザが対象かは別途調べてください)
.img { width: 100%; aspect-radio: 10/6; }
(2) WebPなどの軽量画像を利用する
Googleが開発した次世代画像フォーマットですが、2024年現在、多くの主要ブラウザで対応しています。
圧縮率が高く、軽量化ができるので使用してみましょう。
Nuxt3ではNuxt Image が標準搭載される様になっているので、こちらで対応しても良いかも知れません。(assetsフォルダは対応していませんでしたが)
(3) 表示に不要なコンポーネントを必要になるまで読み込まない
ファーストビューで不要なコンポーネントは下記の様にv-showではなく、v-ifにて表示させない様にしましょう。
<TextBtn v-if="isShow" />
また、Dynamic Importsを利用し、必要になるまで読み込まない様にすることも可能です(ComponentにLazyをつけるだけ)
<LazyTextBtn v-if="isShow" />
(4) 起動時のファイルを軽量化する
/_nuxt/entry.***.jsや/_nuxt/entry.***.css などは起動時にheadに埋め込まれ、読み込み・解析されるまで表示されない作りになっています。
上記のファイルはNuxt自体のコアなロジックに加え、composable,pluginやapp.ts,pages/index.tsで読み込まれるファイルが埋め込まれます。
不要なプログラムなどはdynamic importにて遅延読み込みをするといいでしょう
置き換え前
import { SomeThing } from "example";
置き換え前
const { SomeThing } = await import("example");
特に外部パッケージは容量が大きい場合があるので、必要に応じてmoduleをやめて、自分の必要な場所でのみimportすると良いかも知れません。
パッケージのバンドル状況は nuxi analyzeにて計測することができます。
(5) 外部パッケージをファイル分割
JSバンドルの分割のためのプラグインがViteにあるので、こちらを利用するといいでしょう。
import { splitVendorChunkPlugin } from 'vite'; export default defineNuxtConfig({ vite: { plugins: [splitVendorChunkPlugin()], }, });
参考: https://zenn.dev/toaru_fe/articles/5128fb6a6c21d2
(6) 頻繁にアクセスするURLにpreconnectを追加する
ユーザーが頻繁にアクセスする可能性のあるURLを記載することで、ブラウザが接続を最適化してくれます。
APIサーバーやリソースサーバー、GoogleなどのSaasサービスのサーバーなどあればnuxt.config.tsに記載しておくといいでしょう。
export default defineNuxtConfig({ app: { head: { link: { ref: "preconnect", href: "https://apis.google.com", }, }, }, });
参考: https://developer.mozilla.org/ja/docs/Web/HTML/Attributes/rel/preconnect
(7) 読み込む必要のないファイルはimport typeにてビルドインさせない
TypeScript 3.8より Type Only Importが可能になっています。
型情報のみimportすることでトランスパイル後のJSには含まれなくなるので、ファイルの軽量化が見込めます。
置き換え可能であれば積極的に対応していきましょう。
import type { SomeThing } from "example";
参考: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html
最後に
いかがでしたでしょうか?ページの高速化はPVやCNRも向上する可能性が大きいのでぜひ改良してみてください。