[3]Next.jsチュートリアルを進められたのでやってみる(3)フォントと画像の最適化

# はじめに

今回の記事では、Next.jsチュートリアル第3章「フォントと画像の最適化」を進めていきます。

https://nextjs.org/learn/dashboard-app/optimizing-fonts-images

#### 前回の記事

https://qiita.com/2201009-kikukawa/items/c15429dadc555ae2b7a9

## chapter3:フォントと画像の最適化

この章では以下の内容について学ぶことができます。

- `next/font/`を使用してカスタムフォントを追加する方法
- `next/image`で画像を追加する方法
- Next.jsでフォントと画像がどのように最適化されるか

## next/font

`next/font`を使用することで、ビルド時にフォントファイルをダウンロードし他の静的アセットとともにホストすることができます。これによりパフォーマンスへの影響が少なくなります。

### プライマリーフォントの追加

#### fonts.ts
メインで使用するフォントを設定するために、`/app/ui`フォルダー内に新しい`fonts.ts`ファイルを作成し以下のコードを貼り付けます。
```fonts.ts
import { Inter } from 'next/font/google';
 
export const inter = Inter({ subsets: ['latin'] });

```
`subsets`とは使用する文字セットを設定するためのパラメーターです。
今回はlatinなので Interのフォントはラテン語のみをダウンロードしています。

#### layout.tsx
プライマリーフォントはアプリケーション全体に設定したいです。
そのため前回の学習でも使用した、layout.tsxに下記のコードを追加します。
```layout.tsx
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`の`className`に`inter.className`を設定することで、フォントがアプリケーション全体に適用されます。
また`antialiased`はフォントを滑らかにするクラスで使用は必須ではないですが、使用すると便利だそうです。

## セカンダリフォントを追加する
セカンダリフォントとしてLusitanaを使用するためにfonts.tsファイルを編集します。
```fonts.ts
import { Inter,Lusitana } from 'next/font/google';

 
export const inter = Inter({ subsets: ['latin'] });

export const lusitana = Lusitana({
    weight: ['400', '700'],
    subsets: ['latin'],
  })
```
```page.tsx
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';//追加
 
export default function Page() {
  return (
    // ...
    <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>
    // ...
  );
}
```
今回は`<p>`タグに対して`Lusitana`を適用したいので`<p>`の`className`に`lusitana.className`を追加し、`import { lusitana } from '@/app/ui/fonts'`を`import`しています。

これで2種類のフォントをアプリケーションに適用することができました。

## next/image
このコンポーネントはHTMLの`<img>`タグの拡張で、以下の内容を自動でおこなってくれます。
- **レイアウトのずれ防止**: 画像の読み込み時にレイアウトがずれるのを防ぎます
- **画像サイズの自動調整**: 小さなビューポートを持つデバイスに対して大きな画像を送信することを避け、画像のサイズを自動で調整します
- **遅延読み込み**: デフォルトで画像を遅延読み込みします。画像はビューポートに入るまで読み込まれません
- **最新の画像形式サポート**: ブラウザがサポートされている場合、WebPやAVIFなどの最新の画像形式で画像を提供します

普段、画像のサイズなどは手動で設定すると特定のPCでは、ずれてしまったりなど面倒な作業だったのでかなりありがたいコンポーネントですね。

### 画像を追加してみる
早速next/imageを使用して画像を追加してみます

```page.tsx
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>
    //...
  );
}
```
これは公式のやり方なのですが、このチュートリアルを教えてくれた人からもっと簡単なコードを教えてもらったので紹介します。

```page.tsx
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';

import hero_desktop from '../public/hero-desktop.png'

 
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}

           alt="Acme Hero Image Desktop"

           className="hidden md:block"

       />

    </div>
    //...
  );
}
```
画像自体を`import`しそれを`image`コンポーネントの`src`に設定することで`width`と`height`の設定が不要になったとのことです。この方法の方が記述がわかりやすくて良いですね！

## おわりに
今回の記事ではカスタムフォントの追加方法、画像の最適化について学習しました。
next/fontコンポーネントかなり便利ですね。今後Next.jsを使っての開発では何回もお世話になりそうな機能なのでしっかりと理解しておく必要がありそうですね。

## 次の記事