SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

Vercel+Next.jsを活用したWebアプリケーション開発入門

ブログを作りながら学ぶ、Next.jsの便利な4つの機能(グローバル設定、プリレンダリング、動的ルート、サーバーレス)

Vercel+Next.jsを活用したWebアプリケーション開発入門 第4回

  • X ポスト
  • このエントリーをはてなブックマークに追加

7. プリレンダリング

変更前ソース

機能概要

 Next.jsはプリレンダリングを行い、JavaScriptが無効な状態でも、ページのコンテンツを表示できます。一方、React.jsではすべての描写をJavaScriptで行うため、JavaScriptが無効の場合は何も表示がされません。

機能詳細

 Next.jsのプリレンダリングはさらに2つの方式があります。

  1. 静的生成(Static-site Generation(SSG))
  2. サーバーサイドレンダリング(Server-side Rendering(SSR))

 SSGの場合、ビルド時にすべてのHTMLを作成します。SSRの場合、WebサーバーにリクエストがあるたびにHTMLを作成します。

 パフォーマンスの観点では、SSGのほうがCDNで提供できるため優れています。Next.jsではSSGとSSRをページごとに選択できますので、基本はSSGで作成し、必要に応じてSSRを使うというような使い分けをするとよいでしょう。

 今回はSSGの実装を行います。

実装方法

 ブログのデータをファイルで用意します。

 「posts」フォルダを作成します(「pages/posts」ディレクトリとは別です)。

 「pre-rendering.md」と「ssg-ssr.md」2つのファイルを作成します。

 「pre-rendering.md」を編集します。

---
title: 'Two Forms of Pre-rendering'
date: '2020-01-01'
---

Next.js has two forms of pre-rendering: **Static Generation** and **Server-side Rendering**. The difference is in **when** it generates the HTML for a page.

- **Static Generation** is the pre-rendering method that generates the HTML at **build time**. The pre-rendered HTML is then _reused_ on each request.
- **Server-side Rendering** is the pre-rendering method that generates the HTML on **each request**.

Importantly, Next.js lets you **choose** which pre-rendering form to use for each page. You can create a "hybrid" Next.js app by using Static Generation for most pages and using Server-side Rendering for others.

 「ssg-ssr.md」を編集します。

---
title: 'When to Use Static Generation v.s. Server-side Rendering'
date: '2020-01-02'
---

We recommend using **Static Generation** (with and without data) whenever possible because your page can be built once and served by CDN, which makes it much faster than having a server render the page on every request.

You can use Static Generation for many types of pages, including:

- Marketing pages
- Blog posts
- E-commerce product listings
- Help and documentation

You should ask yourself: "Can I pre-render this page **ahead** of a user's request?" If the answer is yes, then you should choose Static Generation.

On the other hand, Static Generation is **not** a good idea if you cannot pre-render a page ahead of a user's request. Maybe your page shows frequently updated data, and the page content changes on every request.

In that case, you can use **Server-Side Rendering**. It will be slower, but the pre-rendered page will always be up-to-date. Or you can skip pre-rendering and use client-side JavaScript to populate data.

 開発サーバーを止めて、先ほどのファイルのメタデータを読むために次のnpmをインストールします。

npm install gray-matter

 「lib」フォルダを作成し、「posts.js」ファイルを作成します。

import fs from 'fs';
import path from 'path';
import matter from 'gray-matter';

const postsDirectory = path.join(process.cwd(), 'posts');

export function getSortedPostsData() {
  // posts ディレクトリのファイル一覧を取得
  const fileNames = fs.readdirSync(postsDirectory);
  const allPostsData = fileNames.map((fileName) => {
    // ".md" 拡張子を消してidとして読み込む
    const id = fileName.replace(/\.md$/, '');

    // ファイルを読み込む
    const fullPath = path.join(postsDirectory, fileName);
    const fileContents = fs.readFileSync(fullPath, 'utf8');

    // gray-matter でメタデータを取得
    const matterResult = matter(fileContents);

    // IDとメタデータを返す
    return {
      id,
      ...matterResult.data,
    };
  });
  // 投稿データを日付順でソートする
  return allPostsData.sort(({ date: a }, { date: b }) => {
    if (a < b) {
      return 1;
    } else if (a > b) {
      return -1;
    } else {
      return 0;
    }
  });
}

 「pages/index.js」に次のコードを追加します。

import Head from 'next/head';
import Layout, { siteTitle } from '../components/layout';
import utilStyles from '../styles/utils.module.css';
import { getSortedPostsData } from '../lib/posts'; // 新たにインポート

// パラメーターに allPostsData を追加
export default function Home({ allPostsData }) {
  return (
    // Layout に home であることを明示的に指定
    <Layout home>
      <Head>
        <title>{siteTitle}</title>
      </Head>
      <section className={utilStyles.headingMd}>
        <p>[Your Self Introduction]</p>
        <p>
          (This is a sample website - you’ll be building a site like this on{' '}
          <a href="https://nextjs.org/learn">our Next.js tutorial</a>.)
        </p>
      </section>
      {/* ブログの目次を表示する処理を追加 */}
      <section className={`${utilStyles.headingMd} ${utilStyles.padding1px}`}>
        <h2 className={utilStyles.headingLg}>Blog</h2>
        <ul className={utilStyles.list}>
          {allPostsData.map(({ id, date, title }) => (
            <li className={utilStyles.listItem} key={id}>
              {title}
              <br />
              {id}
              <br />
              {date}
            </li>
          ))}
        </ul>
      </section>
    </Layout>
  );
}

// 静的生成時にデータを取得する処理を追加
export async function getStaticProps() {
  const allPostsData = getSortedPostsData();
  return {
    props: {
      allPostsData,
    },
  };
}

 静的生成(SSG)時は「getStaticProps」で可変するデータを読み取ってページに埋め込むことができます。この時注意していただきたいのはあくまでもビルド時点に呼び出されるということです。

 「npm run dev」で動かしているときは利便性が重視され、ブラウザからのリクエスト毎にデータを読み込みます。開発時は動いたけど本番ではうまく動かないという時はこの点に注意してください。

 また、SSRの場合は「getServerSideProps」を同様に実装することでリクエスト毎にデータを読み込み、ページを動的に書き換えることが可能です。本記事ではSSRは取り扱いませんので、詳細は公式ドキュメントのgetServerSidePropsをご確認ください。

動作確認

 http://localhost:3000/をブラウザで開いて、次のように表示されます。

完成したソース

サンプルサイト

次のページ
8.動的ルート

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
Vercel+Next.jsを活用したWebアプリケーション開発入門連載記事一覧

もっと読む

この記事の著者

山本 誠樹(サイトコア株式会社)(ヤマモト マサキ)

 サイトコア株式会社 セールスグループ パートナーテクニカルイネーブルメントマネージャー。通信系システムや会員管理サービスの設計・開発から保守まで、システムエンジニアとして様々なプロジェクトに約20年従事。近年はクラウドにフォーカスしたコンサルティングを小売・流通・電力系など業種を問わず行う。201...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/16612 2022/10/07 11:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング