今回は自己研鑽の時間でNext.jsを触ってみたので、紹介したいと思います。
目次
- 目次
- Next.js -- Reactベースのフロントエンドフレームワーク
- Next.jsの開発の始め方
- Vercel -- ホスティングサービス
- Vercelを利用し、テンプレートを起動
- 1: https://vercel.com/ へアクセスし、 TryVercel を選択
- 2: ログインに使用するアカウントを選択。今回はGithubを選択
- 3: ログイン後 Clone Template にてテンプレートをクローンできるので、一番基本となるテンプレートの Next.js を選択
- 4: 作成先のリポジトリ名を決め、Createを選択。今回は nextjs にします。
- 5: ログインしたGithubプロジェクトにテンプレートをクローンできている事を確認
- 6: ローカルPCにテンプレートコードをクローンし、インストールと起動を実行
- 7. http://localhost:3000 へアクセスし、テンプレートが表示されれば成功
- Next.jsの基本的な解説
- Next.jsの強み
- まとめ
Next.js -- Reactベースのフロントエンドフレームワーク
Reactをベースとした、Node.jsで起動するフロントエンドフレームワーク
Next.jsの強み
- ファイル名から自動でルーティング
- SSR と SSG をページ毎に設定可能
他にもいくつかありますが、今回はこちらの2つにフォーカスして解説していきたいと思います。
Next.jsの開発の始め方
おすすめはVercelを利用する方法です。
Vercel -- ホスティングサービス
- Next.jsの開発元であるVercelが作成したプラットフォーム
- ビルドやホスティングが可能なサービス
- 自動SSL化、サブドメインが自由に設定できるなど無料でも機能豊富
- 無料でテンプレートが複数提供されている
今回は、Vercelのテンプレートを利用して始めます。
Vercelを利用し、テンプレートを起動
1: https://vercel.com/ へアクセスし、 TryVercel
を選択
2: ログインに使用するアカウントを選択。今回はGithubを選択
3: ログイン後 Clone Template
にてテンプレートをクローンできるので、一番基本となるテンプレートの Next.js
を選択
4: 作成先のリポジトリ名を決め、Createを選択。今回は nextjs
にします。
5: ログインしたGithubプロジェクトにテンプレートをクローンできている事を確認
6: ローカルPCにテンプレートコードをクローンし、インストールと起動を実行
$ npm i $ npm run dev
7. http://localhost:3000 へアクセスし、テンプレートが表示されれば成功
これで開発する準備が整いました。
Next.jsの基本的な解説
以下のようなディレクトリ構成をしています。
$ tree . ├── README.md ├── next.config.js ├── node_modules ├── package-lock.json ├── package.json ├── pages │ ├── _app.js │ ├── api │ └── index.js ├── public │ ├── favicon.ico │ └── vercel.svg └── styles ├── Home.module.css └── globals.css
テンプレートに表示されている通り、 pages/index.js
がページの本体のComponentになります。
# pages/index.js import Head from 'next/head' import Image from 'next/image' import styles from '../styles/Home.module.css' export default function Home() { return ( <div className={styles.container}> <Head> <title>Create Next App</title> <meta name="description" content="Generated by create next app" /> <link rel="icon" href="/favicon.ico" /> </Head> <main className={styles.main}> <h1 className={styles.title}> Welcome to <a href="https://nextjs.org">Next.js!</a> </h1> (省略) ) }
Next.jsの強み
ファイル名から自動でルーティング
https://localhost:3000
のにアクセスした時に、 pages/index.js
のComponentを呼ぶようにルーティングされています。
これはNext.jsの特徴で、pagesに格納したComponentファイルは、ゼロコンフィグでアプリケーションのルーティングを構成する事ができます。
デフォルトでは pages
が対象になっていますが、 src/pages
に配置しても動作します。好みで移動させましょう。
静的ページを作成
試しにページを追加してみます。
pages/hoge/fuga.js
を作成した場合、 https://localhost:3000/hoge/fuga
が自動でルーティングされます。
# pages/hoge/fuga.js export default function Fuga() { return <p>fuga</p> }
また、Fast Refreshという機能により自動でファイルの変更やルーティングの追加を反映してくれるのでサーバーを再起動する必要もありません。便利ですね。
新規コンポーネントへのリクエスト時に自動でコンパイルをしてくれているのが確認できます。
動的ページを作成
ファイル名を [fruit].js
のように角括弧で記述することで動的なルート指定が可能になります。
この場合、 pages/:fruit
のリクエストがルーティングされます。
next/router
の useRouter
機能を使用することで fruit を取得できます。
# pages/[fruit].js import {useRouter} from 'next/router' export default function Fruit() { const router = useRouter() const {fruit} = router.query return <p>あなたの選んだフルーツは{fruit}です!</p> }
http://localhost:3000/apple
でアクセスしてみると、動的にページ生成が行えている事が確認できます。
Rest APIを作成
同じように、Rest APIの作成も可能です。
テンプレートコードの pages/api/hello.js
の中身を確認してみます。
export default function handler(req, res) { res.status(200).json({ name: 'John Doe' }) }
jsonで返却するだけでAPIを作ることができます。
自動でルーティングされるので、この場合は https://localhost:3000/api/hello
にアクセスすることでjsonで返却ができます。
簡単なAPIの作成も、特にモジュールなどのインストール無く実装することができます。
SSR と SSG をページ毎に設定可能
一般的なフレームワークは、サービス全体でSSGとするかSSRとするかしか選択できません。
それに対し、Next.jsはページ毎に指定が可能な事が大きな特徴になります。
SSR と SSG について簡単に解説した後、Next.jsでページ毎に設定する方法を解説します。
server-side rendering (SSR)
リクエストを受けてから、サーバーでHTMLを生成する一般的な方法。
最新の情報で常にHTMLを生成できるため、ユーザー認証が必要なページ等に向いています。
ただし、毎回HTMLを生成する関係上レンダリングを毎回行うのでCPU負荷が高く、応答速度も遅めです。
static-side generation (SSG)
サーバー側で事前にHTMLを生成しておき、リクエストを受けた時に返却する方法。
事前にHTMLを生成しているため、応答速度が高くレンダリングを行わないためCPU負荷も低いです。
ただし、事前にビルドしたタイミングでコンテンツを生成している関係上最新のページに更新したい場合はビルドを実行し直す必要があります。そのため、リアルタイム性が求められるページには不向きです。
SSRとSSGのメリット、デメリット
HTML生成方法 | リアルタイム性 | 応答速度 |
---|---|---|
SSR | 常にリアルタイム | 遅い |
SSG | ビルド時に依存 | 早い |
特徴が違うため、ページ毎に適切に生成方法を変える事ができれば快適なWebサイトを作成できます。
Next.jsではページ毎に生成方法を指定できるため、実際にやってみます。
Next.jsでページ毎に設定
テンプレートの package.json
を確認してみましょう。
"scripts": { "dev": "next dev", "build": "next build", "start": "next start", "lint": "next lint" },
next build
のコマンドが存在します。このコマンドを実行する事で、HTMLファイルを事前に静的生成できます。
いくつか静的生成時に使えるAPIを紹介します。
getStaticProps
静的生成時に外部APIを実行し、データを取得できるAPI。
今まで作成していたcomponentと同一ファイルに記述する事で、ビルド時にAPIの実行など外部データの取得を行うことができます。
GitHubAPIを使い、toranoanaの名称を取ってくるコードを書いてみます。
export async function getStaticProps() { const res = await fetch('https://api.github.com/users/toranoana'); const resJson = await res.json(); return { props: { resJson } } } export default function Github(props) { return <p>{ props.resJson.name }</p> }
ビルドを実行します。
$ npm run build Page Size First Load JS ┌ ○ / 5.57 kB 76.5 kB ├ └ css/149b18973e5508c7.css 655 B ├ /_app 0 B 70.9 kB ├ ○ /[fruit] 365 B 71.3 kB ├ ○ /404 194 B 71.1 kB ├ λ /api/hello 0 B 70.9 kB ├ ● /github (370 ms) 286 B 71.2 kB └ ○ /hoge/fuga 269 B 71.2 kB
左側のマークはそれぞれ以下を表しており、 github
は ●
のアイコンなので静的生成されており、ページ毎に違う生成方法が指定できている事が確認できます。
λ (Server) server-side renders at runtime (uses getInitialProps or getServerSideProps) ○ (Static) automatically rendered as static HTML (uses no initial props) ● (SSG) automatically generated as static HTML + JSON (uses getStaticProps)
サーバーを起動し、 http://localhost:3000/github
にアクセスする事で静的生成されたtoranoanaの名称が取得できました。
getStaticPaths
静的生成時に動的ルートのページを生成するAPI。
例えば先程の pages/[fruit].js
などを静的生成する場合に使用します。
受け取った文字列をjsonで返却するAPIと、それを呼び出し静的生成するコードを書いてみます。
# pages/api/test/[test].js export default function handler(req, res) { const { query: { test } } = req; res.status(200).json({ "apiName": test }) }
# pages/test/[test].js export async function getStaticPaths() { const params = [ { params: { test: "toranoana" } }, { params: { test: "yumenosora" } } ]; return { paths: params, fallback: false }; } export async function getStaticProps({ params }) { const res = await fetch(`http://localhost:3000/api/test/${params.test}`); const resJson = await res.json(); return { props: { resJson } }; } export default function Test(props) { return <p>{ props.resJson.apiName }</p> }
npm run build
で実行し、2つのページが生成されている事を確認します。
Page Size First Load JS ┌ ○ / 5.57 kB 76.5 kB ├ └ css/149b18973e5508c7.css 655 B ├ /_app 0 B 70.9 kB ├ ○ /[fruit] 365 B 71.3 kB ├ ○ /404 194 B 71.1 kB ├ λ /api/hello 0 B 70.9 kB ├ λ /api/test/[test] 0 B 70.9 kB ├ ● /github (385 ms) 292 B 71.2 kB ├ ○ /hoge/fuga 269 B 71.2 kB └ ● /test/[test] 291 B 71.2 kB ├ /test/toranoana └ /test/yumenosora
- /test/toranoana
- /test/yumenosora
が静的生成されている事が確認できます。
今回は固定値を入れましたが、ここを外部APIにする事で記事の数だけ事前生成などが可能になるので非常に便利です。
Vercelにデプロイする
余談ですが、既にVercelからテンプレートコードを取得したのでリポジトリがVercelに認識されサーバーが作成されている状態になります。DOMAINS を選択すると、サーバーが確認できます。
更新をリポジトリに反映することで、Vercel上のサーバーも更新されるため確認してみます。
今までの編集内容を test
ブランチに反映し、 main
ブランチに向けてプルリクエストを出します。
そうするとVercel上からプルリクエストの確認とプレビューサーバーが確認できるようになります。中身を確認し、今回の編集が反映されているか確認してみましょう。
1: Vercelの Deployments を開き、今回作成したプルリクエストがある事を確認
2: 選択し、DOMAINSを選択でプレビューサーバーを起動して今回の編集が反映されていることを確認
無事Vercel上でも作成した api/[fruit]
が表示された事を確認できました。
あとはmainブランチにマージすれば、本番デプロイ完了です。
まとめ
Next.jsはシンプルながら、強力なフロントエンドフレームワークです。
本稿で紹介したものは一部にすぎません。Vercelを使うことで気軽に体験する事もできるので、是非簡単なページ作成からNext.jsを試してみて下さい。
P.S.
虎の穴ラボでは、私たちと一緒に新しいオタク向けサービスを作る仲間を募集しています。
詳しい採用情報は以下をご覧ください。
yumenosora.co.jp