当サイトは、アフィリエイト広告を利用しています

【Gatsby × contentful】遅延静的生成 (DSG)の使い方

作成日:2023月11月26日
更新日:2023年11月26日

Gatsbyのv4から使えるようになった遅延静的生成 (DSG) を
Gatsby製の当ブログで導入したので、その実装方法をGatsbyの
ページ生成パターン別にまとめる。

遅延静的生成 (DSG)とは何か?

遅延静的生成 (DSG)とはGatsbyのレンダリングオプションの一つ

Gatsbyでは基本的にはSSGでbuild時にページを生成しているが、
DSGでは指定したページの生成をbuild時ではなく、ユーザーのリクエストがあって
はじめて行うようにすることができる

DSGのメリット

DSGはbuild時ではなく、初リクエスト時にページ生成が
行われるので下記のようなメリットがある

build時間の短縮

大規模なWEBサイトやホームページなどでは大量のページがあれば
すべてのページをビルド時に生成すると、ビルド時間が非常に長くなってしまう

そこでDSGを使用すると、ビルド時には必要なページだけを生成し
残りのページはユーザーがアクセスしたときに初めて生成することで
ビルド時間を大幅に短縮でき、ウェブサイトのパフォーマンスを向上させることができる

リソースの効率的な利用

アクセス頻度の低いページのbuildをDSGでユーザーアクセス時まで
遅延させることでリソースを効率的に利用することができる

DSGのデメリット

DSGでbuild時ではなく、初リクエスト時にページ生成することによる
デメリットは下記のような感じ

SSGに比べて高速でなくなる

ページ初回アクセス時に生成されるため
SSGよりもわずかに速度が遅くなる

DSGの使いどころ

メリット、デメリットを踏まえると

  • アクセスが少ないページ
  • 重要度が低いページ

に対してDSGを使うのが良さそうだ

GatsbyのDSGを使う

実際にGatsbyのDSGを使ってみる

Gatsbyにはページ生成の方法が

  • src/pagesディレクトリのjsxファイルを元に静的ページを生成
  • createPagesAPIを使って動的にページを作成
  • FileSystemRouteAPIを使って動的にページを作成

の3つあるので
それぞれでDSGを使う方法をまとめる

環境

環境としては下記のような感じ
ベースは下記の記事で使ったプロジェクトを変更していくので
よかったらご参照ください

package.json
{
"dependencies": {
"@babel/preset-react": "^7.17.12",
"@emotion/babel-plugin": "^11.9.2",
"@emotion/react": "^11.9.0",
"@emotion/styled": "^11.8.1",
"@mdx-js/mdx": "1.6.22",
"@mdx-js/react": "1.6.22",
"dotenv": "^16.0.2",
"gatsby": "^4.14.1",
"gatsby-plugin-emotion": "^7.14.0",
"gatsby-plugin-feed": "^4.14.0",
"gatsby-plugin-gatsby-cloud": "^4.14.0",
"gatsby-plugin-google-analytics": "^4.14.0",
"gatsby-plugin-image": "^2.24.0",
"gatsby-plugin-manifest": "^4.14.0",
"gatsby-plugin-mdx": "3.20.0",
"gatsby-plugin-offline": "^5.14.1",
"gatsby-plugin-react-helmet": "^5.14.0",
"gatsby-plugin-sharp": "^4.14.1",
"gatsby-remark-copy-linked-files": "^5.14.0",
"gatsby-remark-images": "^6.14.0",
"gatsby-remark-prismjs": "^6.14.0",
"gatsby-remark-responsive-iframe": "^5.14.0",
"gatsby-remark-smartypants": "^5.14.0",
"gatsby-source-contentful": "^7.21.1",
"gatsby-source-filesystem": "^4.14.0",
"gatsby-transformer-sharp": "^4.14.0",
"prismjs": "^1.28.0",
"react": "^17.0.1",
"react-dom": "^17.0.1",
"react-helmet": "^6.1.0",
"typeface-merriweather": "0.0.72",
"typeface-montserrat": "0.0.75"
},
"devDependencies": {
"prettier": "^2.6.2"
},
}

色々はいってはいるが、Gatsbyがv4以上であればDSGは使える

src/pagesディレクトリのjsxファイルを元に静的ページを生成でDSG

まずはpages配下の静的に生成されるページを
DSGで遅延静的生成させてみる

DSG対象

DSGの対象となるのは下記になる

DSG対象
.
|-- pages
| |-- 404.js
| |-- about.jsx
| |-- index.jsx
| |-- using-typescript.tsx

pages配下の

  • index.jsx

を対象にする

index.jsxの編集

src/pagesディレクトリのjsxファイルを元に静的ページを生成する場合は
ファイル内で

  • deferキーを持つオブジェクトを返す非同期関数config

をエクスポートする必要がある

index.jsx
import * as React from "react"
import { Link, graphql } from "gatsby"
// 記事一覧ページ
const BlogIndex = ({ data }) => {
const nodeList = data.allContentfulBlogPost.edges
return (
<div>
{nodeList.map(({ node }) => {
return (
<div>
<Link to={node.slug}>{node.title}</Link>
</div>
)
})}
</div>
)
}
export default BlogIndex
// contentfulから情報取得
export const pageQuery = graphql`
query {
allContentfulBlogPost {
edges {
node {
title
slug
}
}
}
}
`
// DSGの設定関数
export async function config() {
return () => {
return {
defer: true,
}
}
}

これでbuild時にDSG対象として認識してくれるようになる。

DSGされているか確認

実際にDSGの対象になっているか確認する

確認方法は「gatsby build」と「gatsby serve」を実行すれば
確認できる
※「gatsby build」では確認できないので注意!!

「gatsby build」を実行する

確認
Pages
┌ src/pages/404.js
│ ├ /404/
│ └ /404.html
├ src/pages/about.jsx
│ └ /about/
├ src/pages/index.jsx
│ └ D /
╭────────────────────────────────────────────────────────────────╮
│ │
│ (SSG) Generated at build time │
│ D (DSG) Deferred static generation - page generated at runtime │
│ ∞ (SSR) Server-side renders at runtime (uses getServerData) │
│ λ (Function) Gatsby function │
│ │
╰────────────────────────────────────────────────────────────────╯

上記のようなログがでる
DSG対象としている「src/pages/index.jsx」に
「D」がついているのが確認できる

「gatsby serve」を実行する

確認
gatsby serve
You can now view gatsby-starter-blog in the browser.
http://localhost:9000/

起動したので画面を確認すると
2023-11-21-00-17-23 画面表示は問題なくできている

createPagesAPIを使って動的にページを作成でDSG

gatsby-node.js内でcreatePagesAPIを使って
動的に作成するページをDSGで遅延静的生成させてみる

DSG対象

DSGの対象となるのは下記になる

DSG対象
.
`-- templates
`-- contentfulPost.jsx

templates配下の

  • contentfulPost.jsx

を対象にする

gatsby-node.jsの編集

createPagesAPIはgatsby-node.jsで使用しているので
DSGの設定もgatsby-node.js内で行う

gatsby-node.js
const path = require(`path`)
exports.createPages = async ({ graphql, actions }) => {
const { createPage } = actions
// contentful記事のkeyを取得
const contentfulAirticleResult = await graphql(`
query airticleQuery {
allContentfulBlogPost {
edges {
node {
slug
}
}
}
}
`)
const contentfulAirticle =
contentfulAirticleResult.data.allContentfulBlogPost.edges
//記事数分ループして記事ページを作成する
contentfulAirticle.forEach(({ node }) => {
createPage({
path: `${node.slug}/`, //記事ページのurl
component: path.resolve(`./src/templates/contentfulPost.jsx`), //記事ページ作成のtemplateコンポーネント
//templateコンポーネントに渡す引数
context: {
slug: node.slug,
},
defer: true,
})
})
}

createPageに渡すオブジェクトに「defer」属性を作り
「true」にすればDSG対象として認識してくれる

DSGされているか確認

実際にDSGの対象になっているか確認する

「gatsby build」を実行する

確認
Pages
┌ src/templates/contentfulPost.jsx
│ ├ D /gatsby-contentful-page-filesystemrouteapi/
│ └ D ...157 more pages available
├ src/pages/404.js
│ ├ /404/
│ └ /404.html
├ src/pages/about.jsx
│ └ /about/
├ src/pages/index.jsx
│ └ D /
└ src/pages/using-typescript.tsx
└ /using-typescript/
╭────────────────────────────────────────────────────────────────╮
│ │
│ (SSG) Generated at build time │
│ D (DSG) Deferred static generation - page generated at runtime │
│ ∞ (SSR) Server-side renders at runtime (uses getServerData) │
│ λ (Function) Gatsby function │
│ │
╰────────────────────────────────────────────────────────────────╯

上記のようなログがでる
今回指定した分が追加で「D」がついているので
DSGされているのが確認できる

FileSystemRouteAPIを使って動的にページを作成でDSG

Gatsbyのv4から導入されたFileSystemRouteAPIを使って
動的に生成しているページをDSGで遅延静的生成させてみる

DSG対象

DSGの対象となるのは下記になる

DSG対象
|-- pages
| |-- 404.js
| |-- about.jsx
| |-- index.jsx
| |-- using-typescript.tsx
| `-- {ContentfulBlogPost.slug}.jsx

pages配下の

  • {ContentfulBlogPost.slug}.jsx

を対象にする

createPagesAPIで作っていたページを
FileSystemRouteAPIを使うように変更しているので
pages配下に

  • {ContentfulBlogPost.slug}.jsx

を作成している
※合わせてgatsby-node.jsでのcreatePagesは削除している

「FileSystemRouteAPI」については下記記事でまとめている

{ContentfulBlogPost.slug}.jsxの編集

FileSystemRouteAPIでDSGを使用する場合は

  • deferキーを持つオブジェクトを返す非同期関数config

をエクスポートする必要がある

{ContentfulBlogPost.slug}.jsx
import React from "react"
import { graphql, Link } from "gatsby"
import MDXConvert from "../components/mdxConvert"
const ContentfulPost = ({ data }) => {
const post = data.allContentfulBlogPost.edges[0].node
const { body } = post
return (
<div>
<MDXConvert>{body.childMdx.body}</MDXConvert>
</div>
)
}
export default ContentfulPost
// gatsby-node.jsのcreatePageから渡されたslugを元にGraphQLで記事と
// その目次データ取得する
export const query = graphql`
query Query($slug: String!) {
allContentfulBlogPost(filter: { slug: { eq: $slug } }) {
edges {
node {
body {
childMdx {
tableOfContents
body
}
}
}
}
}
}
`
//deferキーを持つオブジェクトを返す非同期関数config
export async function config() {
return () => {
return {
defer: true,
}
}
}

deferキーを持つオブジェクトを返す非同期関数configを追加することで
DSG対象として認識してくれる

DSGされているか確認

実際にDSGの対象になっているか確認する

「gatsby build」を実行する

確認
Pages
┌ src/pages/404.js
│ ├ /404/
│ └ /404.html
├ src/pages/about.jsx
│ └ /about/
├ src/pages/index.jsx
│ └ D /
├ src/pages/using-typescript.tsx
│ └ /using-typescript/
└ src/pages/{ContentfulBlogPost.slug}.jsx
├ D /gatsby-contentful-page-filesystemrouteapi/
└ D ...157 more pages available
╭────────────────────────────────────────────────────────────────╮
│ │
│ (SSG) Generated at build time │
│ D (DSG) Deferred static generation - page generated at runtime │
│ ∞ (SSR) Server-side renders at runtime (uses getServerData) │
│ λ (Function) Gatsby function │
│ │
╰────────────────────────────────────────────────────────────────╯

上記のようなログがでる
FileSystemRouteAPIで作成したものにも「D」がついているので
DSGされているのが確認できる

まとめ

Gatsbyのv4から導入された遅延静的生成 (DSG)について
その効果と使用方法をページ生成方法別にまとめてみた。

使い方はまとめたが、実際にどこに使うかは使う人の判断になるので
うまく使って、サイト開発を効率化していきたい

参考

新着記事

タグ別一覧
top