Next.jsでは、アセット類を最適化できるコンポーネントやロジックが提供されており、パフォーマンスの良さに定評があります。
画像の最適化
Imageコンポーネントを用いることで、下記のような最適化を行ってくれます。
- 最適な拡張子の画像が生成によるパフォーマンス向上
- レイアウトシフトの防止
- 遅延読み込みによる、ページの読み込み速度の最適化
使い方
next/image
からimportして使います。
import Image from 'next/image'
export const ImageContainer = () => (
<Image
// props
/>
)
Imageコンポーネントで使えるpropsの型は、ImageProps
でexportされております。
export declare type ImageProps = Omit<JSX.IntrinsicElements['img'], 'src' | 'srcSet' | 'ref' | 'width' | 'height' | 'loading' | 'style'> & {
src: string | StaticImport; // 画像のソース(ex: /images/test.png)
width?: number | string; // 画像の横幅(layout='fill'以外は必須)
height?: number | string; // 画像の高さ(layout='fill'以外は必須)
layout?: LayoutValue; // viewport を変更した時のレイアウト
loader?: ImageLoader; // 画像のURLを生成する関数
quality?: number | string; // 画質(0〜100, デフォ75)
priority?: boolean; // preloadするか (trueでページ遷移時にpreload)
loading?: LoadingValue; // 遅延ロードする ("lazy" | "eager")
lazyBoundary?: string; // 遅延読み込みをトリガーする閾値の設定(デフォ 200px)
placeholder?: PlaceholderValue; // プレースホルダーの形式("blur" | "empty", デフォ empty)
blurDataURL?: string; // placeholder="blur"の時のブラーする画像のURL
unoptimized?: boolean; // 最適化しないか (デフォ false - 最適化される)
objectFit?: ImgElementStyle['objectFit']; // layout='fill'の時のobject-fit
objectPosition?: ImgElementStyle['objectPosition']; // layout='fill'の時のobject-position
onLoadingComplete?: OnLoadingComplete; // 画像を完全ロード直後に実行されるコールバック関数
};
ものすごくオプションがたくさんありますが、基本的にはsrc
layout
width
height
を使います。
layoutモードに関して
layout
には、fill
fixed
intrinsic
responsive
の四種類あります。
fill
親の要素のwidth
/ height
に合わせて画像の幅と高さが設定される。
fixed
指定したwidth
/ height
に常に固定される。
responsive
指定したwidth
/ height
の比率は保ちながら、ビューポートに合わせてサイズが変わる。
intrinsic
responsive
と同じく、指定したwidth
/ height
の比率は保ちながら、ビューポートに合わせてサイズが変わるが、指定したwidth
は超えられない。
(筆者本人が神戸でとった写真だよ!天気が悪かったなぁ )
フォントの最適化
Next.js v10.2 以降から、webフォントが最適化されるようになりました。
最適化される内容としては、下記になります。
- フォントCSSを自動的にインライン化
- 表示の高速化
下記記事をみていただくとわかる通り、はんっぱなくLCPが改善されます。
すごい。
使い方
1. next/head
を使う
Headコンポーネント内でwebフォントを読み込むと最適化されます。
import Head from 'next/head'
export default page = () => {
return (
<div>
<Head>
<link
href="https://fonts.googleapis.com/css2?family=Inter&display=optional"
rel="stylesheet"
/>
</Head>
</div>
)
}
2. next/document
を使う
next/document
のHeadコンポーネントでwebフォントを読み込むと最適化されます。
import Document, { Html, Head, Main, NextScript } from 'next/document'
class MyDocument extends Document {
render() {
return (
<Html>
<Head>
<link
href="https://fonts.googleapis.com/css2?family=Inter&display=optional"
rel="stylesheet"
/>
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
)
}
}
export default MyDocument
スクリプトの最適化
Scriptコンポーネントを使うことで、スクリプトの読み込みを最適化することができます。
主に、計測・分析タグなどのサードパーティスクリプトの読み込みを最適化するために使います。
使い方
next/script
からimportして使います。
import Script from 'next/script'
export const ImageContainer = () => (
<Script src="https://www.google-analytics.com/analytics.js" />
)
Scriptコンポーネントで使えるpropsの型は、ScriptProps
でexportされております。
export interface ScriptProps extends ScriptHTMLAttributes<HTMLScriptElement> {
strategy?: 'afterInteractive' | 'lazyOnload' | 'beforeInteractive'; // 読み込みタイミング (デフォはafterInteractive)
id?: string; // 読み込みを順を最適するための追跡id
onLoad?: (e: any) => void; // ロード後に実行する関数
onError?: (e: any) => void; // エラー時に実行する関数
children?: React.ReactNode;
}
strategyに関して
strategy
には、afterInteractive
lazyOnload
beforeInteractive
の3種類あります。
順序は、beforeInteractive
→ afterInteractive
→ lazyOnload
です。
詳しいタイミングを説明します。
beforeInteractive
ページがインタラクティブになる前に実行されます。
(つまり、自分の書いたjavascriptよりも先に実行されることになります。)
下記のような重要なスクリプトに使われます。
- ボット検出
- cookieなどの同意管理
afterInteractive (デフォ値)
ページがインタラクティブになった後に実行されます。
下記のような重要なスクリプトに使われます。
- タグマネージャー
- 分析系のタグ
lazyOnload
すべてのリソースがフェッチされた後、アイドル時間中にロードされます。
このコードを本気で読解した記事を発見し、とても興味津々に読んでいたのですが、
よくみたら自分が大尊敬している会社の先輩の記事でした