Next.jsの主要な技術、機能についてまとめ
目次
1. はじめに
Next.jsの勉強会に参加する機会があったので下調べ。
Next.jsはReact上で動作するフレームワークで、SSRやSSG、APIルーティングなどの多くの機能を備えています。本記事ではこれらの機能と、それを最大限に活用するための戦略について詳しく掘り下げていきます。
2. React: Next.jsの基盤
2.1. UIライブラリとしてのReact
Next.jsはReactの上に構築されており、Reactのコンポーネントベースの設計を利用してアプリケーションを構築します。
2.2. ReactとNext.jsの関係
Next.jsはReactの強力なUIライブラリの能力を拡張し、サーバーサイドレンダリングや静的サイト生成などの追加機能を提供します。
3. レンダリング技術と戦略
3.1. サーバーサイドレンダリング (SSR)
SSRはページロード時にサーバー上でページをレンダリングする技術です。具体的にはgetServerSideProps
を使用することで実現できます。
export async function getServerSideProps(context) {
return {
props: {} // ここにデータを渡す
}
}
戦略:
SSRを使用することで、ユーザーに対してより迅速にページを表示できます。しかし、サーバーのリソースが必要になるため、トラフィックの多いサイトでは適切なスケーリング戦略が必要です。
3.2. 静的サイト生成 (SSG)
SSGはビルド時にページを静的に生成する技術です。getStaticProps
とgetStaticPaths
を使用して実現します。
export async function getStaticProps(context) {
return {
props: {}, // ここにデータを渡す
revalidate: 10
}
}
戦略:
SSGを使用することで、サーバーのリソースを節約し、高速なページロードを実現できます。変わらないコンテンツや頻繁に更新されないページに特に適しています。
3.3. ISR (Incremental Static Regeneration)
ISRは静的生成されたページを動的に再生成する技術です。revalidate
オプションを使用して実現します。
export async function getStaticProps() {
return {
props: {},
revalidate: 60 // 1分後に再生成
};
}
3.4. 一般戦略
ISRは、SSGのメリットとリアルタイムのデータ更新のメリットを組み合わせたものです。一度静的に生成されたページは高速に提供され、revalidate
の間隔でデータを更新することができます。
Next.js で頻繁にデータが変わるサイトを運営する際の一般的な戦略をコード付きで説明します。
-
静的ページの生成とISRの組み合わせ:
一般的なブログのように、頻繁に新しい投稿が追加されるが、個々の投稿の内容はそんなに頻繁に変わらない場合、ISRを使用することができます。
// pages/posts/[id].js
function Post({ post }) {
return (
<div>
<h1>{post.title}</h1>
<p>{post.content}</p>
</div>
);
}
export async function getStaticPaths() {
const posts = await fetchPosts();
const paths = posts.map(post => ({ params: { id: post.id.toString() } }));
return {
paths,
fallback: true // 新しい投稿に対応
};
}
export async function getStaticProps({ params }) {
const post = await fetchPostById(params.id);
return {
props: { post },
revalidate: 10
};
}
export default Post;
-
新しいデータとのリアルタイムな対応:
よりリアルタイム性を求める場面では、
SWR
やクライアントサイドのデータフェッチを使用するのが一般的です。
// pages/dashboard.js
import useSWR from 'swr';
function Dashboard() {
const { data, error } = useSWR('/api/live-data', fetcher);
if (error) return <div>Error loading data</div>;
if (!data) return <div>Loading...</div>;
return (
<div>
<h1>Dashboard</h1>
<p>Live Data: {data.value}</p>
</div>
);
}
export default Dashboard;
-
完全なSSGと再ビルド:
サイトの内容があまり頻繁に変わらない場合や、高いパフォーマンスを求める場合、完全なSSGと周期的な再ビルドを選択することができます。
// pages/about.js
function About({ data }) {
return (
<div>
<h1>About Us</h1>
<p>{data.description}</p>
</div>
);
}
export async function getStaticProps() {
const data = await fetchData();
return {
props: { data }
};
}
export default About;
そして、変更があった場合、Webhook や CI/CD ツールを使用してサイトを自動的に再ビルドします。
最後に、どの戦略を選択するかは、アプリケーションの要件、利用者の期待、そして開発・運営の複雑さによって異なります。これらのアプローチは相互に排他的ではなく、一つのアプリケーション内で複数のアプローチを組み合わせることができます。
4. ルーティングとAPI
4.1. API Routes
API Routesは、pages/api/
ディレクトリ内に配置することで簡単にAPIエンドポイントを作成できる機能です。これらはローカル環境ではNode.jsサーバー上で動作し、デプロイ時にはVercel上でサーバーレス関数として変換されます。
// pages/api/hello.js
export default (req, res) => {
res.status(200).json({ text: 'Hello' })
}
戦略とメリット:
サーバーレス関数はリクエストに応じてスケールするため、リソースを節約しながらも高いパフォーマンスを維持することができます。サーバーレスは、維持費が低く、スケーラビリティが高いというメリットがあります。
4.2. Dynamic Routes
Next.jsは、ファイル名やディレクトリ名に[]
を使用することで動的なルーティングをサポートします。
// pages/posts/[id].js
import { useRouter } from 'next/router'
function Post() {
const router = useRouter()
const { id } = router.query
return <h1>Post: {id}</h1>
}
戦略:
動的ルーティングは、大量のページを持つサイトやアプリケーションでのルーティングを簡素化するために使用されます。例えば、ブログの各投稿や商品の詳細ページなど、パターンは同じでもコンテンツが異なるページに理想的です。
5. パフォーマンスと最適化
5.1. Fast Refresh
Fast Refreshは、開発中の即時フィードバックを可能にするNext.jsの機能です。コンポーネントの状態を維持したまま、変更を即座に反映させることができます。
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}
上記のようなカウンターコンポーネントを考えた場合、Fast Refreshによりカウントの状態は維持されたまま、他の部分のコードを変更・保存しても更新が即座に画面に反映されます。
5.2. Web Vitals
Web Vitalsは、ページのユーザーエクスペリエンスを測定するための主要な指標を提供します。Next.jsはこれらの指標を簡単に取得・表示するツールを組み込んでいます。
import { useWebVitals } from 'next/app'
function MyApp({ Component, pageProps }) {
useWebVitals(console.log)
return <Component {...pageProps} />
}
上記のコードは、Web Vitalsのデータをコンソールにログとして出力します。
5.3. Image Component & Image Optimization
Next.jsのImage
コンポーネントは、自動的な画像最適化をサポートしています。
import Image from 'next/image'
function MyComponent() {
return <Image src="/path/to/image.jpg" alt="Description" width={500} height={500} layout="responsive" />
}
layout
属性をresponsive
に設定することで、画像は親要素のサイズに応じて自動的にサイズ変更されます。
6. スタイリング
6.1. Styled JSX
Styled JSXは、コンポーネントレベルのスコープ付きCSSを実現します。
function MyComponent() {
return (
<div>
<p className="description">Styled with JSX</p>
<style jsx>{`
.description {
color: blue;
}
`}</style>
</div>
);
}
この方法で、.description
クラスはMyComponent
内でのみ有効となります。
6.2. CSS Modules
CSS Modulesは、スタイルのクラス名が一意になるように変換することで、スタイルの競合を回避します。
styles.module.css
:
.container {
padding: 20px;
background-color: #f9f9f9;
}
MyComponent.js
:
import styles from './styles.module.css'
function MyComponent() {
return <div className={styles.container}>Hello, Next.js!</div>
}
CSSモジュールは、スタイルが他のコンポーネントと干渉しないようにするための効果的な方法です。
7. 拡張性とカスタマイズ
7.1. Plugins and Integrations
Next.jsは多くのプラグインや統合をサポートしており、さまざまなツールやサービスと簡単に連携することができます。
7.2. Custom Configuration
next.config.js
ファイルを使用すると、Next.jsのデフォルトの設定をカスタマイズすることができます。