Next.js 9.3
2020年3月9日(月)
投稿者:JJ Kasper @ _ijjk、Joe Haddad @ timer150、Luis Alvarez @ luis_fades、Shu Uesugi @ chibicode、Tim Neutkens @ timneutkens
本日、Next.js 9.3をご紹介できることを嬉しく思います。以下の機能を搭載しています:
- 次世代静的サイト生成(SSG)サポート:新しいデータ取得メソッドによる組み込み最適化静的生成
- プレビューモード:CMSからのドラフトを表示するために静的生成されたページをバイパス
- グローバルスタイルシート用の組み込みSassサポート:アプリケーションで.scssファイルをグローバルスタイルシートとして直接インポート可能
- コンポーネントレベルスタイル用の組み込みSass CSSモジュールサポート:.module.scss規約を活用し、ローカルスコープのCSSをアプリケーション内のどこでもインポートして使用可能
- 404の自動静的最適化:404ページを静的に提供することで速度と信頼性を向上
- 32kB小さなランタイム:強力な最適化により、すべてのNext.jsアプリケーションのランタイムサイズを削減
- GitHub DiscussionsのNext.jsコミュニティ:GitHubのNext.jsリポジトリから直接議論や質問が可能
これらの利点はすべて非破壊的で完全に後方互換性があります。更新するには以下を実行するだけです:
npm i next@latest react@latest react-dom@latest
次世代静的サイト生成(SSG)サポート
WebサイトやWebアプリケーションを構築する際、一般的に2つの戦略から選択する必要があります:静的生成(SSG)またはサーバーサイドレンダリング(SSR)。Next.jsは初のハイブリッドフレームワークで、ページごとに最適な技術を選択できます。
Next.js 9.0では自動静的最適化の概念を導入しました。ページにgetInitialPropsのようなブロッキングデータ取得要件がない場合、ビルド時に自動的にHTMLにレンダリングされます。
ブロッキングデータ取得要件があってもビルド時にページを静的HTMLにレンダリングしたい場合があります。例えば、(ヘッドレス)コンテンツ管理システム(CMS)で動作するマーケティングページやサイトのブログセクションなどです。
HashiCorpなどのSSGとnext exportのヘビーユーザーと協力し、Next.jsの歴史上最もコメントされたRFCでコミュニティと適切な制約について広範囲に議論し、データ取得と静的生成の新しい統一された方法を作成しました。
本日、2つの新しいデータ取得メソッドを発表できることを非常に嬉しく思います:getStaticPropsとgetServerSideProps。また、動的ルートの静的ページを静的生成するためのパラメータを提供する方法も含まれています:getStaticPaths。
これらの新しいメソッドは、SSGとSSRになるものの明確な区別があるため、getInitialPropsモデルよりも多くの利点があります。
- getStaticProps(静的生成):ビルド時にデータを取得
- getStaticPaths(静的生成):データに基づいて事前レンダリングする動的ルートを指定
- getServerSideProps(サーバーサイドレンダリング):各リクエストでデータを取得
これらの改善はAPI追加です。すべての新機能は完全に後方互換性があり、段階的に採用できます。非推奨は導入されず、getInitialPropsは現在と同様に機能し続けます。新しいページやプロジェクトではこれらの新しいメソッドの採用をお勧めします。
getStaticProps
ページからgetStaticPropsという非同期関数をエクスポートすると、Next.jsはビルド時にこのページを事前レンダリングします。これは、CMSから特定の静的ページをレンダリングしたい場合に特に有用です。
getStaticPropsは常にNode.jsコンテキストで実行され、コードは自動的にブラウザバンドルからtree-shakenされ、ブラウザに送信されるコードが少なくなります。これにより、Node.jsとブラウザ環境の両方でのデータ取得コードの実行について心配する必要がなくなります。これらの環境にはいくつかの不整合があります。
これにより、fetch、REST、GraphQL、さらにはデータベースへの直接アクセスを含む、任意の非同期または同期データ取得技術を使用できます。
export async function getStaticProps(context) {
return {
props: {},
};
}
contextパラメータは以下のキーを含むオブジェクトです:
- params:動的ルートを使用するページのルートパラメータを含みます。例えば、ページ名が
[id].jsの場合、paramsは{ id: ... }のようになります。詳細については、動的ルーティングドキュメントをご覧ください。これは後で説明するgetStaticPathsと一緒に使用する必要があります。
以下は、getStaticPropsを使用してCMSからブログ投稿のリストを取得する例です:
import fetch from 'node-fetch';
function Blog({ posts }) {
return (
<ul>
{posts.map((post) => (
<li>{post.title}</li>
))}
</ul>
);
}
export async function getStaticProps() {
const res = await fetch('https://.../posts');
const posts = await res.json();
return {
props: {
posts,
},
};
}
export default Blog;
getStaticPropsを使用すべき場合
以下の場合にgetStaticPropsを使用すべきです:
- ページをレンダリングするために必要なデータがユーザーのリクエストより前のビルド時に利用可能
- データがヘッドレスCMSから来る
- データが公開キャッシュ可能(ユーザー固有でない)
- ページが事前レンダリングされ(SEOのため)、非常に高速である必要がある —
getStaticPropsはHTMLとJSONファイルの両方を生成し、どちらもパフォーマンスのためにCDNでキャッシュできます
getStaticPropsの詳細については、データ取得ドキュメントを参照してください。
getStaticPaths
ページが動的ルートを持ち、getStaticPropsを使用する場合、ビルド時にHTMLにレンダリングする必要があるパスのリストを定義する必要があります。
動的ルートを使用するページからgetStaticPathsという非同期関数をエクスポートすると、Next.jsはgetStaticPathsで指定されたすべてのパスを静的に事前レンダリングします。
export async function getStaticPaths() {
return {
paths: [
{ params: { ... } }
],
fallback: true or false
};
}
pathsキー(必須)
pathsキーは事前レンダリングされるパスを決定します。例えば、pages/posts/[id].jsという動的ルートを使用するページがあるとします。このページからgetStaticPathsをエクスポートし、pathsに以下を返すとします:
return {
paths: [
{ params: { id: 1 } },
{ params: { id: 2 } }
],
fallback: ...
}
すると、Next.jsはpages/posts/[id].jsのページコンポーネントを使用してビルド時にposts/1とposts/2を静的生成します。
各paramsの値はページ名で使用されるパラメータと一致する必要があることに注意してください:
- ページ名が
pages/posts/[postId]/[commentId]の場合、paramsはpostIdとcommentIdを含む必要があります
- ページ名がキャッチオールルートを使用する場合(例:
pages/[...slug])、paramsは配列であるslugを含む必要があります。例えば、この配列が['foo', 'bar']の場合、Next.jsは/foo/barでページを静的生成します
fallbackキー(必須)
getStaticPathsによって返されるオブジェクトは、ブール値のfallbackキーを含む必要があります。
Fallback: false
fallbackがfalseの場合、getStaticPathsによって返されないパスは404ページになります。これは、すべてのパスがビルド時に既知であることがわかっている場合に有用です。
以下は、pages/posts/[id].jsというページごとに1つのブログ投稿を事前レンダリングする例です。ブログ投稿のリストはCMSから取得され、getStaticPathsによって返されます。その後、各ページでgetStaticPropsを使用してCMSから投稿データを取得します。
import fetch from 'node-fetch';
function Post({ post }) {
}
export async function getStaticPaths() {
const res = await fetch('https://.../posts');
const posts = await res.json();
const paths = posts.map((post) => `/posts/${post.id}`);
return { paths, fallback: false };
}
export async function getStaticProps({ params }) {
const res = await fetch(`https://.../posts/${params.id}`);
const post = await res.json();
return { props: { post } };
}
export default Post;
Fallback: true
fallbackがtrueの場合、getStaticPropsの動作が変わります。Next.jsは提供されたパスをビルド時にHTMLにレンダリングします。ビルド時に生成されなかったパスは、ユーザーがページをリクエストしたときにオンデマンドで生成されます。
これは、アプリケーションに静的生成可能な多くのルートがあるが、サブセットのみをビルド時に生成することでページのビルド時間の増加を避けたい場合に有用です。
ページの生成をトリガーするユーザーには、フォールバックHTMLが提供されます。これは一般的にローディング状態のページです。これは、静的HTMLがCDNから提供でき、まだ生成されていない場合でもページが常に高速であることを保証するためです。
オンデマンドで追加ページを静的生成する例:
import { useRouter } from 'next/router';
import fetch from 'node-fetch';
function Post({ post }) {
const router = useRouter();
if (router.isFallback) {
return <div>Loading...</div>;
}
}
export async function getStaticPaths() {
return {
paths: [{ params: { id: 1 } }, { params: { id: 2 } }],
fallback: true,
};
}
export async function getStaticProps({ params }) {
const res = await fetch(`https://.../posts/${params.id}`);
const post = await res.json();
return { props: { post } };
}
export default Post;
getStaticPathsの詳細については、データ取得ドキュメントを参照してください。
getServerSideProps
ページからgetServerSidePropsという非同期関数をエクスポートすると、Next.jsは各リクエストでこのページをレンダリングします(SSR)。
getServerSidePropsは常にサーバーサイドで実行され、コードは自動的にブラウザバンドルからtree-shakenされ、ブラウザに送信されるコードが少なくなります。これにより、サーバーとブラウザ環境の両方でのデータ取得コードの実行について心配する必要がなくなります。これらの環境にはいくつかの不整合があります。
サーバーは一般的にデータソースへの高速接続を持つため、多くの場合パフォーマンスが向上します。また、データ取得ロジックの露出を減らすことでセキュリティも向上します。
これにより、fetch、REST、GraphQL、さらにはデータベースへの直接アクセスを含む、任意の非同期または同期データ取得技術を使用できます。
next/linkを使用してページ間を移動する場合、ブラウザでgetServerSidePropsを実行する代わりに、Next.jsはサーバーにfetchを行い、getServerSidePropsの呼び出し結果を返します。
export async function getServerSideProps(context) {
return {
props: {},
};
}
contextパラメータは以下のキーを含むオブジェクトです:
- params:このページが動的ルートを使用する場合