Next.js 13 を試してみた

2022.10.26

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

Next.js Conf 2022でNext.js 13の発表がありました。BlogなかでNext.js13の新機能まとまっていたので引用。

  • app/ Directory (beta): Easier, faster, less client JS.
  • Layouts
  • React Server Components
  • Streaming
  • Turbopack (alpha): Up to 700x faster Rust-based Webpack replacement.
  • New next/image (stable): Faster with native browser lazy loading.
  • New @next/font (beta): Automatic self-hosted fonts with zero layout shift.
  • Improved next/link: Simplified API with automatic <a> .

Next.js 13 Blog

かなり、魅力的な機能がたくさんです。

ディレクトリ構造がそのままパスルーティングされますが、Next.js 13ではReact18になり、SuspenseをつかったData FetchingやRenderingがいい感じにできるようになっているようです。

早速やってみます。

やってみた

今回は以下の2つの機能を試してみました。

今回のサンプルはこちらになります

サンプル作成

既存をマイグレーションせずに新規で作ります。

$ npx create-next-app nextjs13-sample --ts --use-npm

新規作成で、すでにNext.js 13になってるようです。

ただ、app/ Directory (beta) はbetaなのでnext.config.jsで有効化する必要があります

next.config.js

/** @type {import('next').NextConfig} */
const nextConfig = {
  reactStrictMode: true,
  swcMinify: true,
  experimental: {
    appDir: true,
  },
}
module.exports = nextConfig

appディレクトリに移す

新規作成時は従来通りの./pagesでルーティングが設定されてるので、appを有効化しても、pagesが存在するとエラーになってしまいます。ばっさり削除します。 appディレクトリを作成します。

$ rm -rf pages
$ mkdir app

いままでpagesには基本にはpageファイルだけで、アプリで共通の設定が_documentや_appなどでしたが、それが各ページ毎におけるようになったイメージです。

  • page.tsx: ページで読みこまれる(いままでpagesにおいていたファイル相当)
  • layout.tsx: ページ毎のレイアウト。
  • loading.tsx: Suspenseが発生した時のローディングView
  • error.tsx: Suspenseでエラーが発生したきのエラーView
  • template.tsx: レイアウトにてるけどちょっと違う。レイアウトは状態を維持するけどテンプレートは常に新しいインスタンスされ状態の引き継がない。
  • head.tsx: Head の設定

いままではindex.jsを読み込まれるようになってましたが、page.jsを読み込まれるようになります。

サンプルとしてGitHubのUsersを表示するページを作ります。

layoutを作成

基礎的なHtmlの雛形のlayoutで作成。

"

import { FC, PropsWithChildren } from "react";

const RootLayout: FC<PropsWithChildren> = ({ children }) => {
  return (
    <html lang="en">
      <head>
        <title>Next.js</title>
      </head>
      <body>{children}</body>
    </html>
  );
};

export default RootLayout;

loadingを作成

GitHub Users APIをfetchでSuspenseで読み込み、そのときのローディングViewを作成

"

export default function Loading() {
  return <div>Loading...</div>;
}

pageを作成

Reactのuseを使ってデータを表示します。(あれもうuseつかえるのか。。。)

"

import { use } from "react";

type User = {
  id: number;
  login: string;
};

const fetchUsers: () => Promise<User[]> = async () => {
  const res = await fetch("https://api.github.com/users");
  return res.json();
};

export default function Page() {
  const users = use(fetchUsers());
  return (
    <div>
      <h1>GitHub Users!</h1>
      <div>
        {users.map((user) => {
          return (
            <div key={user.id}>
              {user.id}: {user.login}
            </div>
          );
        })}
      </div>
    </div>
  );
}

実際に動かす

$ npm run dev

まとめ

React18のSuspenseがやはり起爆剤で、色々追加/変更がありますが、かなり嬉しい変化だと思っています。

Rustの影響でまた新たなビルドツールTurbopackもでてきましたし、変化が激しい時期がまだまだ続きそうですね。