LoginSignup
0
0

【03】Next.js app routerのチュートリアルやってみる(フォントと画像の最適化)

Last updated at Posted at 2024-02-04

はじめに

Next.js app routerのチュートリアルの第3章のアウトプットします。

前の記事

【01】Next.js app routerのチュートリアルやってみる

https://qiita.com/naoyuki2/items/af58da3d20cbc790e767

【02】Next.js app routerのチュートリアルやってみる

https://qiita.com/naoyuki2/items/edf450b3ee135e83d1e8

第3章 フォントと画像の最適化

この章では下記を学習しました。

  • next/fontを利用して、カスタムフォントを追加する
  • next/imageを利用して、画像を追加する

next/font

next/fontを利用することで、ビルド時にフォントファイルをダウンロードすることができる。

これにより、パフォーマンスへの影響が少なくなる。

メインで使うフォントを追加する

fonts.ts

まず、フォントを管理するために/app/ui/fonts.tsファイルを作成する。

そして、下記を貼り付ける。

/app/ui/fonts.ts
import { Inter } from 'next/font/google';
 
export const inter = Inter({ subsets: ['latin'] });

subsetsというのは、使用する文字セットを指定するためのパラメータです。

これにより、必要な文字だけを含むフォントファイルをダウンロードすることができます。

上記のコードでは、subsets: ['latin']と指定しているため、Interのフォントはラテン文字のみダウンロードしています。

layout.tsx

メインフォントはすべてのページに適用させたいです。

そんな時は前回勉強したように、layout.tsxに記述をします。

/app/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>
  );
}

bodyclassNameinter.classNameと記述することで、このフォントがアプリケーション全体に適用されます。

antialiasedは、tailwindのクラスで、フォントを滑らかにするクラスだそうです。

下に比較画像を張ってみました。

上がデフォルトの文字で、

下がantialiasedを適用した文字だそうです。

正直違い分からん。

image.png

セカンダリフォントを追加する

fonts.ts

セカンダリフォントとして、Lusitanaフォントを使用するために/app/ui/fonts.tsファイルを編集する。

/app/ui/fonts.ts
+ import { Inter, Lusitana } from 'next/font/google';
 
export const inter = Inter({ subsets: ['latin'] });
 
+ export const lusitana = Lusitana({
+   weight: ['400', '700'],
+   subsets: ['latin'],
+ });

weightを指定しているのは、必要な文字の太さだけを指定してダウンロードすることで、不必要なデータのダウンロードを避け、パフォーマンスを向上させることができます。

でもLusitanaフォントはそもそも、weight400700のやつしかないんだけどね。

page.tsx

セカンダリフォントは使用したい要素にのみ、クラス名を割り当てます。

/app/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タグのclassNamelusitana.cassNameを記述しています。

これでフォントは完了です。

next/image

以下のことを自動で行ってくれるのがnext/imageコンポーネントです。

  • 画像読み込み時に自動的にレイアウトがずれるのを防ぐ
  • 小さなビューポートを備えたデバイスに大きな画像が送信されるのを避けるために、画像のサイズを変更する
  • デフォルトで画像を遅延読み込みします (画像はビューポートに入るときに読み込まれます)
  • ブラウザがサポートしている場合、AVIFやWebPなどの最新の形式で画像を提供する

next/iamgeを使用しない場合は、これらを手動ですることになるため大変です。

画像を配置してみよう

/app/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>
    //...
  );
}

上のコードは、チュートリアル公式のコードです。

ですが、widthheightを指定するのが、私は面倒なので他の方法を使います。

/app/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>
    //...
  );
}

下記の記事を参考にしたのですが、Next.js 11のアップデートにより、widthheightの指定が不要になったそうです。

画像をimportして、それをImageコンポーネントのsrcに指定することで、記述が楽になります。

公式でも書いてくれればいいのに。

おわりに

こういう最適化の積み重ねでWebアプリのパフォーマンスが上がるんでしょうね。

次の記事

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0