静的サイトは、速度、セキュリティ、そしてシンプルさの側面から、近年再び脚光を浴びています。多数ある静的サイト構築ツールの中でも多くの支持を集めているのが、高速な静的サイトジェネレーター(SSG)の「Gatsby」です。

Gatsbyなら、個人ブログポートフォリオサイト、ビジネスサイトなど、あらゆるサイトを作成できます。そこで今回は、Gatsbyを使って静的サイトを構築する方法を順を追ってご紹介。基礎から上級編まで、Gatsbyについて隈なく見ていきます。

この記事の解説を読んで構築できるデモサイト
この記事の解説を読んで構築できるデモサイト

静的サイトとは

静的サイトとは、事前にレンダリングされたHTMLCSSJavaScriptファイルを含むウェブページです。動的サイトとは異なり、各リクエストに対してサーバーサイドの処理に依存することがありません。すべてのコンテンツが事前に生成され、ブラウザに直接配信されます。この特徴から、静的サイトには以下のようなメリットがあります。

  1. スピード─サーバーサイドの処理がないため、読み込みが高速。
  2. セキュリティ─サーバーサイドでコードを実行しないため、セキュリティ上の脅威に晒されにくい。
  3. スケーラビリティ─コンテンツデリバリネットワーク(CDN)を使ったキャッシュや配信が容易。
  4. シンプルさ─開発、デプロイ、メンテナンスが簡単。

静的サイトの概要とメリットを押さえたところで、Gatsbyについて掘り下げていきましょう。

Gatsbyとは

Gatsbyは、JavaScriptライブラリであるReactをベースにしたオープンソースフレームワーク。Reactコンポーネントの機能とデータ管理用のGraphQLを組み合わせたもので、静的サイトの構築プロセスを簡素化することができるため、あらゆる開発者に有用です。Gatsbyには以下のような強みがあります。

  1. 圧倒的な速度─コード分割や遅延読み込みなどの機能でサイトを素早く最適化し、ほぼ瞬時にページの読み込むことができる。
  2. 柔軟なデータ取得─Markdownファイル、API、データベースなど、あらゆる場所からデータを取得可能。
  3. 豊富なプラグイン優れたプラグインエコシステムにより、機能の強化が容易。
  4. SEOとパフォーマンス─SEOとパフォーマンスに最適化されたHTMLを自動生成。

Gatsbyの使用方法

これからご紹介する内容は、以下を前提条件とします。

  • HTML、CSS、JavaScriptの基礎知識
  • Reactの基礎知識
  • Node.jsとnpm(Node Package Manager)またはyarnがコンピュータにインストールされている

Gatsbyを使い始めるには、Gatsby Starter Libraryにあるサンプルを使用するか、ゼロからプロジェクトを作成してください。

今回の例では、GatsbyJSの公式Hello Worldテンプレートを使用していきます。

  1. 次のコマンドを実行して、Gatsby CLIをコンピュータにインストールします。
npm install -g gatsby-cli

gatsby --versionを実行し、適切にインストールされているかどうかを確認してください。

  1. プロジェクトを作成したいフォルダに移動し、以下のコマンドを実行します。
npx gatsby new <project-name> https://github.com/gatsbyjs/gatsby-starter-hello-world

<project-name>は、実際のプロジェクト名に置き換えます。

  1. プロジェクトフォルダに移動し、開発サーバーを起動します。
cd <project-name>
gatsby develop

ローカルの開発サーバーが「http://localhost:8000」で起動し、Gatsbyサイトにアクセスできるようになります。

GatsbyのHello Worldテーマ
GatsbyのHello Worldテーマ

Gatsbyのファイル構造

プロジェクトをコードエディターで開くと、以下のような構造になっています。

/
|-- /public
|-- /src
    |-- /pages
        |-- index.js
|-- /static
|-- gatsby-config.js
  • /public:Gatsbyのビルドプロセスの出力が含まれ、生成されたHTML、CSS、JavaScriptなどのアセットが格納される。
  • /src:プロジェクトの中核であり、ほとんどの作業をここで行う。様々なサブディレクトリとファイルが格納される。
    • /pages:すべてのページが保存され、各JavaScriptファイルがサイトのルートに対応。
  • /static:画像、フォント、ダウンロード可能なファイルなど、サイトの静的ファイル用に使用される(ファイルはGatsbyによる処理なしでそのまま提供される)。
  • gatsby-config.js:プラグインやサイトのメタデータなど、サイトのあらゆる設定を定義。

ページとコンポーネントの作成

Gatsbyでは、簡単にページを作成できます。ページの自動生成機能により、src/pagesフォルダ内に作成したJavaScriptファイルは、自動的に対応するルートを持つページになります。

src/pagesフォルダにJavaScriptファイルを追加することで、サイトに必要なだけページを作成可能です。例えば、about.jsファイルを作成して、会社概要ページを作るなど。

src/pagesフォルダで、各ページ用に個別のJavaScriptファイルを作成することも可能ですが、サブフォルダを作成して関連するページをグループ化すると、より整頓されます(blogフォルダを作成して、ブログに関連するすべてのページをまとめるなど)。

今回の例では、以下のようなページ構成とします。

|-- /src
    |-- /pages
        |-- about.js
        |-- index.js
        |-- /blog
            |-- index.js

ページにJSXを使用する

GatsbyはReactの上に構築されているため、ページとコンポーネントはJSX(JavaScript XML)で書かれています。JSXはJavaScriptの構文拡張で、可読性が高く、表現力豊かな方法でユーザーインターフェースの構造とレイアウトを定義できます。

例えば、トップページ(index.js)のコンテンツを以下のように作成します。

import React from 'react';

export default function Home() {
  return (
    <>
      <div>
        <h1>Kinsta StSHで静的サイトホスティングをお楽しみください</h1>
        <p>高速、安全、信頼性に優れたホスティングソリューション</p>
      </div>
    </>
  );
}

Gatsbyでページをリンクする

他のページへのリンクを作成するには、Linkコンポーネントを使用します。

import React from 'react';
import { Link } from 'gatsby';

export default function Home() {
    return (
        <>
            <div>
                <h1>Kinsta StSHで静的サイトホスティングをお楽しみください</h1>
                <p>高速、安全、信頼性に優れたホスティングソリューション</p>
                <Link> to="/about">会社概要</Link>
                <Link> to="/blog">ブログ</Link>
            </div>
        </>
    );
}

上のコードでは、gatsbyからLinkコンポーネントをインポートして、会社概要ページとブログへのリンクを作成します。会社概要ページには/aboutルートがあり、訪問者が「会社概要」をクリックすると、/aboutのページが読み込まれます。

外部サイトへのリンクを作成するには、href属性を持つ通常のアンカー(<a>)タグを使用します。

import React from 'react';

export default function Home() {
  return (
        <>
            <div>
                <h1>Kinsta StSHで静的サイトホスティングをお楽しみください</h1>
                <p>高速、安全、信頼性に優れたホスティングソリューション</p>
                <div>
                    <h1>Kinsta StSHで静的サイトホスティングをお楽しみください</h1>
                    <p>高速、安全、信頼性に優れたホスティングソリューション</p>
                    <a href="https://kinsta.com/docs/static-site-hosting/" target="_blank" rel="noreferrer">
                        <div>Read more</div>
                    </a>
                </div>
            </div>
        </>
    );
}

target="_blank"rel="noreferrer"属性により、外部サイトは新たなブラウザタブで表示されます。

コンポーネントの作成

Gatsbyのコンポーネントベースのアーキテクチャでは、ウェブページの再利用可能なビルディングブロックを作成可能です。複数のページで同じコードを書く代わりに、共通する要素をコンポーネントにカプセル化することで、コードベースがよりクリーンになり、保守管理しやすくなります。

トップページのコードに、ナビゲーションセクション、メインコンテンツ、フッターを追加するとします。

import React from 'react';
import { Link } from 'gatsby';

export default function Home() {
  return (
    <>
      <div className="nav-links">
        <Link> to="/">Home</Link>
        <Link> to="/about">About</Link>
        <Link> to="/blog">Blog</Link>
      </div>
      <div>
        <h1>Kinsta StSHで静的サイトホスティングをお楽しみください</h1>
        <p>高速、安全、信頼性に優れたホスティングソリューション</p>
        <a href="https://kinsta.com/docs/static-site-hosting/">
          <div>もっと詳しく</div>
        </a>
      </div>
      <div className="footer">
        <p>
          Hosted with ❤️ by Kinsta's{' '}
          <a> href="https://kinsta.com/static-site-hosting">
            静的サイトホスティング
          </a>
          .
        </p>
      </div>
    </>
  );
}

サイト上のすべてのページで、同じナビゲーションバーとフッターを書くのは気の遠くなる作業。そこで力を発揮してくれるのがコンポーネントです。ナビゲーションバー、フッター、そして複数のページやコンポーネントにまたがって重複するすべてのコードに対して、再利用可能なコンポーネントを生成することができます。

Gatsbyでコンポーネントを扱うには、srcフォルダにcomponentsフォルダを作成し、すべてのコンポーネントを格納します。それから、Navbar.jsFooter.jsなどのコンポーネントを作成。Navbar.jsファイルでは、以下のようにコードを区切ります。

import { Link } from 'gatsby';
import React from 'react';

const Navbar = () => {
    return (
        <nav>
            <div className="nav-links">
                <Link to="/">ホーム</Link>
                <Link to="/about">会社概要</Link>
                <Link to="/blog">ブログ</Link>
            </div>
        </nav>
    );
};

export default Navbar;

Footer.jsも同様です。

import React from 'react';
const Footer = () => {
    return (
        <div className="footer">
            <p>
                Hosted with ❤️ by Kinsta's{' '}
                <a> href="https://kinsta.com/static-site-hosting">Static Site Hosting</a>
                .
            </p>
        </div>
    );
};

export default Footer;

次に、コンポーネントファイルをページまたはコンポーネントにインポートし、次のように使用します。

import React from 'react';
import Navbar from '../components/Navbar';
import Footer from '../components/Footer';

export default function Home() {
  return (
    <>
      <Navbar />
      <div>
        <h1>Kinsta StSHで静的サイトホスティングをお楽しみください</h1>
        <p>高速、安全、信頼性に優れたホスティングソリューション</p>
        <a href="https://kinsta.com/docs/static-site-hosting/">
          <div>もっと詳しく</div>
        </a>
      </div>
      <Footer />
    </>
  );
}

レイアウトコンポーネントの作成

ウェブ開発では、サイトの全体的な構造をカプセル化するレイアウトコンポーネントを作成するのが一般的です。レイアウトコンポーネントには通常、ヘッダー、フッター、ナビゲーションメニュー、サイドバーなど、すべてのページに表示される要素が含まれます。

src/componentsフォルダにLayout.jsファイルを作成し、レイアウト構造を定義します。以下の例では、レイアウト構造はナビゲーションバーとフッターのみを加えます。

import React from 'react';
import Navbar from './Navbar';
import Footer from './Footer';

const Layout = ({ children }) => {
    return (
        <div className="layout">
            <Navbar />
            <div> className="content">{children}</div>
            <Footer />
        </div>
    );
};

export default Layout;

上のレイアウトコンポーネントでは、ページのコンテンツを包むためにコンポーネントを使用します(children)。ページでレイアウトコンポーネントを使うには、それをインポートして、ページコンテンツを包みます。例えば、index.jsページでは以下のようになります。

import React from 'react';
import Layout from '../components/Layout';

export default function Home() {
  return (
    <Layout>
      <div>
        <h1>Kinsta StSHで静的サイトホスティングをお楽しみください</h1>
        <p>高速、安全、信頼性に優れたホスティングソリューション</p>
        <a href="https://kinsta.com/docs/static-site-hosting/">
          <div>Read more</div>
        </a>
      </div>
    </Layout>
  );
}

レイアウトコンポーネントを使用することで、すべてのページで一貫した構造と外観を確保し、コードを整理して保守管理しやすくすることができます。これによって、サイトの共通要素をかなり効率的に管理できます。

ページとコンポーネントのスタイリング

Gatsbyのスタイリング機能は柔軟で、通常のCSS、CSS-in-JS、SassのようなCSSプリプロセッサなど、様々なアプローチを使用できます。今回は、通常のページスタイルとモジュールスタイルの作成方法を見ていきます。

CSSスタイリング

CSSファイルを作成し、コンポーネントやページにリンクするのは簡単です。例えば、srcフォルダにstylesフォルダを作成し、global.cssファイルにCSSコードを記述します。

先ほど作成したコンポーネントの基本的なグローバルスタイルは、以下のとおりです。

@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500&display=swap');

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

body {
    background-color: #ddd;
    font-family: 'Poppins',
        sans-serif;
    width: 1200px;
    margin: 0 auto;
}

a {
    text-decoration: none;
}

img {
    width: 100%;
}

nav {
    display: flex;
    justify-content: space-between;
    height: 200px;
    align-items: center;
}

nav .logo-img {
    width: 100px;
}

nav .nav-links a {
    padding: 0 20px;
    font-size: 18px;
}

@media (max-width:700px) {
    body {
        width: 100%;
        padding: 0 20px;
    }

    nav .nav-links a {
        padding: 0 18px;
    }
}

.footer {
    width: 100%;
    text-align: center;
    margin: 100px 0 20px;
}

Google FontsからPoppinsフォントをインポートし、すべてのコンポーネントに適用する基本的なスタイルを定義しています。

続いて、スタイルを設定したいコンポーネントにCSSファイルをインポートします。例としてLayoutコンポーネントに追加し、グローバルに適用できるようにしてみます。

import React from 'react';
import Navbar from './Navbar';
import Footer from './Footer';
import '../styles/global.css';

const Layout = ({ children }) => {
    return (
        <div>
            <Navbar />
            <div> className="content">{children}</div>
            <Footer />
        </div>
    );
};

export default Layout;

モジュールCSSを使ったスタイリング

CSSモジュールを使用すると、スタイルを特定のコンポーネントやページに適用可能です。これにより、スタイルの衝突を防ぎ、コードのメンテナンスも簡素化されます。stylesフォルダで、<ページ名>.module.cssの形式でCSSモジュールを作成し、そのファイルに特定のスタイルを追加します。

例として、トップページ用にhome.module.cssを作って、以下のコードを追加します。

.home_hero {
    display: flex;
    justify-content: center;
    align-items: center;
    flex-direction: column;
    text-align: center;

}

.home_hero h1 {
    font-size: 60px;
    width: 70%;
}

.home_hero p {
    color: #6E7076;
    font-size: 20px;
}

.btn {
    background-color: #5333ed;
    padding: 20px 30px;
    margin-top: 40px;
    border-radius: 5px;
    color: #fff;
}

@media (max-width:700px) {
    .home_hero h1 {
        font-size: 40px;
    }

    .home_hero p {
        font-size: 16px;
    }
}

モジュールのCSSスタイルをページやコンポーネントで使用するには、CSSモジュールのスタイルをオブジェクトとして、ページやコンポーネントファイルの先頭にインポートし、次のように使用します。

import React from 'react';
import Layout from '../components/Layout';
import * as styles from '../styles/home.module.css';

export default function Home() {
  return (
    <Layout>
      <div className={styles.home_hero}>
        <h1>Kinsta StSHで静的サイトホスティングをお楽しみください</h1>
        <p>高速、安全、信頼性に優れたホスティングソリューション</p>
        <a href="https://kinsta.com/docs/static-site-hosting/">
          <div className={styles.btn}>Read more</div>
        </a>
      </div>
    </Layout>
  );
}


Gatsbyで静的ファイルを使用する

Gatsbyにおける静的ファイルとは、画像、フォント、CSSファイルなどのサーバサイドの処理を行わずにブラウザに直接提供されるアセットを意味します。これらのファイルは、プロジェクトのルートにある/staticディレクトリに格納されます。

画像(kinsta-logo.png)を/staticディレクトリに追加すると、次のようにコンポーネントに表示できます。

import { Link } from 'gatsby';
import React from 'react';

const Navbar = () => {
    return (
        <nav>
            <Link> to="/">
                <img src="/kinsta-logo.png" alt="Kinstaのロゴ" className="logo-img" />
            </Link>
            <div className="nav-links">
                <Link> to="/">ホーム</Link>
                <Link> to="/about">会社概要</Link>
                <Link> to="/blog">ブログ</Link>
            </div>
        </nav>
    );
};

export default Navbar;

これらの相対パスは、サイトのビルド時に正しいURLに自動的に解決されます。Gatsbyで画像を最適化する方法については、後ほどご説明します。

プラグインと統合

Gatsbyには、機能の拡張に使えるプラグインが多数あります。SEO分析、画像最適化、Markdown変換など種類も豊富で、インストールと設定も簡単。サイトを劇的にパワーアップすることができます。

今回は、以下4つのプラグインを取り上げます。

  1. gatsby-transformer-remark:MarkdownファイルをHTMLコンテンツに変換し、ブログ記事やドキュメントなど、テキストベースのコンテンツを簡単に作成・管理できる。
  2. gatsby-transformer-sharpgatsby-plugin-sharp:プロジェクト内の画像を最適化、連携して操作を可能にする。
  3. gatsby-source-filesystem:プロジェクトディレクトリからファイルを取得し、GraphQLでクエリできるようにする。

プラグインをGatsbyプロジェクトで使用するには、プロジェクトのルートディレクトリで次のコマンドを実行してインストールします。

npm install gatsby-transformer-remark gatsby-transformer-sharp gatsby-plugin-sharp gatsby-source-filesystem

次に、gatsby-config.jsファイルでプラグインの設定を行います。例を見てみましょう。

module.exports = {
    plugins: [
        // その他のプラグイン
        // MarkdownファイルをHTMLに変換
        'gatsby-transformer-remark'
        // 画像の最適化と操作
        'gatsby-transformer-sharp'
        'gatsby-plugin-sharp'
        // プロジェクトディレクトリのファイルを取得
        {
            resolve: `gatsby-source-filesystem`,
            options: {
                name: `posts`,
                path: `${__dirname}/src/posts/`,
            },
        },
        {
            resolve: `gatsby-source-filesystem`,
            options: {
                name: `images`,
                path: `${__dirname}/src/images/`,
            },
        },
    ],
};

2つのgatsby-source-filesystem設定が作成され、postsimagesという2つのフォルダに紐づいています。postsには、gatsby-transformer-remarkで変換されるMarkdownファイル(ブログ記事)が保存され、imagesにはブログ用の画像や最適化したい画像が保存されます。

なお、gatsby-config.jsファイルを変更する際には、必ずローカルの開発サーバーを再起動してください。

ブログ記事の作成

プラグインの設定が完了したら、srcディレクトリにpostsフォルダを作成し、以下の内容のMarkdownファイルを2つ作成します。

post-1.md

---
title: "Gatsby入門"
date: "2023-10-01"
slug: "introduction-to-gatsby"
description: "ギャツビーの基礎と機能を学ぶ"
featureImg: ../images/featured/image-1.jpeg
---

一緒にGatsbyを学びましょう。この記事では、Gatsbyの基本的な使用方法と機能についてご説明します。

post-2.md

---
title: "Gatsbyで画像のを最適化する方法"
date: "2023-10-05"
slug: "optimizing-images-in-gatsby"
description: "Gatsbyプロジェクトで画像を最適化する方法を探ります。"
featureImg: ../images/featured/image-2.jpeg
---

ウェブ開発において、画像は重要な要素です。この記事では、プラグインを使用してGatsbyの画像を最適化する方法をご紹介します。

これらのMarkdownファイルには、タイトル、日付、スラッグ、説明、画像パスなど、ブログ記事に関するメタデータを含むfrontmatterが含まれています。

GraphQLを使ったGatsbyでのクエリ

Gatsbyは、GraphQLを使用してサイトのデータをクエリして取得します。GraphQLは強力なクエリ言語で、必要なデータを正確にリクエストできるため、効率的かつ柔軟にクエリすることができます。このセクションでは、GatsbyでGraphQLを使用してデータをクエリする方法を見ていきます。

ターミナルでgatsby developを実行すると、ウェブ上でプロジェクトを開くリンク「gatsby-source-filesystem」に加えて、URL「http://localhost:8000/___graphql」が表示されます。これは、GatsbyプロジェクトのGraphiQLエディターへのアクセスを提供するものです。

エディターを開くと、以下のようなインターフェースが表示されます。

GraphQL Playground
GraphQL Playground

このエディターから、サイトに関するあらゆるデータを照会可能です。今回の場合は、先ほどMarkdownファイルを作成し、gatsby-config.jsファイルで必要なものを設定済みです。エディターで次のクエリを実行して、Markdownファイルとその内容を照会してみます。

query BlogList {
    allMarkdownRemark {
        nodes {
            frontmatter {
                title
                slug
                description
            }
            id
        }
    }
}

このクエリは、allMarkdownRemarkを使ってすべてのMarkdownファイルからデータを取得します。各ファイルのfrontmatterからtitleslugdescription、そしてidを取得します。

クエリを書いたら、「Play」ボタン(右向きの三角形のアイコン)をクリックして、クエリを実行します。結果はエディターの右側に表示されます。

GraphiQL PlaygroundでMarkdown情報を取得
GraphiQL PlaygroundでMarkdown情報を取得

次に、コンポーネントやページ内のMarkdownデータをクエリするため、GraphQLを使用します。blog/index.jsページでこのデータを照会するには、まずgatsbyからgraphqlをインポートし、JSXコードの一番下に以下を貼り付けます。

export const query = graphql`
query BlogList {
    allMarkdownRemark {
        nodes {
            frontmatter {
                title
                slug
                description
            }
            id
        }
    }
}
`;

上のコードは、graphqlタグを使用して、GraphQLクエリqueryを作成します。blog/index.jsファイルは次のようになるはずです。

import { graphql, Link } from 'gatsby';
import React from 'react';
import Layout from '../../components/Layout';
import * as styles from '../../styles/blog.module.css';

const blog = ({ data }) => {
    const posts = data.allMarkdownRemark.nodes;
    return (
        <Layout>
            <div className={styles.blog_cont}>
                <h2>Blog</h2>
                <div className={styles.blog_grid}>
                    {posts.map((post) => (
                        <Link
                            to={`/blog/${post.frontmatter.slug}`}
                            className={styles.blog_card}
                            key={post.id}
                        >
                            <h3>{post.frontmatter.title}</h3>
                            <p>{post.frontmatter.description}</p>
                        </Link>
                    ))}
                </div>
            </div>
        </Layout>
    );
};
export default blog;

export const query = graphql`
query BlogList {
    allMarkdownRemark {
        nodes {
            frontmatter {
                title
                slug
                description
            }
            id
        }
    }
}
`;

このコードでは、コンポーネントのdataプロップを通して、queryの結果にアクセスしています。次に、postsのデータをJavaScriptのmap()メソッドを使ってデータをループし、タイトルを一覧表示します。

エラーを避けるため、stylesフォルダにblog.module.cssファイルを作成して、以下のコードを貼り付けます。

.blog_cont h2 {
    font-size: 40px;
    margin-bottom: 20px;
}

.blog_grid {
    display: grid;
    grid-template-columns: 1fr 1fr 1fr;
    gap: 20px;
}

@media (max-width:700px) {
    .blog_grid {
        grid-template-columns: 1fr;
    }
}

.blog_card {
    background-color: #bfbfbf;
    padding: 20px;
    border-radius: 5px;
    color: #000;
    transition: all .5s ease-in-out;
}

.blog_card:hover {
    background-color: #5333ed;
    color: #fff;
}

.blog_card h3 {
    margin-bottom: 15px;
}

.blog_card p {
    margin-bottom: 15px;
}
GraphQL経由で取得したブログ記事
GraphQL経由で取得したブログ記事

GraphQLを使ったGatsbyのテンプレートと動的ページの生成

テンプレートと動的ページは、Gatsbyにおいて、柔軟でデータ駆動型のサイトを作成するための重要な概念です。テンプレートを使用すると、ページの構造とレイアウトを定義することができ、GraphQLでこれらのテンプレートに動的にデータを取り込むことができます。

ブログ記事テンプレートの作成

各ブログ記事がタイトルやコンテンツを含む、一貫した構造を持つブログを作成するとします。レイアウトを定義するために、BlogDetailsテンプレートを作成します。srcフォルダにtemplatesフォルダを作成し、その後blog-details.jsファイルを作成します。

import React from 'react';
import Layout from '../components/Layout';
import * as styles from '../styles/blog-details.module.css';

const BlogDetails = () => {

    return (
        <Layout>
            <div>
                <div className={styles.blog_content}>
                    <Img
                        className={styles.blog_featured}
                    />
                    <h3>タイトル</h3>
                    <div>
                        className={styles.html}
                        dangerouslySetInnerHTML={}
                    />
                </div>
            </div>
        </Layout>
    );
};

export default BlogDetails;

この例では、BlogDetailsテンプレートが個々のブログ記事の構造を定義しています。次に、GraphQLを使って特定のブログ記事のデータを取得し、このテンプレートにpropsとして渡します。

動的ページの生成

動的ページを生成するには、プロジェクトのルートディレクトリにgatsby-node.jsファイルを作成します。このファイルで、ページの作成方法を定義することができます。

gatsby-node.jsファイルでは、GraphQLを使用して動的ページに使用するデータをクエリします。例えば、Markdownのブログ記事があれば、そのスラッグをクエリすることが可能です。

const path = require(`path`);

exports.createPages = async ({ graphql, actions }) => {
  const { data } = await graphql(`
    query Articles {
      allMarkdownRemark {
        nodes {
          frontmatter {
            slug
          }
        }
      }
    }
  `);

  data.allMarkdownRemark.nodes.forEach((node) => {
    actions.createPage({
      path: '/blog/' + node.frontmatter.slug,
      component: path.resolve('./src/templates/blog-details.js'),
      context: { slug: node.frontmatter.slug },
    });
  });
};

上の例では、すべてのMarkdown投稿のスラッグを照会し、BlogDetailsテンプレートを使用して各投稿の動的ページを作成します。contextオブジェクトは、テンプレートにデータを渡すために使用され、このデータ(スラッグ)は、テンプレートがスラッグと一致する他のデータを取得するために使われます。

テンプレートページにGraphQLクエリを追加する前に、Gatsbyで画像最適化について押さえておきましょう。

Gatsbyの画像最適化

先ほど、画像を取得するためにgatsby-transformer-sharpgatsby-plugin-sharpgatsby-source-filesystemをインストール、設定しました。

これらのプラグインを使って、GraphQLで画像をクエリして最適化します。以下は、gatsby-plugin-sharpを使って最適化された画像をクエリして表示する例です。

export const query = graphql`
  query {
    file(relativePath: { eq: "example.jpg" }) {
      childImageSharp {
        fluid {
          ...GatsbyImageSharpFluid
        }
      }
    }
  }
`;

上記では、example.jpgという名前の画像をimagesソースからクエリし、クエリされた画像のfluidプロパティを使用して、レスポンシブで最適化されたレンダリングで表示しています。

最適化された画像を扱うために、gatsby-imageからImgをインポートすることができます。

import React from 'react';
import { graphql } from 'gatsby';
import Img from 'gatsby-image';

const ImageExample = ({ data }) => {
  const { fluid } = data.file.childImageSharp;

  return (
    <div>
      <Img fluid={fluid} alt="Example Image" />
    </div>
  );
};

export default ImageExample;

動的ページのクエリ

Gatsbyでは、指定されたテンプレートを使用して、ブログ記事ごとに個別のページを作成します。例として、テンプレートページにGraphQLクエリを追加して、スラッグに基づいてデータを取得します。

import { graphql } from 'gatsby';
import Img from 'gatsby-image';
import React from 'react';
import Layout from '../components/Layout';
import * as styles from '../styles/blog-details.module.css';

const BlogDetails = ({ data }) => {
    const { html } = data.markdownRemark;
    const { title, featureImg } = data.markdownRemark.frontmatter;
    return (
        <Layout>
            <div>
                <div className={styles.blog_content}>
                    <Img
                        fluid={featureImg.childImageSharp.fluid}
                        className={styles.blog_featured}
                    />
                    <h3>{title}</h3>
                    <div
                        className={styles.html}
                        dangerouslySetInnerHTML={{ __html: html }}
                    />
                </div>
            </div>
        </Layout>
    );
};

export default BlogDetails;

export const query = graphql`
    query ProjectDetails($slug: String) {
        markdownRemark(frontmatter: { slug: { eq: $slug } }) {
            html
            frontmatter {
                title
                featureImg {
                    childImageSharp {
                        fluid {
                            ...GatsbyImageSharpFluid
                        }
                    }
                }
            }
        }
    }
`;

上のコードでは、最適化された画像をクエリし、スラッグに一致するブログ記事をクエリします。

今回のGatsbyプロジェクトのソースコードの全貌はこちらでご覧ください。

KinstaでGatsby静的サイトをデプロイする方法

Kinstaでは、無料で最大100件まで静的サイトをホストできます。任意のGitサービス(BitbucketGitHub、またはGitLab)にコードをプッシュし、デプロイ可能です。

リポジトリを準備したら、以下の手順で静的サイトをKinstaにデプロイします。

  1. MyKinstaにログイン、またはアカウントを作成
  2. GitサービスでKinstaを認証
  3. 左サイドバーの「静的サイト」を選択して「サイトの追加」をクリック
  4. デプロイしたいリポジトリとブランチを選択
  5. サイトに一意の名前を割り当てる
  6. Gatsbyプロジェクトのビルド設定が自動検出される
    • ビルドコマンドnpm run build
    • Nodeのバージョン18.16.0
    • 公開ディレクトリpublic
  1. サイトを作成」をクリック

これで、数秒以内にサイトのデプロイが完了し、サイトのデプロイされたバージョンにアクセスするためのリンクが提供されます。必要に応じて、独自ドメインSSL証明書を追加できます。

また、静的サイトホスティングだけでなく、Kinstaのアプリケーションホスティングでも静的サイトをデプロイできます。スケーリング、Dockerfileを使用したデプロイメントのカスタマイズ、リアルタイムおよび過去のデータを網羅した包括的な分析など、多数の機能を利用できます。

まとめ

Gatsbyにおけるデータ取得、ルーティング、スタイリング、画像最適化、プラグイン、デプロイメントなどの基礎についてご紹介しました。

Gatsbyの柔軟性、速度、そして豊富なエコシステムは、静的サイトの構築に役立ちます。個人ブログ、ポートフォリオサイト、ビジネスサイトなど、あらゆるサイトを作ることができます。

Gatsbyサイトの構築にこの記事がお役に立てば幸いです。これまでにGatsbyで何かを開発された経験はありますか?以下のコメント欄で、ぜひお聞かせください。

 

Joel Olawanle Kinsta

Joel is a Frontend developer working at Kinsta as a Technical Editor. He is a passionate teacher with love for open source and has written over 200 technical articles majorly around JavaScript and it's frameworks.