Next.js(App Router)のnext/fontでGoogleフォントをセルフホスティング
はじめに
- Next.js の Font Optimization(フォント最適化)について紹介します。
- 実際のプロジェクトを作成し、Google フォント をでフォント最適化します。
- TailwindCSS で Google フォントを利用する方法も紹介します。
今回の作業結果は以下にあります。
フォント最適化
next/font
を利用することで、サイトで使用するフォントが自動的に Next.js サーバでセルフホスティングされます。これにより、これまで追加でフォントをダウンロードするために発生していた通信が削減され、ページの読み込み速度が向上します。Google フォントの場合は、ブラウザから Google への通信が発生しなくなり、通信量が削減されます。
公式サイト
環境を構築
プロジェクトを新規に作成します。
$ pnpm create next-app@latest nextjs-next-font-sample --typescript --eslint --import-alias "@/*" --src-dir --use-pnpm --tailwind --app
$ cd nextjs-next-font-sample
不要な設定を削除し、クリーンアップします。
クリーンアップ
以下の通り上書きします。
@tailwind base;
@tailwind components;
@tailwind utilities;
export default function Home() {
return (
<main className="">
テストページ
</main>
)
}
import "./globals.css";
export const metadata = {
title: "Create Next App",
description: "Generated by create next app",
};
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="ja">
<body className="">{children}</body>
</html>
);
}
ローカルサーバで動作確認します。
$ pnpm dev
$ pnpm build
$ git add .
$ git commit -m "delete unnecessary files"
next/font
を単一ページで利用
next/font
を実際に使ってみます。ここでは、特定ページのみでフォントを適用する方法を紹介します。
以下のフォントを利用します。
-
next/font/google
からRampart_One
をimport
します。 -
weight
は400
を指定します。 -
subsets
はlatin
を指定します。(japanese
を指定するとタイプエラーになります。)
import { Rampart_One } from "next/font/google";
const RampartOneFont = Rampart_One({
weight: "400",
subsets: ["latin"],
});
export default function Home() {
return (
<main className="">
<div className={RampartOneFont.className}>人類社会のすべての構成員の固有の尊厳と平等で譲ることのできない権利とを承認することは</div>
</main>
)
}
以下の通りフォントが適応されました。
コミット
$ pnpm build
$ git add .
$ git commit -m "add google font to single page"
next/font
を複数ページで利用
ページの全体あるいは特定のページの塊にフォントを紹介します。
以下のように layout.tsx
を修正することで、layout.tsx
が適応される複数ページに対してフォントを適用できます。
import "./globals.css";
+import { Hachi_Maru_Pop } from "next/font/google";
+const HachiMaruPopFont = Hachi_Maru_Pop({ weight: "400", subsets: ["latin"] });
export const metadata = {
title: "Create Next App",
description: "Generated by create next app",
};
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="ja">
- <body className="">{children}</body>
+ <body className={HachiMaruPopFont.className}>{children}</body>
</html>
);
}
1 行を追加して、layout.tsx
で指定されたフォント、page.tsx
の単体ページで指定されたフォントの違いが分かるようにします。
import { Rampart_One } from "next/font/google";
const RampartOneFont = Rampart_One({
weight: "400",
subsets: ["latin"],
});
export default function Home() {
return (
<main className="text-4xl">
+ <div>人類社会のすべての構成員の固有の尊厳と平等で譲ることのできない権利とを承認することは</div>
<div className={RampartOneFont.className}>人類社会のすべての構成員の固有の尊厳と平等で譲ることのできない権利とを承認することは</div>
</main>
)
}
正しく適応されていることが確認できます。
コミット
$ pnpm build
$ git add .
$ git commit -m "add google font to layout"
Tailwindを利用する場合
next/font
を TailwindCSS と組み合わせることで、TailwindCSS から Google フォントを指定できます。ここでは TailwindCSS と next/font
を組み合わせ利用する方法について紹介します。
page.tsx
を以下のように修正し、Google フォントを削除します。
-import { Rampart_One } from "next/font/google";
-const RampartOneFont = Rampart_One({
- weight: "400",
- subsets: ["latin"],
-});
export default function Home() {
return (
<main className="text-4xl">
<div>人類社会のすべての構成員の固有の尊厳と平等で譲ることのできない権利とを承認することは</div>
- <div className={RampartOneFont.className}>人類社会のすべての構成員の固有の尊厳と平等で譲ることのできない権利とを承認することは</div>
+ <div className="">人類社会のすべての構成員の固有の尊厳と平等で譲ることのできない権利とを承認することは</div>
</main>
)
}
- リファクタリングとして、
DotGothic16Font
をlayout.tsx
に移動させます。 - CSS Variable を定義します。
- CSS Variable を<body>に追加します。
import "./globals.css";
-import { Hachi_Maru_Pop } from "next/font/google";
+import { Hachi_Maru_Pop, Rampart_One } from "next/font/google";
-const HachiMaruPopFont = Hachi_Maru_Pop({ weight: "400", subsets: ["latin"] });
+const HachiMaruPopFont = Hachi_Maru_Pop({
+ weight: "400",
+ subsets: ["latin"],
+ variable: "--font-HachiMaruPop",
+});
+const RampartOneFont = Rampart_One({
+ weight: "400",
+ subsets: ["latin"],
+ variable: "--font-RampartOne",
+});
export const metadata = {
title: "Create Next App",
description: "Generated by create next app",
};
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="ja">
- <body className={`${HachiMaruPopFont.variable} ${RampartOneFont.variable}`}>
+ <body className={`${HachiMaruPopFont.variable} ${RampartOneFont.variable}`}>
{children}
</body>
</html>
);
}
TailwindCSS でフォントを呼び出せるように、TailwindCSS の設定で、フォントを拡張します。
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
"./src/pages/**/*.{js,ts,jsx,tsx,mdx}",
"./src/components/**/*.{js,ts,jsx,tsx,mdx}",
"./src/app/**/*.{js,ts,jsx,tsx,mdx}",
],
theme: {
extend: {
backgroundImage: {
"gradient-radial": "radial-gradient(var(--tw-gradient-stops))",
"gradient-conic":
"conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))",
},
+ fontFamily: {
+ HachiMaruPop: ["var(--font-HachiMaruPop)"],
+ RampartOne: ["var(--font-RampartOne)"],
+ },
},
},
plugins: [],
};
layout.tsx
はさらに修正します。ポイントは、className
にて font-MPlusRounded1cFont
でフォントを指定しているところです。
import "./globals.css";
import { Hachi_Maru_Pop, Rampart_One } from "next/font/google";
const HachiMaruPopFont = Hachi_Maru_Pop({
weight: "400",
subsets: ["latin"],
variable: "--font-HachiMaruPop",
});
const RampartOneFont = Rampart_One({
weight: "400",
subsets: ["latin"],
variable: "--font-RampartOne",
});
export const metadata = {
title: "Create Next App",
description: "Generated by create next app",
};
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="ja">
- <body className={`${HachiMaruPopFont.variable} ${RampartOneFont.variable}`}>
+ <body className={`${HachiMaruPopFont.variable} ${RampartOneFont.variable} font-HachiMaruPop`}>
{children}
</body>
</html>
);
}
正しく適応されていることが確認できます。
コミット
$ pnpm build
$ git add .
$ git commit -m "integrate with TailwindCSS"
利用するフォントについて
Google フォントの利用において、next/font
で最高のパフォーマンスを出すためには、Variable fontsの使用が公式として推奨されています。
フォントの再利用について
特定のフォントを複数箇所で再利用する場合は、const
で定義し export
することで、再利用が可能になります。フォントを export
で共有しない場合、同一のフォントのインスタンスがサーバ上で複数作成されることになります。(公式ページを参照)
まとめ
- Next.js の Font Optimization(フォント最適化)について紹介しました。
- 実際のプロジェクトを作成し、Google フォント をでフォント最適化しました。
- TailwindCSS で Google フォントを利用する方法も紹介しました。
今回の作業結果は以下にあります。
Discussion