SSR

Server-Side Rendering

SSR

今度は「SSR」、つまり「サーバーサイドレンダリング」の話をしましょう。これまた、だいぶヤバいやつですよね〜(褒め言葉)。SSR(Server-Side Rendering)は、サーバー側でウェブページの内容をレンダリング(表示)する方法です。

例えば、レストランのウェブサイトがあります。お店のメニューや場所、営業時間などの情報が載っています。ウェブサイトを作る際、2 つの方法があります。

  1. サーバーでウェブページを準備して、そのままお客さん(ブラウザ)に見せる(SSR)
  2. お客さん(ブラウザ)がウェブページを組み立てる(クライアントサイドレンダリング)

SSR の場合、お客さんに見せる前に、ウェブページがサーバーで作られます。これにより、お客さんはすぐに情報を見ることができます。

もう少し分かりやすく説明する

SSRはウェブページをサーバー上で生成するテクニックで、クライアント(ユーザーのブラウザ)がリクエストすると、サーバーは完成したHTMLを送ります。これが「サーバーサイドレンダリング」、つまりSSRの基本です。なんでこれが便利かっていうと、ユーザーがページを見るのが早くなるんですよ。なぜなら、ブラウザは完成品のHTMLを受け取ってすぐ表示できるからです。

これをまた例え話で説明すると、レストランで料理を頼むときにシェフがその場で料理を作り始める感じです。ユーザーが「ページを見せて」と頼むと、サーバーはその場でページ(=料理)を作って、すぐに提供します。そうすることで、ユーザーは待ち時間なくすぐに料理(=ページ)を楽しめます。

ただ、いつも注文ごとに料理を作ると、シェフ(=サーバー)にとっては結構大変ですよね。そこでNext.jsではSSRと静的サイト生成(SSG)を組み合わせる方法が提供されています。これを使うと、一部のページは予め作っておいて(=SSG)、一部は注文が入ったときに作る(=SSR)という、ベストなバランスを保てます。

一体どういうことなん?って思いますよね。でも、SSRをうまく活用することで、ユーザーが待つ時間を減らすことができます。そして、Next.jsのSSRとSSGの組み合わせを使うと、サーバーの負荷も考えながら、最良のユーザーエクスペリエンスを提供できます。凄くないですか?ここまで大丈夫ですか?SSR、試してみる価値は大いにありますよ!

実装

ソースコードの例を見てみましょう。Node.js と Express を使ったサーバーで、SSR を実装しています。

const express = require('express')
const app = express()

app.get('/', (req, res) => {
  const pageTitle = 'レストランのウェブサイト'
  const pageContent = '<h1>ようこそ!</h1><p>ここにはメニューや場所、営業時間などの情報があります。</p>'

  const html = `
    <!DOCTYPE html>
    <html>
      <head>
        <title>${pageTitle}</title>
      </head>
      <body>
        ${pageContent}
      </body>
    </html>
  `

  res.send(html)
})

app.listen(3000, () => {
  console.log('サーバーが起動しました!')
})

このコードでは、サーバーが / のリクエストを受け取った時、ウェブページの HTML を組み立ててお客さん(ブラウザ)に送ります。これが SSR の仕組みです。お客さんはすぐにウェブページの情報を見ることができます。

Next.js は、ウェブサイトを作るためのツールです。Next.js を使うと、簡単に SSR(Server-Side Rendering)を実現できます。SSR は、サーバー側でウェブページの内容を作って、お客さん(ブラウザ)に送る方法です。これによって、お客さんはすぐにウェブページの情報を見ることができます。

Next.js で SSR を使ったウェブページを作る方法を、例を使って説明します。例えば、ペットショップのウェブサイトがあります。ペットの種類や名前、値段などの情報が載っています。

Next.js のプロジェクトで、pagesフォルダの中にpetshop.jsというファイルを作ります。そして、以下のようなコードを書きます。

// ペットのデータを取得する関数
async function fetchPetData() {
  // ここでは、ペットのデータをサーバーから取得しています。
  // 実際のプロジェクトでは、APIを使ってデータを取得することが多いです。
  const petData = [
    { name: 'ワンちゃん', type: '犬', price: '10,000円' },
    { name: 'ニャンちゃん', type: '猫', price: '12,000円' },
  ]
  return petData
}

// Next.js の getServerSideProps 関数を使って、ペットのデータを取得します。
export async function getServerSideProps() {
  const petData = await fetchPetData()
  return {
    props: {
      petData,
    },
  }
}

function PetShop({ petData }) {
  return (
    <div>
      <h1>ペットショップ</h1>
      <ul>
        {petData.map((pet) => (
          <li key={pet.name}>
            {pet.name}{pet.type}- {pet.price}
          </li>
        ))}
      </ul>
    </div>
  )
}

export default PetShop

このコードでは、getServerSideProps関数を使って、ペットのデータをサーバー側で取得しています。その後、PetShopコンポーネントでデータを表示しています。これが Next.js での SSR の仕組みです。お客さん(ブラウザ)には、すでにペットの情報が表示されたウェブページが送られます。

Next.js と TypeScript を使って、SSR(Server-Side Rendering)を実現する方法を説明します。例として、図書館のウェブサイトがあります。本のタイトルや著者、出版年などの情報が載っています。

まず、Next.js のプロジェクトで TypeScript を使うために、tsconfig.jsonファイルを作成し、以下のように設定します。

{
  "compilerOptions": {
    "target": "es5",
    "lib": ["dom", "dom.iterable", "esnext"],
    "allowJs": true,
    "skipLibCheck": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "preserve",
    "esModuleInterop": true
  },
  "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
  "exclude": ["node_modules"]
}

次に、pagesフォルダの中にlibrary.tsxというファイルを作成し、以下のようなコードを書きます。

// TypeScriptで型定義を作成します。
type Book = {
  title: string
  author: string
  year: number
}

// 本のデータを取得する関数
async function fetchBookData(): Promise<Book[]> {
  const bookData: Book[] = [
    { title: 'ねじまき鳥クロニクル', author: '村上春樹', year: 1994 },
    { title: 'ハリー・ポッターと賢者の石', author: 'J.K.ローリング', year: 1997 },
  ]
  return bookData
}

// Next.js の getServerSideProps 関数を使って、本のデータを取得します。
export async function getServerSideProps() {
  const bookData: Book[] = await fetchBookData()
  return {
    props: {
      bookData,
    },
  }
}

// TypeScriptでpropsの型を定義します。
type LibraryProps = {
  bookData: Book[]
}

const Library = ({ bookData }: LibraryProps) => {
  return (
    <div>
      <h1>図書館のウェブサイト</h1>
      <ul>
        {bookData.map((book) => (
          <li key={book.title}>
            {book.title}{book.author}- {book.year}</li>
        ))}
      </ul>
    </div>
  )
}

export default Library

このコードでは、TypeScript を使って本のデータの型定義を作成し、fetchBookData関数で本のデータを取得しています。その後、Next.js のgetServerSideProps関数を使って、サーバー側で本のデータを取得し、Libraryコンポーネントでデータを表示しています。

これが Next.js と TypeScript を使った SSR(Server-Side Rendering)の仕組みです。お客さん(ブラウザ)には、すでに本の情報が表示されたウェブページが送られます。

この例では、TypeScript の型定義を使ってコードの品質を向上させています。型定義によって、データの構造が明確になり、エラーを未然に防ぐことができます。

Next.js と TypeScript を組み合わせることで、ウェブ開発がより簡単で安全になります。開発者は、SSR を簡単に実現し、同時にコードの品質を向上させることができます。これによって、お客さんはすばやく情報を得ることができ、開発者は安心してコードを書くことができます。