はじめに
Next.js app routerのチュートリアルの第3章のアウトプットします。
前の記事
【01】Next.js app routerのチュートリアルやってみる
https://qiita.com/naoyuki2/items/af58da3d20cbc790e767
【02】Next.js app routerのチュートリアルやってみる
第3章 フォントと画像の最適化
この章では下記を学習しました。
-
next/font
を利用して、カスタムフォントを追加する -
next/image
を利用して、画像を追加する
next/font
next/font
を利用することで、ビルド時にフォントファイルをダウンロードすることができる。
これにより、パフォーマンスへの影響が少なくなる。
メインで使うフォントを追加する
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
に記述をします。
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
は、tailwind
のクラスで、フォントを滑らかにするクラスだそうです。
下に比較画像を張ってみました。
上がデフォルトの文字で、
下がantialiased
を適用した文字だそうです。
正直違い分からん。
セカンダリフォントを追加する
fonts.ts
セカンダリフォントとして、Lusitana
フォントを使用するために/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
フォントはそもそも、weight
が400
と700
のやつしかないんだけどね。
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.cassName
を記述しています。
これでフォントは完了です。
next/image
以下のことを自動で行ってくれるのがnext/image
コンポーネントです。
- 画像読み込み時に自動的にレイアウトがずれるのを防ぐ
- 小さなビューポートを備えたデバイスに大きな画像が送信されるのを避けるために、画像のサイズを変更する
- デフォルトで画像を遅延読み込みします (画像はビューポートに入るときに読み込まれます)
- ブラウザがサポートしている場合、AVIFやWebPなどの最新の形式で画像を提供する
next/iamge
を使用しない場合は、これらを手動ですることになるため大変です。
画像を配置してみよう
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>
//...
);
}
上のコードは、チュートリアル公式のコードです。
ですが、width
とheight
を指定するのが、私は面倒なので他の方法を使います。
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のアップデートにより、width
とheight
の指定が不要になったそうです。
画像をimport
して、それをImage
コンポーネントのsrc
に指定することで、記述が楽になります。
公式でも書いてくれればいいのに。
おわりに
こういう最適化の積み重ねでWebアプリのパフォーマンスが上がるんでしょうね。
次の記事
参考