Next.jsの新しいルーティングシステムとNested Layoutsの実装について調べてみた
こんにちは。データアナリティクス事業本部 サービスソリューション部の北川です。
Next.jsで、新しいルーティングシステムについての記事が公式から出ました。
今回は中でも、ようやく提案されたNested Layoutsについて調べたので、まだ正式に実装されたわけではないですが、せっかくなので記事にしました。
Appフォルダの提供
Next.jsでは、pagesフォルダの配下に作成したファイルが、そのままURLのパスとして機能します。
新しいルーティングシステムでは、pagesフォルダではなく、機能追加に対して段階的に変更できるよう、新しくappフォルダを提供する考えのようです。そのため、appフォルダとpagesフォルダは併用できそうです。アップデートによる修正や更新の負担が減るので、これはありがたいです。もちろんpagesフォルダ同様、階層を下げてパスを指定できます。
pagesフォルダと違う点は、appフォルダではファイルではなく、フォルダが一つのパスとして機能するようです。これによる利点は、フォルダの配下にファイルを作成したとしても、そのファイルは一つのページとして認識されない点にあります。そのため、一つのページでしか使用しないUIコンポーネントのファイルや、hooksのファイルをフォルダ配下におけるようになります。
pageExtensions
pagesフォルダでも、pageExtensions機能を使用することで、実装が可能です。
/** @type {import('next').NextConfig} */ const nextConfig = { reactStrictMode: true, // 「.bar.tsx」、「.foo.tsx」のファイルがページとして認識される pageExtensions: ["bar.tsx", "foo.tsx"] } module.exports = nextConfig
上記の例だと、拡張子が「.bar.tsx」と「.foo.tsx」のファイルのみページとして認識され、「index.tsx」のようなファイルはパスとして機能しなくなります。
Nested Layouts
NestedLayoutsは、共通部分をまとめたレイアウトを階層ごとに作成することで、その配下のページで複数のレイアウトを適用することができます。Remixでは初期の頃からこの仕様を提供しており、Next.jsとの大きな比較部分でした。
getLayout
一応、Next.jsでレイアウトの分岐を行うには、getLayout()を使用してページごとにレイアウトを指定する方法がありました。
import "../styles/globals.css"; import type { AppProps } from "next/app"; import { NextPage } from "next"; import { ReactElement, ReactNode } from "react"; type NextPageWithLayout = NextPage & { getLayout?: (page: ReactElement) => ReactNode; }; type AppPropsWithLayout = AppProps & { Component: NextPageWithLayout; }; function MyApp({ Component, pageProps }: AppPropsWithLayout) { const getLayout = Component.getLayout || ((page) => { return page; }); return getLayout(<Component {...pageProps} />); } export default MyApp;
const Sample = () => { return ( <> ... </> ); } export default Sample; // LayoutAを適用 Sample.getLayout = LayoutA;
Layouts
レイアウトでは、ファイル内で共通で使うUIを提供します。レイアウトを作成した階層(サブツリー)内のセグメント間で共有できます。レイアウトはパスに影響を与えず、ユーザーがページ間を移動しても再レンダリングされないです。
layout.jsファイルを作成し、コンポーネント内をラッピングすることで機能します。
import { Header } from "layouts/header/header"; import { Footer } from "layouts/footer/footer"; import type { ReactChild } from "react"; export const Layout = ({ children }: {children: ReactChild}) => { return ( <> <Header /> <main> {children} </main> <Footer/> </> ); };
import { Layout } from "../layouts/layouts"; const Sample = () => { return ( <Layout> ... </Layout> ); }; export default Sample;
レイアウトは2つのタイプを提供します。
- Root layout
- Regular layout
2つ以上のレイアウトを入れ子にすることで、Nested Layouts機能を実装できます。
Root layout
ルートレイアウトは、すべてのページに共通するUI、設定を記述します。_appフォルダの直下に、layout.jsを作成することでルートレイアウトとして機能します。これは、_app.jsと_document.jsの大替として提供されるようです。また、、タブのカスタマイズもできます。
Regular layout
特定のフォルダ内に、layout.jsを作成することで通常のレイアウトとして機能します。一部のページにのみ、共通化させるレイアウトを実装したい場合に使用します。
ルートレイアウト、レギュラーレイアウトを組み合わせたり、レギュラーレイアウトを複数作成することで、ネストされたレイアウトを実装することができます。
まとめ
今回は、Nested Layoutsについて、調べてみました。今後の意向が容易になると思うので、これから新規にNext.jsを使用する場合は、pageExtensionsを設定しておくといいのかなと思いました。今後、どのように機能が追加されていくのか楽しみです。
ではまた。