Next.jsを学ぶために、Next.js公式のチュートリアルをやっていきます。
前回のチュートリアルはこちら。
初めからやる場合はこちらからどうぞ。
Next.jsのチュートリアルをやってみる【準備編】今回学ぶこと
next.font
モジュールでカスタムフォントを追加する方法next/image
モジュールで画像を追加する方法Next.js
でフォントと画像を最適化する方法
なぜフォントを最適化するのか?
カスタムフォントを使用すると、フォントファイルの取得や読み込みが必要になり、パフォーマンスに影響が出る可能性があるからです。
累積レイアウトシフトと呼ばれるウェブサイトのパフォーマンスとUXを評価するために使用するGoogleの指標があります。
フォントの場合レイアウトシフトは、ブラウザが最初にフォールバックフォントかシステムフォントでテキストをレンダリング、読み込み後にカスタムフォントに入れ替わった際に発生します。この入れ替えによってテキストのサイズ、間隔、レイアウトが変化して周囲の要素が移動することがあります。
Next.jsではnext/font
モジュールを使用すると、アプリケーション内のフォントを自動的に最適化します。ビルド時にフォントファイルをダウンロードして、ほかの静的アセットと一緒にホストするので、ユーザーがアクセスする際のパフォーマンスに影響するような追加ネットワークリクエストが発生しないのです。
プライマリフォントを追加する
アプリケーションにカスタムGoogleフォントを追加して、その動作を確認してみましょう。
/app/ui
フォルダにfonts.ts
という新しいファイルを作成して、以下のコードを追加しましょう。このファイルはアプリケーション全体で使用するフォントを保持するために使用します。
// Interフォントをインポート
import { Inter } from 'next/font/google';
// Interフォントのlatinサブセットを読み込む
export const inter = Inter({ subsets: ['latin'] });
続いて/app/layout.tsx
の<body>
要素にフォントを追加しましょう。
import '@/app/ui/global.css';
import { inter } from '@/app/ui/fonts';
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body className={`${inter.className} antialiased`}>{children}</body>
</html>
);
}
<body>
要素にInter
を追加することで、アプリケーション全体にフォントを適用することができます。ここではフォントを滑らかにするためにTailwindのantialiased
クラスも追加しています。必須ではありませんが、覚えておくといいでしょう。
セカンダリーフォント
アプリケーションの特定の要素のみにフォントを追加することもできます。
ではここで練習をしてみましょう。font.ts
ファイルでLusitana
というセカンダリーフォントをインポートし、/app/page.tsx
ファイルの<p>
要素に渡してみてください。先ほどと同じようにサブセットを指定して、さらにフォントのウェイトも指定する必要があります。
- ウェイトオプションが不明な場合は、コードエディタでTypeScriptのエラーを確認しましょう。
- Google Fontsにアクセスし、
Lusitana
を検索して利用可能なオプションを確認してください。 - Next.jsのドキュメントから複数のフォントの追加と、オプション一覧を確認してください
// Interフォントをインポート
import { Inter, Lusitana } from 'next/font/google';
// Interフォントのlatinサブセットを読み込む
export const inter = Inter({ subsets: ['latin'] });
// Lusitanaフォントのlatinサブセットを読み込む
export const lusitana = Lusitana({ weight: '400', subsets: ['latin'] });
import AcmeLogo from '@/app/ui/acme-logo';
import { ArrowRightIcon } from '@heroicons/react/24/outline';
import Link from 'next/link';
import styles from '@/app/ui/home.module.css';
import { lusitana } from './ui/fonts';
export default function Page() {
return (
// lusitanaのクラス名を追加
<p className={`${lusitana.className} text-xl text-gray-800 md:text-3xl md:leading-normal`}>
<strong>Welcome to Acme.</strong> This is the example for the{' '}
<a href="https://nextjs.org/learn/" className="text-blue-500">
Next.js Learn Course
</a>
, brought to you by Vercel.
</p>
// ...
);
}
また、AcmeLogoコンポーネントもLusitanaフォントを使用しており、エラー回避のためコメントアウトしていました。コメントを解除して確認してみてください。
// ...
export default function Page() {
return (
<main className="flex min-h-screen flex-col p-6">
<div className="flex h-20 shrink-0 items-end rounded-lg bg-blue-500 p-4 md:h-52">
<AcmeLogo />
{/* ... */}
</div>
</main>
);
}
以下の様にロゴが表示され文章のフォントが変化したら正解です。
なぜ画像を最適化するのか?
Next.jsは画像のような静的アセットをトップレベルの/public
フォルダの下に置くことができます。/public
内のファイルはアプリケーションから参照することができます。
通常、HTMLではこのように画像ファイルを使用します。
<img
src="/hero.png"
alt="Screenshots of the dashboard project showing desktop version"
/>
しかし、この場合、次のような作業を手作業で行わなければなりません。
- 画像がさまざまな画面サイズに対応するようにする。
- さまざまなデバイス用に画像サイズを指定する。
- 画像が読み込まれるときにレイアウトがずれないようにする。
- ユーザーのビューポート外にある画像を遅延ロードする。
画像の最適化は、ウェブ開発における大きな話題であり、それ自体が1つの専門分野とも言えます。 これらの最適化を手動で実装する代わりに、next/image
コンポーネントを使用することで画像を自動的に最適化することができるのです。
<Image>
コンポーネント
<Image>
コンポーネントはHTMLの<img>
タグを拡張したようなもので、次のような画像最適化機能を備えています。
- 画像の読み込み時に自動的にレイアウトがずれるのを防ぐ
- ビューポートが小さいデバイスに大きな画像を送らないように画像サイズを変更する
- デフォルトで画像を遅延読み込みする
- ブラウザがサポートしている場合、WebPやAVIFのような最新フォーマットで画像を提供する
デスクトップ用画像の追加
<Image>
コンポーネントを使用してみましょう。/public
フォルダの中を確認してみると、hero-desktop.png
とhero-mobile.png
の2つの画像があることがわかります。この二つの画像は全く異なるもので、ユーザーのデバイスによって表示されるものが変わります。
/app/page.tsx
ファイルでnext/image
からコンポーネントをインポートしましょう。その後、コメントの下に画像を追加して確認してみましょう。
import AcmeLogo from '@/app/ui/acme-logo';
import { ArrowRightIcon } from '@heroicons/react/24/outline';
import Link from 'next/link';
import { lusitana } from '@/app/ui/fonts';
import Image from 'next/image';
export default function Page() {
return (
// ...
<div className="flex items-center justify-center p-6 md:w-3/5 md:px-28 md:py-12">
{/* Add Hero Images Here */}
<Image
src="/hero-desktop.png"
width={1000}
height={760}
className="hidden md:block"
alt="Screenshots of the dashboard project showing desktop version"
/>
</div>
//...
);
}
hidden
はモバイルでアクセスされたら表示されないように、md:block
はデスクトップで表示するように設定するためのクラスです。
モバイル用画像の追加
ではここでモバイル用の追加で練習してみましょう。
先ほど追加した画像の下に、hhero-mobile.png
用の<image>
コンポーネントをもう一つ追加します。画像の幅は560px
、高さは620px
にしましょう。モバイル画面では表示され、デスクトップ画面では非表示になれば成功です。
ブラウザの開発者ツールでモバイル画面の確認ができますので、正しくなっているかを確認してみてください。
モバイル画面は以下の様になっているはずです。
まとめ
- ユーザーがアクセスする際のパフォーマンスやずれに影響するのでフォントや画像を最適化する必要がある。
<body>
タグにフォントを適用することで、アプリケーション全体にフォントを適用することができる。- Next.jsでは
<Image>
コンポーネントを使用して画像を読むと自動的に最適化される。