本文書はReactライブラリベースのフレームワークGatsbyを利用してスクラッチからGatsby Cloudへのデプロイの方法について説明を行なっています。Markdownで作成したファイルの記事の個別ページの表示や画像の設定方法についての基本を理解することができます。

本ブログではGatsbyのブログ作成について記事を公開していますが記事が古くなり設定方法が一部変わっていることまた複数に分かれていた記事を一つにまとめています。

Gatsbyとは

GatsbyはStatic Site Generator(静的サイトジェネレーター)でReactライブラリをベースに開発されているフレームワークです。Gatsbyを使いこなすためにはJavaScriptだけではなくReact, GraphQLなどの基礎知識が必要となります。

Gatsbyではデータを取得する際にはRest APIではなくGraphQLを利用します。GraphQLは外部リソースからデータを取得できるだけではなくローカルに保存されたMarkdownファイル、データベース、CSVファイルまたはContentfulやWordPressなどさまざまなリソースからデータを取得することができます。コミュニティによって作成されたPlugin(プラグイン)も豊富にあるため何か機能を追加したい場合には自分で作成することなくインストールするだけで目的にあったサイト構築を行うことができます。

ァイルへのアクセスや画像の処理などすべてプラグインを追加することで機能を利用することができるようになるためGatsbyを使いこなすためにはPluginにどのようなものがあるかも理解する必要があります。

Gatsbyを利用する主な理由にはサイトの高速化や画像の最適化、セキュリティ対策といったものがあります。

サイトの高速化は静的サイトジェネレーターという機能で実現されています。WordPressのようにブラウザからアクセスがあった場合にデータベースに保存されている記事情報をSQLでデータベースから取得して動的にページ作成するのではなく静的ページを事前に作成(ビルド)しておくことで高速化を図ります。

最近はPCからだけではなくスマホやタブレットPCなどさまざまなデバイスからのアクセスがあります。サイトによってはスマホからのアクセスが大半を占めるサイトもあります。それぞれのデバイスに合わせて自動で画像を調整してくれる画像の最適化機能をGatsbyは持っており画像を調整するための煩雑な設定から開放されます。

Gatsbyでは事前に静的ページを作成するためにアクセスの度にデータベースへのアクセスを行う必要がありません。またHeadless CMSのContentfullからデータを取得することもできるためGatsbyが稼働するサーバにデータを持たせないことも可能です。そのためGatsby経由でデータベースに保管されている重要なデータへアクセスされる可能性がなくセキュリティへの不安を和らげることができます。

サイトの作成

Gatsbyの動作確認を行うためにGatsbyサイトの作成を行います。サイトの作成はnpm init gatsbyコマンドで行うことができます。コマンドを実行するとプロジェクト名の設定など対話式で進めることができます。サイトの名前、JavaScriptかTypeScriptの選択、CMSの選択、スタイリングや利用する機能の追加を行うことができます。本文書ではJavaScriptを選択してCMSやスタイリング、機能の追加を行わずに進めます。サイトの名前はgatsby-siteとしています。サイト名は任意の名前をつけることができます。


 % npm init gatsby 
Need to install the following packages:
  create-gatsby
Ok to proceed? (y) y
create-gatsby version 2.24.0



                               Welcome to Gatsby!



What would you like to call your site?
✔ · gatsby-site
What would you like to name the folder where your site will be created?
✔ Desktop/ gatsby-site
✔ Will you be using JavaScript or TypeScript?
· JavaScript
? Will you be using a CMS?
(Single choice) Arrow keys to move, enter to confirm
❯ No (or I'll add it later)
  –
  Contentful
  DatoCMS
  Netlify CMS
  Sanity
  Shopify
  WordPress
? Would you like to install a styling system?
(Single choice) Arrow keys to move, enter to confirm
❯ No (or I'll add it later)
  –
  Emotion
  PostCSS
  Sass
  styled-components
  Theme UI
  vanilla-extract
? Would you like to install additional features with other plugins?
(Multiple choice) Use arrow keys to move, spacebar to select, and confirm with an enter on "Done"
❯◯ Add the Google Analytics tracking script
 ◯ Add responsive images
 ◯ Add an automatic sitemap
 ◯ Generate a manifest file
 ◯ Add Markdown and MDX support
 ◯ Add Markdown support (without MDX)
  ─────
  Done
Thanks! Here's what we'll now do:

    🛠  Create a new Gatsby site in the folder gatsby-site


? Shall we do this? (Y/n) › Yes

コマンドに-yオプションをつけることで対話をスキップして実行することもできます。-tsオプションをつけることでTypeScriptを選択してサイトを作成することもできます。


 % npm init gatsby -y -ts my-site-name

npm init gatsbyコマンドによりサイトの作成が完了したら作成されたフォルダ(gatsby-site)に移動します。

本文書で動作確認を行うバージョンをpackage.jsonで確認しておきます。gatsbyのバージョンが4.24.0でreactのバージョンが18.1.0であることがわかります。


{
  "name": "gatsby-site",
  "version": "1.0.0",
  "private": true,
  "description": "gatsby-site",
  "author": "reffect2020",
  "keywords": [
    "gatsby"
  ],
  "scripts": {
    "develop": "gatsby develop",
    "start": "gatsby develop",
    "build": "gatsby build",
    "serve": "gatsby serve",
    "clean": "gatsby clean"
  },
  "dependencies": {
    "gatsby": "^4.24.0",
    "react": "^18.1.0",
    "react-dom": "^18.1.0"
  }
}

Gatsby Command Line Interface(CLI)

npm initコマンドではなくGatsbyのコマンドラインであるgatsbyコマンドでサイトを作成することもできます。Gatsbyコマンドを利用するためにgatsby-cliパッケージをインストールすることができます。


 $ sudo npm install -g gatsby-cli

gatsbyコマンドを利用することでサイトをスクラッチから作成するだけではなくコミュニティがメンテナンスしているstarter(スターター)を利用してサイトを作成することができます。アプリケーションの目的に応じたテンプレートであるstarterがいくつもアップされており、starterを利用することで短時間で目的のサイトを作成することができます。starterを指定したい場合は、URL_OF_STARTER_GITHUB_REPOにGitHubのURLを指定します。


gatsby new [SITE_DIRECTORY_NAME] [URL_OF_STARTER_GITHUB_REPO]
gatsby-cliをインストールせずにgatsbyコマンドを実行したい場合は先頭にnpxをつけます。npx gatsby new …で実行できます。

例えばブログを構築したい場合にはGatsby Starter Blogを指定することができます。


 % gatsby new blog https://github.com/gatsbyjs/gatsby-starter-blog

https://www.gatsbyjs.com/starters/からstarterを見つけることができます。

開発中に作成されるキャッシュやpublicフォルダを削除したい場合にgatsby cleanコマンドが役に立ちます。

gatsby-cliをインストールしていないくてもnpx gatsby cleanコマンドを実行することができます。

開発サーバの起動

サイトの作成が完了したらサイトフォルダに移動して、npm run developコマンドを実行します。起動後のメッセージhttp://localhost:8000/とあるように開発用のサーバはローカルのPCのポート番号8000で起動します。ブラウザからhttp://localhost:8000/にアクセスします。


 % npm run develop

> gatsby-site@1.0.0 develop
> gatsby develop

success compile gatsby files - 1.144s
success load gatsby config - 0.020s
success load plugins - 0.257s
success onPreInit - 0.002s
success initialize cache - 0.235s
success copy gatsby files - 0.437s
success Compiling Gatsby Functions - 0.452s
success onPreBootstrap - 0.474s
success createSchemaCustomization - 0.002s
success Checking for changed pages - 0.003s
success source and transform nodes - 0.117s
success building schema - 0.234s
success createPages - 0.002s
success createPagesStatefully - 0.151s
info Total nodes: 24, SitePage nodes: 4 (use --verbose for breakdown)
success Checking for changed pages - 0.002s
success write out redirect data - 0.043s
success onPostBootstrap - 0.005s
info bootstrap finished - 8.003s
success onPreExtractQueries - 0.001s
success extract queries from components - 0.238s
success write out requires - 0.034s
success run page queries - 0.030s - 3/3 99.39/s
⠀
You can now view gatsby-site in the browser.
⠀
  http://localhost:8000/
⠀
View GraphiQL, an in-browser IDE, to explore your site's data and schema
⠀
  http://localhost:8000/___graphql
⠀
Note that the development build is not optimized.
To create a production build, use gatsby build
⠀
success Building development bundle - 13.851s
success Writing page-data.json files to public directory - 0.087s - 3/4 45.96/s

gatsby-cliをインストールしている場合はgatsby developコマンドで開発サーバを起動することができます。

ブラウザ上には以下の画面が表示されます。

Gatsbyサイトの開発サーバの初期画面
Gatsbyサイトの開発サーバの初期画面

ブラウザ上に表示されている内容は/src/pagesフォルダのindex.jsファイルの中に記述されています。

ブログサイトの構築

作成したサイトを利用してスクラッチからブログサイトを構築していきます。ファイルの更新を行う場合は必ず下記のコマンドを実行しておきます。


 $ npm run develop

トップページの更新

src¥pagesフォルダにあるindex.jsファイルを下記のように更新します。


import * as React from 'react';

const IndexPage = () => {
  return <h1>Gatsby Blog Site</h1>;
};

export default IndexPage;

更新すると手動でリロードすることなくブラウザに変更内容が更新されます。これはホットリロードと呼ばれており効率的に追加した内容をチェックするこができます。更新を行った内容Gatsby Blog Siteが表示されます。

index.jsファイルの更新
index.jsファイルの更新

aboutページの追加

Gatsbyでは/src/pagesフォルダにページコンポーネントを作成することでページを追加することができます。src/pages/abouts.jsファイルを作成するとhttp://localhost/aboutでabout.jsファイルに記述した内容が表示されます。

about.jsファイルをindex.jsファイルを元に作成します。


import * as React from 'react';

const AboutPage = () => {
  return <h1>About Page</h1>;
};

export default AboutPage;

src/pagesにabout.jsファイルを追加した後localhost:8000/aboutにアクセスすると以下の画面が表示されます。

aboutページの表示
aboutページの表示

aboutページ以外にもページを追加したい場合には同じ方法で行うことができます。

404ページ

ここまでの設定で/(ルート), /aboutページにアクセスするとページが表示されますがそれ以外のURLにアクセスがあった場合にどのような情報が表示されるか確認します。

localhost:.8000/の後ろに適当な文字列を入力してください。ここではpages/フォルダに存在しないprofileを入力すると下記のページが表示されます。”Preview custom 404 page”ボタンとページの作成方法について説明があります。

404ページの表示
404ページの表示
本番環境では上記の画面は表示されません。

画面に表示されている”Preview custom 404 page”ボタンをクリックしてください。クリックすると以下の画面が表示されます。

Page Not foundページ
Page Not foundページ

このページの内容はsrc/pagesフォルダの404.jsファイルの中身です。404.jsファイルを更新することでページの存在しないURLにアクセスがあった場合に表示させたい内容を変更することができます。


import * as React from 'react';

const NotFound = () => {
  return <p>アクセスしたページは存在しません。</p>;
};

export default NotFound;

404.jsファイルを行った後再度”Preview custom 404 page”ボタンをクリックすると記述した内容が表示されます。

更新した404.jsファイルの表示
更新した404.jsファイルの表示

開発環境ではGatsby.js Development 404 Pageが表示されますが本番環境ではGatsyby.js Development 404 Pageではなく直接作成した404ページの内容が表示されます。確認したい場合はnpm run buildコマンドを実行してビルドを行いnpm run serveコマンドを実行してください。Gatsbyが正常に起動した場合は存在しないURLにアクセスすると404.jsファイルの中身が表示されます。

リンクの設定

indexページとaboutページを作成しましたが現在の設定ではaboutページにアクセスするためにはブラウザのURLに/aboutを手動で入力する必要があります。indexページとaboutページ間でページ移動ができるようにリンクの設定を行います。

Gatsbyでページ間のリンクを貼る場合はLinkコンポーネントを利用します。Linkコンポーネントをgatsbyからimportします。


import { Link } from "gatsby"

index.jsファイルからaboutページへのリンクを貼るためにLinkタグを下記のように記述します。toにAboutページのurlを指定します。


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

const IndexPage = () => {
  return (
    <>
      <ul>
        <Link to="/about">About</Link>
      </ul>
      <h1>Gatsby Blog Site</h1>
    </>
  );
};

export default IndexPage;

ブラウザで確認するとAboutページへのリンクが貼られます。クリックするとAboutページ全体の読み込みが行われずスムーズにAbout Pageが表示されることが確認できます。通常のHTMLのようにaタグを利用してリンクを貼ることができますがその場合はページを移動するとページ全体が再読み込みされます。外部のページへのリンクはaタグを利用して行います。

リンクを貼った後のトップページ
リンクを貼った後のトップページ

ヘッダーとフッターコンポーネントの作成

ブログサイトのようにページ内で表示が異なる部分は投稿の記事部分である場合、ヘッダー、フッターまたサイドバー(ある場合)はすべてのページで共通です。この場合、ページ毎にヘッダー、フッターなど同じコードを記述するのではなくコンポーネントとして部品化してすべてのページで共有して利用します。

ここまでの作業ではindex.jsとabout.jsページの2つしかありませんが、2つのページのリンクを表示するためにHeaderコンポーネントを追加します。srcフォルダの下にcomponentsフォルダを作成します。

componentsフォルダ作成後その下にheader.jsファイルを作成します。

header.jsファイルには各ページへのリンクを追加します。


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

const Header = () => {
  return (
    <header>
      <nav>
        <ul>
          <li>
            <Link to="/">top</Link>
          </li>
          <li>
            <Link to="/about">about</Link>
          </li>
        </ul>
      </nav>
    </header>
  );
};

export default Header;

index.jsでは作成したHeaderコンポーネントをimportします。index.jsでは直接Linkコンポーネントを利用しないのでLinkのimportを削除します。


import * as React from 'react';
import Header from '../components/header';

const IndexPage = () => {
  return (
    <>
      <Header />
      <h1>Gatsby Blog Site</h1>
    </>
  );
};

export default IndexPage;

Headerコンポーネント追加後はページの上部にリンクが表示されます。リンクをクリックするとページを移動することができます。

Headerコンポーネント追加後の表示
Headerコンポーネント追加後の表示

Footerコンポーネントの作成も行います。header.jsと同様にcomonentsフォルダの下にfooter.jsファイルを作成します。西暦を自動表示できるように(new Date()).getFullYear()を利用しています。


import * as React from 'react';

const Footer = () => {
  return (
    <footer>
      <div>© Gatsby Blog Site {new Date().getFullYear()}</div>
    </footer>
  );
};

export default Footer;

Headerコンポーネントと同様にFooterコンポーネントもimportします。


import * as React from 'react';
import Header from '../components/header';
import Footer from '../components/footer';

const IndexPage = () => {
  return (
    <>
      <Header />
      <h1>Gatsby Blog Site</h1>
      <Footer />
    </>
  );
};

export default IndexPage;

ブラウザで確認すると上部にHeaderコンポーネントの要素、下部にFooterコンポーネントの要素が表示されることが確認できます。

HeaderコンポーネントとFooterコンポーネント追加
HeaderコンポーネントとFooterコンポーネント追加

Layoutコンポーネント

HeaderとFooterコンポーネントを作成しましたが、これらのコンポーネントを含むLayoutコンポーネントを作成します。すべてのページはLayoutコンポーネントを使ってコンテンツ以外を共通化します。

まだLayoutコンポーネントの作成を行っていませんがindex.jsファイルでLayoutコンポーネントをimportしLayoutタグで囲みます。


import * as React from 'react';
import Layout from '../components/layout';

const IndexPage = () => {
  return (
    <Layout>
      <h1>Gatsby Blog Site</h1>
    </Layout>
  );
};

export default IndexPage;

次にlayout.jsファイルをcomponentsフォルダの下に作成して以下を記述します。これまではHeader、Footerコンポーネントはindex.jsでimportしていましたが、Layoutコンポーネントの中でimportします。index.jsファイルでLayoutタグの間にコンテンツを入れていましたが、コンテンツはpropsを使って受け取ることができます。

Reactでは親コンポーネントから子コンポーネントにデータを渡す際にpropsを利用します。

import * as React from 'react';
import Header from './header';
import Footer from './footer';

const Layout = ({ children }) => {
  return (
    <div>
      <Header />
      {children}
      <Footer />
    </div>
  );
};

export default Layout;

Layoutコンポーネントを作成後、ブラウザでアクセスすると先ほどと同じ内容が表示されます。about.jsファイルもindex.jsファイルと同様にLayoutコンポーネントをimportして設定します。


import * as React from 'react';
import Layout from '../components/layout';

const AboutPage = () => {
  return (
    <Layout>
      <h1>About Page</h1>
    </Layout>
  );
};

export default AboutPage;

index.jsとabout.jsはコンテンツ以外は共通となりました。

aboutページもlayoutコンポーネントを設定
aboutページもlayoutコンポーネントを設定

スタイル設定

CSSを利用してスタイルを適用する方法は複数の方法があるのでここでは2つの方法を使ってスタイルを適用します。

Global CSS Styles

だれもが知っている一番シンプルな方法です。src¥componentsフォルダにglobal.cssファイルを作成します。

作成したglobal.cssファイルに以下を追加します。


h1 {
  color: red;
}

layout.jsファイルで作成したglobal.cssをimportします。


import * as React from 'react';
import Header from './header';
import Footer from './footer';
import './global.css';

const Layout = ({ children }) => {
  return (
    <div>
      <Header />
      {children}
      <Footer />
    </div>
  );
};

export default Layout;

global.cssをimport後にページを確認するとh1タグの文字が赤色になっていることが確認できます。layout.jsファイルでglobal.cssをimportすることで子コンポーネントであるindex.jsファイルのh1タグにスタイルが適用されることがわかります。about.jsファイルでもh1タグを利用している場合はglobal.cssで設定したスタイルが適用されます。

スタイルの適用
スタイルの適用

classを利用してスタイルを適用したい場合にはコンポーネントではclassではなくclassNameを利用します。


.title {
  color: red;
}

import * as React from 'react';
import Layout from '../components/layout';

const IndexPage = () => {
  return (
    <Layout>
      <h1 className="title">Gatsby Blog Site</h1>
    </Layout>
  );
};

export default IndexPage;

CSS Modules

CSS Modulesを利用してスタイルを適用する方法を確認します。Global CSSとは異なりCSS Modulesを利用すると利用したコンポーネントのみCSSが適用されるため、異なるコンポーネントで同じ名前のclass名をつけても名前の重複が発生することはありません。

index.module.cssファイルとabout.module.cssファイルをcomponentsフォルダに作成します。index.module.cssではtitleクラスの色を赤、about.module.cssファイルではtitleクラスの色を青に設定します。titleは同じ名前をつけています。


.title {
  color: red;
}

.title {
  color: blue;
}

それぞれindex.jsとabout.jsファイルでimportします。先ほどlayout.jsファイルでimportしたglobal.cssのimportはコメントしておいてください。


import * as React from 'react';
import Layout from '../components/layout';
import { title } from '../components/index.module.css';
// import './global.css';

const IndexPage = () => {
  return (
    <Layout>
      <h1 className={title}>Gatsby Blog Site</h1>
    </Layout>
  );
};

export default IndexPage;

import * as React from 'react';
import Layout from '../components/layout';
import { title } from '../components/about.module.css';

const AboutPage = () => {
  return (
    <Layout>
      <h1 className={title}>About Page</h1>
    </Layout>
  );
};

export default AboutPage;

index.jsでは文字は赤、about.jsでは文字は青で表示されます。下記はaboutページの青色になった文字のみ表示しています。

CSS Modulesの適用
CSS Modulesの適用

ブラウザのデベロッパーツールを利用して要素に適用されているクラス名を確認するとtitleではなくabout-module–title–hfJuuといった名前がつけられていることがわかります。このように命名してくれることで異なるモジュールファイルで同じクラス名を利用しても重複することがありません。

適用されているクラス名の確認
適用されているクラス名の確認

CSS Modulesの設定方法が確認できたのでindex.modules.css, about.modules.cssのimortの行をindex.jsとabout.jsから削除しclassNameの設定も削除しておきます。

はじめてのGraphQL

GraphQLを利用することでGatsbyの設定ファイルの一つであるgatsby-config.jsファイルに記述したmetaデータを取得することできます。REST APIでは設定ファイルから情報を取得するといったことはないので最初は少し不自然に感じるかもしれません。しかしGatsbyではGraphQLを利用してローカルファイルの中身を取得することができます。

Gatsbyサイトのインストール時にインストールフォルダ直下に作成されるgatsby-config.jsを開いて下記のようにmetaデータを記述しましょう。siteMetadataオブジェクトの中に複数のプロパティと値を設定しています。プロパティについては任意の名前をつけることができます。


module.exports = {
  siteMetadata: {
    title: 'はじめてのGatsby Site',
    author: 'Reffect',
    category: ['Svelte', 'Vue.js', 'React'],
    user: { name: 'John Doe', email: 'john@example.com' },
  },
  /* Your site config here */
  plugins: [],
};

about.jsにGraphQLを記述してgasby-config.jsファイルからmetaデータを取得します。下記の記述はPageQuery(ページクエリ)と呼ばれ、index.js、about.jsのようにページコンポーネント内で利用することができます。queryの結果はdataから取得することができ、data.site.siteMadata.titleでgatsby-config.jsに記述した値を取り出すことができます。


import * as React from 'react';
import Layout from '../components/layout';
import { graphql } from 'gatsby';

const AboutPage = ({ data }) => {
  return (
      <Layout>
        <h2>{data.site.siteMetadata.title}</h2>
        <h1>About page</h1>
      </Layout>
  );
};

export const query = graphql`
  query {
    site {
      siteMetadata {
        title
      }
    }
  }
`;
export default AboutPage;

ブラウザで確認するとGraphQLから取得したtitleが表示されることを確認することができます。

GraphQLでtitle取得
GraphQLでtitle取得
about.jsはページコンポーネントなので上記の記述でtitleを取得することができましたがheader.jsファイルなどの通常のコンポーネントで同様の処理を行うとエラーになります。ページコンポーネント以外のコンポーネントでは後ほど説明するStaticQueryを利用します。

分割代入を利用してpropsのプロパティのdataを取り出していますがpropsを利用すると下記のように記述することができます。console.logを利用してdata以外にどのようなプロパティを持っているかも確認しておきましょう。


import * as React from 'react';
import Layout from '../components/layout';
import { graphql } from 'gatsby';

const AboutPage = (props) => {
  console.log(props)
  return (
      <Layout>
        <h2>{props.data.site.siteMetadata.title}</h2>
        <h1>About page</h1>
      </Layout>
  );
};

export const query = graphql`
  query {
    site {
      siteMetadata {
        title
      }
    }
  }
`;
export default AboutPage;

propsの中身にはdata以外にもlocationやnavigateなどのプロパティも確認できます。

propsの中身の確認
propsの中身の確認

staticQueryの使い方

ページコンポーネントではPageQuery(ページクエリ)を利用することができましたがページコンポーネント以外のコンポーネントではuseStaticQueryを利用してGraphQLでデータを取得することができます。

ここではheader.jsファイルを利用してuseStaticQueryの動作確認を行います。また先ほどのPageQueryとはコードの記述場所が変わります。propsで取得したデータを渡されるのではなくコンポーネントの内側で実行します。


import * as React from 'react';
import { Link, useStaticQuery, graphql } from 'gatsby';

const Header = () => {
  const data = useStaticQuery(
    graphql`
      query {
        site {
          siteMetadata {
            title
          }
        }
      }
    `
  );
  return (
    <header>
      <h2>{data.site.siteMetadata.title}</h2>
      <nav>
        <ul>
          <li>
            <Link to="/">top</Link>
          </li>
          <li>
            <Link to="/about">about</Link>
          </li>
        </ul>
      </nav>
    </header>
  );
};

export default Header;

取得したtitleが画面の一番上に表示されます。

useQueryを利用して取得したデータを表示
useQueryを利用して取得したデータを表示

PageQueryとuseStaticQueryの違いを理解することができました。

ここまではGraphQLのqueryの中身については触れてきませんでした。gatsby-config.jsの他のプロパティを取得したい場合にどのようにして行うかを確認しながらqueryの中身を確認していきます。


export const query = graphql`
  query {
    site {
      siteMetadata {
        title
      }
    }
  }
`;

GraphiQLの使い方

gatsby-config.jsの他のプロパティの値を取得したい場合の正しいqueryをどのように記述するのかをどうすれば知ることができるでしょうか。GraphiQL(※GraphQLではありません)を利用することで正しいqueryを確認することができます。GraphiQLは正しいGraphQLのqueryの構造やどのような情報が取得できるかを確認することができるツールです。

GraphiQLを利用するためには、ブラウザのURLにhttp://localhost:8000/___graphiqlを入れてアクセスします。graphiqlの前には_(アンダーバー)が3つ入ります。本番環境で__graphiqlを入力してもアクセスすることはできません。

GraphiQLのURLはnpm run developコマンドを実行した時に表示されます。


//略
You can now view my-gatsby-site in the browser.
⠀
  http://localhost:8000/
⠀
View GraphiQL, an in-browser IDE, to explore your site's data and schema
⠀
  http://localhost:8000/___graphql
//略

ブラウザから初めてアクセスを行うと下記の画面が表示されます。左側のExplorerを使ってどのような値を取得できるかを確認することができます。

GraphiQLの表示
GraphiQLの表示

GraphiQLの使い方は下記のように中央にqueryを記述して実行を行うとqueryの結果が右側に表示されます。queryの内容は先ほどのPageQueryの内容と同じものをコピー&ペーストしています。GraphiQLの右矢印の実行ボタンを押すと右側にtitleの内容が表示されていることが確認できます。

GraphiQLを使った最初のQuery
GraphiQLを使った最初のQuery

title以外の別のプロパティを取得するためにtitleの下に何か文字を入力すると入力支援で別のプロパティの候補が表示されるので入力の間違いもなく簡単に別のプロパティ情報を見つけることができます。

title以外の別のプロパティ
title以外の別のプロパティ

入力支援を使うことでgatsby-config.jsファイルのすべてのプロパティの情報を取得できるqueryを確認することができます。gatsby-config.jsに設定した文字列だけではなく配列やオブジェクトもqueryを使って取得できていることが確認できます。

metatagのすべてのプロパティの取得
metatagのすべてのプロパティの取得

ここまでの動作確認でGraphQLを利用してgatsby-config.jsファイルのメタタグの情報が取得できるようになりました。

ファイルシステムの情報取得

gatsby-config.jsファイルに対してGraphQLを利用してGatsbyからアクセスすることができましたがその他のページファイルを含めたローカルのファイルシステムにGatsbyのアプリケーションからアクセスするためにはプラグインのインストールが必要になります。

インストールを行うプラグインはgatsby-source-filesystemです。プラグインはGatsbyの公式ホームページ上から確認することができます。Gatsbyの公式ホームページを開いて上部にあるメニューOpen Sourceにカーソルを当てるとメニューが表示されるので”Gatuby Plugins”をクリックします。

Gatsbyのトップページ
Gatsbyのトップページ

Pluginライブラリのページが表示され左側にPluginの検索フォームがありますがこれからインストールを行う”gatsby-source-filesystem”は人気のPluginなので一番上に表示されています。

Plugins一覧の表示
Plugins一覧の表示

プラグインの名前をクリックするとインストール、プラグインの方法が記述されているのでその手順にしたがってインストールと設定を行います。

インストール方法と設定方法
インストール方法と設定方法

サイトフォルダの直下でnpmコマンドを使ってgatsby-source-filesystemプラグインのインストールを行います。


% npm install gatsby-source-filesystem

インストールしたプラグインは先ほどmeta情報を追加したgatsby-config.jsにプラグイン情報を追加する必要があります。

インストールしたgatsby-source-filesystemをgatsby-config.jsファイルに設定する前に設定前後でどのような変化があるのかGraphiQLを利用して確認しておきます。

設定前では全ファイル数を取得するallFileのtotalCountをqueryを実行してもファイルシステムにGatsbyからアクセスできないため0と表示されます。

GraphiQLからファイルの総数を取得
GraphiQLからファイルの総数を取得

gatsby-source-filesystemをインストールしただけではGatsbyからローカルファイルの情報にアクセスできないことがわかりました。

Gatsbyのインストールフォルダ直下のsrc以下のファイルにアクセスできるようにgatsby-config.jsに下記の設定を行います。この設定を行うことでsrc以下のファイルへのアクセスが可能となります。


module.exports = {
  siteMetadata: {
//略
  },
  plugins: [
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        name: `src`,
        path: `${__dirname}/src/`,
      },
    },
  ],
};

gatsby-config.jsを変更したのでnpm run developコマンドを一度停止、再度実行します。その後、先ほど実行したtotalCountを取得するGraphQLのqueryを実行します。設定後はtotalCount数が0から10に増えていることが確認できます。

gatsby.config.jsファイルの更新後のファイル数
gatsby.config.jsファイルの更新後のファイル数

現在のsrcフォルダ内のファイル数totalCount は、現在のフォルダ構成を確認しても10のファイルが存在することが確認できます。

srcフォルダのファイル数の確認
srcフォルダのファイル数の確認

GraphiQLの左側のExplorerを参考にtotalCountだけではなくファイル名やサイズなどの情報も取得してみましょう。相対パスやファイルサイズ、名前や拡張子などさまざまな情報を取得できることがわかります。

ファイル情報の取得
ファイル情報の取得

ここまでの動作確認でローカルのファイルの情報をGraphQLを利用して取得できることがわかったので取得したデータをブラウザ上に表示させる方法を確認してみましょう。

Gatsbyのファイル内で記述するqueryのコードはGraphiQLのCode Exporterをクリックすることで確認することができます。GraphiQLではどのような情報が取得できるか確認できる上、実際にコードに記述するQueryも確認することができます。

Code ExplorerでQueryを確認
Code ExplorerでQueryを確認

about.jsファイルの中にファイル情報取得のGraphQLコードを記述します。about.jsファイルはページファイルなのでPageQueryを利用します。Code Expoterに表示されているコードをコピー&ペーストすることができます。


import * as React from 'react';
import Layout from '../components/layout';
import { graphql } from 'gatsby';

const AboutPage = ({ data }) => {
  console.log(data);
  return (
    <Layout>
      <h1>About page</h1>
      <table>
        <thead>
          <tr>
            <th>パス</th>
            <th>サイズ</th>
            <th>作成時間</th>
          </tr>
        </thead>
        <tbody>
          {data.allFile.edges.map((edge) => (
            <tr kye={edge.node.ctime}>
              <td>{edge.node.relativePath}</td>
              <td>{edge.node.size}</td>
              <td>{edge.node.ctime}</td>
            </tr>
          ))}
        </tbody>
      </table>
    </Layout>
  );
};

export const query = graphql`
  query {
    allFile {
      totalCount
      edges {
        node {
          relativePath
          size
          extension
          name
          ctime
        }
      }
    }
  }
`;
export default AboutPage;

ブラウザで確認すると下記のようにGraphQLで取得したデータを表示させることができます。

ローカルファイルの情報を表示
ローカルファイルの情報を表示

GraphQLを利用してローカルに保存されているファイル情報を取得し、map関数で展開しブラウザで表示することができるようになりました。

Markdownファイルからの読み込み

これまでの説明でファイルのパスやサイズなどの情報を取得する方法がわかりました。GatsbyのGraphQLではファイルの情報だけではなくファイルの中身も取得することができます。GatsbyからGraphQLを利用してMarkdown(マークダウン)ファイルへアクセスを行い、ファイルの中身が取得できることを確認していきます。

ブログの記事の内容が記述されているMarkdownの中身を取得することでできれば文字だけのブログサイトを構築することが可能です。

画像の取得はまた別の機能が必要となるので後ほど説明を行います。

Markdown(マークダウン)とは

WEBページを作成する際、通常はHTMLで記述します。HTMLでWEBページを作成するためにはタグを理解する必要があり使いこなすまでに時間が必要となります。しかしMarkdownではタグの変わりにシンプルなSyntax(シンタックス)を利用するので読みやすく軽量のためHTMLと比較すると使いこなすまでの時間があまりかかりません。一般的なユーザにMarkdownを覚えてもらうことは難しいですがエンジニアであれば覚えることはそれほど難しくありません。また作成したMarkdownで記述したファイルはパーサーによりHTMLに変換を行うことができます。ブログの記事やGitHub, Qiita, Zennなどでも利用されており、ファイルの拡張子はmdです。

本文書についてはMarkdownの記述方法についての細かな説明を行いませんが、Markdownの記述方法を知らなくてもこれから説明する内容への影響はありません。

Markdownファイルの作成

Markdownファイルを保存するフォルダpostsをsrcフォルダの下に作成します。

ファイル名をfirst-article.mdとし、ファイルの先頭にはメタデータを記述するfront matter(フロントマター)を記述します。titleとdateを記述していますがプロパティと値のペアであればなんでも追加することができます。

front matterは3つのハイフンで囲みます。###は見出しの設定を行っておりh3タグを意味します。見出しの下に2行の文を追加します。2行の間に1行空白行を入れることで改行を行うhtmlに変換するpタグが別々に設定されます。###や空白の情報をmdからHTMLへの変換時にパーサーが理解してタグのないMarkdownのテキスト文書をHTMLへ変換します。

mdファイルを作成
mdファイルを作成

---
title: "はじめての記事"
date: "2020-08-18"
---

### Gatsbyでの最初の記事

Gatsbyサイト上に表示するための初めての記事です。
ブラウザ上に表示されるのか確認です。

プラグインのインストール

mdファイルを作成しましたがGatsbyからファイルの中身を確認することができません。mdファイルの内容を取得してブラウザ上に表示させるためにはHTMLに変換する必要があります。そのためには新たにプラグインをインストールする必要があります。

インストールするプラグインは、gatsby-transfermer-remarkです。GatsbyサイトのPluginでremarkと入力すると表示されます。remarkというのはMarkdownからHTMLに変換するために利用するライブラリの名前です。

Gatsby Pluginの検索
Gatsby Pluginの検索

表示される手順に従ってプラグインのインストールを行います。


npm install --save gatsby-transformer-remark

インストールしたプラグインはgatsby-config.jsに追加する必要があります。


plugins: [
  {
    resolve: `gatsby-source-filesystem`,
    options: {
      name: `src`,
      path: `${__dirname}/src/`,
    },
  },
  "gatsby-transformer-remark",
],
gatsby-config.jsを更新した場合はnpm run develop/gatsby developコマンドを再実行してください。

gatsby-config.jsに追加後にGraphiQLにアクセスしてExplorerを表示するとallMarkdownRemarkとmarkdownRemarkが追加されていることを確認することができます。この2つを利用することでMarkdownファイルにアクセスすることができます。

markdownremark追加
markdownremark追加

Markdownファイルの内容取得

追加されたallMarkdownRemarkを利用してmdファイルの内容を確認していきます。Explorerを確認しながらfrontmatterでtitleとdate、htmlで内容、文字数から文書を読む時間を算出したtimeToReadの値を取得します。

mdファイルの内容取得
mdファイルの内容取得

mdファイルの内容を取得するためのGraphQLのqueryがわかったのでindex.jsファイルにqueryを追加してブラウザ上に表示させます。


import * as React from 'react';
import Layout from '../components/layout';
import { graphql } from 'gatsby';

const IndexPage = ({ data }) => {
  return (
    <Layout>
      <h1>Gatsby Blog Site</h1>
      {data.allMarkdownRemark.edges.map((edge) => (
        <div key={edge.node.id}>
          <h2>{edge.node.frontmatter.title}</h2>
          <p>{edge.node.frontmatter.date}</p>
          <div dangerouslySetInnerHTML={{ __html: edge.node.html }} />
        </div>
      ))}
    </Layout>
  );
};

export const query = graphql`
  query {
    allMarkdownRemark {
      edges {
        node {
          html
          timeToRead
          frontmatter {
            title
            date
          }
        }
      }
    }
  }
`;

export default IndexPage;

ブラウザで確認を行うとCSSの設定を行っていないのでわかりにくいかもしれませんが、title, dateとhtmlの内容がすべてブラウザ上に表示されていることが確認できます。mdファイルに指定したシンタック###(h3)やpタグの設定が反映されていることがわかります。

Markdownファイルの中身をブラウザ上に表示
Markdownファイルの中身をブラウザ上に表示

1つの記事しか作成していなかったのでもう一つ追加でmdファイルを作成します。作成場所はpostsフォルダの下でファイル名はsecond-article.mdとしています。


---
title: '2回目の記事'
date: '2022-10-05'
---

### Gatsby での 2 回目の記事

Gatsby サイト上に表示されることが確認できたので、2 回目の記事を追加しました。

allMarkdownRemarkはすべてのmdファイルの情報を取得しているので、記事を作成するとコードの変更なしで追加したmdファイルの内容が表示されます。

2つ目のMarkdownファイルも表示
2つ目のMarkdownファイルも表示

ここまでの説明でGraphQLを利用してローカルファイルへのアクセス、mdファイルの内容を取得できるようになり、GatsbyにおけるGraphQLの使い方と取得後のデータの処理について確認することができました。

個別ページの表示設定

ブラウザ上にpostsフォルダに保存したマークダウンファイルの内容を一覧として表示できるようになったので次は各記事の個別ページが表示できるように設定を行なっていきます。Gatsbyの持つFilesystem Route APIを利用しています。

個別ページは/posts/first-article, /posts/second-articleといったURLでアクセスできるように設定を行います。indexページやaboutページと異なり/posts/以下のURLの値は動的に変わることになります。動的に変わるためindexページやaboutページとは異なる仕組みを利用する必要があります。動的に変わる部分にslugとしてMarkdownファイルのfrontmatterに設定します。


---
title: 'はじめての記事'
date: '2022-10-05'
slug: 'first-article'
---

---
title: 'はじめての記事'
date: '2022-10-05'
slug: 'second-article'
---

slugをMarkdownファイルに追加することでGraphQLではslugの値を使って各ページの情報のみ取得することができます。

下記では$slugという変数をQueryに追加し、QUERY VARIABLESで変数に設定する値を指定しています。slugにfirst-articleを設定しているのでslugにfirst-articleを持つMarkDownファイルのみhtml, title, slugが取得できています。変数を利用することで取得したい記事のみ取得できるようになります。

slugを利用して情報を取得
slugを利用して情報を取得

slugを利用してMarkdownファイルの情報取得の方法がわかったのでpagesフォルダの下にpostsフォルダを作成し、その中に{markdownRemark.frontmatter__slug}.jsファイルを作成します。/posts/first-article, /posts/second-articleにアクセスすると作成したファイルの内容が表示されます。


import * as React from 'react';

export default function BlogPostTemplate(props) {
  console.log(props);
  return <p>Blog Page</p>;
}
/posts/の後ろにslugに設定していない値を指定するとエラーになります。

propsの中のpageContextというプロパティをみるとfrontmatter__slugとファイルのidの値がGatsbyが自動で取得してくれていることがわかります。

テンプレートファイルの表示
テンプレートファイルの表示

このidをqueryに利用することができ、この値を利用してMarkdownファイルの中身を取得します。


import { graphql } from 'gatsby';
import * as React from 'react';
import Layout from '../../components/layout';

export default function BlogPostTemplate({ data: { markdownRemark } }) {
  const { frontmatter, html } = markdownRemark;
  return (
    <Layout>
      <h2>{frontmatter.title}</h2>
      <div>{frontmatter.date}</div>
      <div className="post-body" dangerouslySetInnerHTML={{ __html: html }} />
    </Layout>
  );
}

export const query = graphql`
  query ($id: String!) {
    markdownRemark(id: { eq: $id }) {
      html
      frontmatter {
        date(formatString: "MMMM DD, YYYY")
        title
      }
    }
  }
`;

idではなくfrontmatter__slugを利用することもできます。


export const query = graphql`
  query ($frontmatter__slug: String) {
    markdownRemark(frontmatter: { slug: { eq: $frontmatter__slug } }) {
      html
      id
      frontmatter {
        title
        slug
      }
    }
  }
`;

/posts/second-articleにアクセスを行うとsecond-article.mdファイルの中身のみ表示されます。記事の個別ページの表示を行えるようになりました。

個別ページの表示
個別ページの表示

リンクの設定

トップページに表示されているブログの記事一覧から記事ページへのリンクを設定します。queryで取得する値にslugを追加しています。リンクにはLinkコンポーネントを利用しているのでimportする必要があります。


import * as React from 'react';
import Layout from '../components/layout';
import { graphql, Link } from 'gatsby';

const IndexPage = ({ data }) => {
  return (
    <Layout>
      <h1>Gatsby Blog Site</h1>
      {data.allMarkdownRemark.edges.map((edge) => (
        <div key={edge.node.id}>
          <h2>
            <Link to={`/posts/${edge.node.frontmatter.slug}`}>
              {edge.node.frontmatter.title}
            </Link>
          </h2>
          <p>{edge.node.frontmatter.date}</p>
          {/* <div dangerouslySetInnerHTML={{ __html: edge.node.html }} /> */}
        </div>
      ))}
    </Layout>
  );
};

export const query = graphql`
  query {
    allMarkdownRemark {
      edges {
        node {
          id
          html
          timeToRead
          frontmatter {
            title
            date
            slug
          }
        }
      }
    }
  }
`;

export default IndexPage;

ブラウザで確認すると記事一覧のタイトルにリンクが貼られ、クリックするとクリックした記事のページが表示されます。

記事一覧へのリンク設定
記事一覧へのリンク設定

画像の設定

アクセスしてきたユーザにブログの中身を読んでもらうためブログの各記事のページの上部にブログの内容を反映した画像を配置します。その場合はfront matterに画像情報の設定を追加することでページ上部に画像表示を行うことが可能です。

プラグインのインストール

front matterで設定する画像を表示するために3つのプラグインをインストールします。gatsby-plugin-image, gatsby-transformer-sharp, gatsby-plugin-sharpです。以前はgatsby-imageではなくgatsby-plugin-imageなので注意してください。


 % npm install gatsby-transformer-sharp gatsby-plugin-sharp gatsby-plugin-image

プラグインのインストールが完了したらgatsby-config.jsファイルにプラグインの設定を行います。


module.exports = {
  siteMetadata: {
//略
  },
  plugins: [
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        name: `src`,
        path: `${__dirname}/src/`,
      },
    },
    'gatsby-transformer-remark',
    `gatsby-plugin-image`,
    `gatsby-transformer-sharp`,
    `gatsby-plugin-sharp`,
  ],
};

Markdownファイルに新たにhero_imageを追加しローカルに保存されているファイルのパスを指定します。imagesフォルダに保存されているicon.pngを利用します。


---
title: 'はじめての記事'
date: '2022-10-05'
slug: 'first-article'
hero_image: '../images/icon.png'
---

### Gatsby での最初の記事

Gatsby サイト上に表示するための初めての記事です。
ブラウザ上に表示されるのか確認です。

GraphQLを使ってfrontmatterのhero_imageの情報を取得します。hero_imageを開いてchildImageSharpを選択してgasbyImageDataをチェックしています。実行すると画像の情報を取得することができます。

画像の情報を取得
画像の情報を取得

画像の取得を行うQueryは{markdownRemark.frontmatter__slug}.jsで利用します。gatsby-plugin-imageからimportしたgetImage関数とGatsbyImageコンポーネントを利用しています。getImage関数でfrontmatter.hero_imageの情報をGatsbyImageで利用できるimageオブジェクトに変換しています。GatsbyImageコンポーネントはimage属性だけではなくalt属性も必要になります。altについてもfont matterに設定してGraphQLで取得することは可能です。ここではaltに”Hero Image”を設定しています。


import { graphql } from 'gatsby';
import * as React from 'react';
import Layout from '../../components/layout';
import { getImage, GatsbyImage } from 'gatsby-plugin-image';

export default function BlogPostTemplate({ data: { markdownRemark } }) {
  const { frontmatter, html } = markdownRemark;
  const image = getImage(frontmatter.hero_image);
  return (
    <Layout>
      <GatsbyImage image={image} alt="Hero Image" />
      <h2>{frontmatter.title}</h2>
      <div>{frontmatter.date}</div>
      <div className="post-body" dangerouslySetInnerHTML={{ __html: html }} />
    </Layout>
  );
}

export const query = graphql`
  query ($id: String!) {
    markdownRemark(id: { eq: $id }) {
      id
      html
      frontmatter {
        date(formatString: "MMMM DD, YYYY")
        title
        hero_image {
          childImageSharp {
            gatsbyImageData
          }
        }
      }
    }
  }
`;

ブラウザで確認すると指定した画像が表示されます。ブログの先頭に表示されるheroイメージの設定方法を理解することができました。

frontmatterで指定した画像の表示
frontmatterで指定した画像の表示

markdownファイルのコンテンツの画像を表示

front mattterで指定した画像の表示方法がわかったので次はMarkdownファイルの中で設定した画像の表示方法を確認します。

Markdownファイルで画像ファイルを指定する時は下記のようにMarkdown記法で記述することができます。[]の部分がimgタグのalt属性に対応します。


---
title: 'はじめての記事'
date: '2022-10-05'
slug: 'first-article'
hero_image: '../images/icon.png'
---

### Gatsby での最初の記事

Gatsby サイト上に表示するための初めての記事です。
ブラウザ上に表示されるのか確認です。

![テスト画像](../images/icon.png)

しかし、現在の設定では画面上に画像は表示されません。

Markdownの中で設定した画像を表示するためにはgatsby-remark-imagesプラグインをインストールする必要があります。


 % npm install gatsby-remark-images

プラグインをインストールした後はgatsby-config.jsファイルを更新する必要があります。


module.exports = {
  siteMetadata: {
    //略
  },
  plugins: [
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        name: `src`,
        path: `${__dirname}/src/`,
      },
    },
    `gatsby-plugin-image`,
    `gatsby-transformer-sharp`,
    `gatsby-plugin-sharp`,
    {
      resolve: `gatsby-transformer-remark`,
      options: {
        plugins: [
          {
            resolve: `gatsby-remark-images`,
            options: {
              maxWidth: 700,
              showCaptions: true,
            },
          },
        ],
      },
    },
  ],
};

gatsby-remakr-imagesではオプションがいくつか存在するのでmaxWidthとshowCaptionsを設定しています。そのほかのオプションについてはドキュメントを確認してください。maxWidthを設定すると画像がブラウザ上でそれ以上の大きさにはなりません。showCaptionsをtrueにするとaltに設定した文字列が画像の下に表示されます。元の画像のWidthがmaxWidthより小さい場合は元の画像のサイズで表示されます。

gatsby-config.jsファイルを更新した後はnpm run developコマンドを再実行してください。

ブラウザで確認すると画像が表示されています。左下にはキャプションで”テスト画像”が表示されています。”テスト画像”の文字列はfigcaptionタグが利用されています。

Markdownファイル内の画像を表示
Markdownファイル内の画像を表示

maxWidthを200に設定すると画像が小さくなることも確認できます。

optionsのmaxWidthを変更
optionsのmaxWidthを変更

Markdownで指定した画像も表示できるようになりました。

Gatsby Cloudへのデプロイ

GatsbyではGatsby Cloudというクラウドサービスを提供しておりGatsbyで構築したアプリケーションをデプロイすることができます。有料のプランもありますが無料プランを利用することができます。

Gatsby Cloudへのデプロイでは最初にGitHubにPushし、そこからGatsby CloudとGiHubを連携しデプロイします。

GitHubレポジトリの作成

GitHubのアカウントでログインしてGatsby用の新たしいリポジロリの作成を行います。Repository nameはここではgatsby-blogとしています。任意の名前をつけてください。

リポジトリの作成画面
リポジトリの作成画面

“Create repository”ボタンをクリックするとローカルファイルをGitHubのレポジトリにpushするまでの方法が表示されるのでその手順に沿ってpushを行います。

レポジトリへのpush方法
レポジトリへのpush方法

 % echo "# gatsby-blog" > README.md 
 % git init
Reinitialized existing Git repository in /Users/mac/Desktop/my-gatsby-site/.git/
 % git add .
 % git commit -m "first commit"
[master 69f9d9c] first commit
 1 file changed, 1 insertion(+), 54 deletions(-)
 rewrite README.md (100%)
 % git branch -M main
 % git remote add origin https://github.com/reffect2020/gatsby-blog.git
 % git push -u origin main
Enumerating objects: 16, done.
Counting objects: 100% (16/16), done.
Delta compression using up to 4 threads
Compressing objects: 100% (13/13), done.
Writing objects: 100% (16/16), 294.69 KiB | 9.21 MiB/s, done.
Total 16 (delta 2), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (2/2), done.
To https://github.com/reffect2020/gatsby-blog.git
 * [new branch]      main -> main
Branch 'main' set up to track remote branch 'main' from 'origin'.

pushが完了するとレポジトリにアップしたファイルを確認することができます。

レポジトリにpushしたファイルの確認
レポジトリにpushしたファイルの確認

Gatsby Cloudの設定

gatsbyjs.comにアクセスして画面左上部にある”Sign Up for Free”か画面の中央付近にある”Get Started For Free”ボタンをクリックします。

Gatsbyjs.comのトップページ
Gatsbyjs.comのトップページ

サインインの画面が表示されてるので”GitHub”や”GitLab”など利用しているGitのアカウントを利用してサインインを行います。本文書ではGitHubのアカウントを利用します。

Gatsby Cloudへのサインアップ
Gatsby Cloudへのサインアップ

Gatsby CloudからGitHubアカウントへのアクセス許可についての確認画面が表示されるので”Authroze Gatsby Cloud”をクリックします。

Gatsby CloudとGitHunのアカウントの連携
Gatsby CloudとGitHunのアカウントの連携

個人情報入力画面が表示されるので入力を行ってください。

個人情報の入力画面
個人情報の入力画面

入力を行い”Complete sign up”ボタンをクリックすると以下のダッシュボード画面が表示されます。”Add a site”ボタンをクリックしてください。

Gatsby Cloudのダッシュボード画面
Gatsby Cloudのダッシュボード画面

Gitリポジトリからimportするための画面が表示されるのでGitHubをクリックします。

Gitリポジトリのimport
Gitリポジトリのimport

初めてアクセスした場合はリポジトリを選択するために”Click here to add an installation”をクリックしてください。

リポジトリへのアクセス
リポジトリへのアクセス

Gatsby Cloudからアクセスできるリポジトリを選択します。Only select repositoriesのラジオボタンをチェックしてGatsbyのコードが保存されたリポジトリを選択してください。

リポジトリの選択
リポジトリの選択

その後にパスワードの確認画面が表示されます。GitHubアカウントのパスワードを入力してください。

パスワードの入力画面
パスワードの入力画面

リポジトリのimportが可能になります。

リポジトリのimport
リポジトリのimport

Site NameやProduction branchは設定されたまま以下の画面が表示されるので”Next”ボタンをクリックします。

Basic Configration
Basic Configration

環境変数の設定を行うことができますが今は設定する環境変数はないのでブランクのまま”Build Site”ボタンをクリックします。

環境変数の設定
環境変数の設定

これで設定は完了です。

ビルドが完了すると以下の画面が表示されます。デプロイするとURLが発行されるのでデプロイした内容を確認することができます。もしビルドが開始されていない場合は”Trigger build”を実行するとビルドが行われます。

デプロイが完了した時のダッシュボード
デプロイが完了した時のダッシュボード

表示されているURLにブラウザからアクセスすると以下の画面が表示されます。

デプロイしたサイトの確認
デプロイしたサイトの確認

個別のブログページにもアクセスができ画像も表示されます。

metaタグの設定方法(SEO)

Googleなどの検索エンジンにコンテンツの内容を正しく伝えるためにはtitleやdescriptionなどのmetaタグを設定する必要があります。

以前のバージョンではSEOを設定するためにはプラグインgatsby-plugin-react-helmetを利用していましたが現在のバージョンでは必要ありません。

aboutページにタイトルを設定したい場合はHeadコンポーネントを追加するだけで設定を行うことができます。


import * as React from 'react';
import Layout from '../components/layout';
import { graphql } from 'gatsby';

const AboutPage = ({ data }) => {
  return (
    <Layout>
//略
    </Layout>
  );
};

export const query = graphql`
  query {
//略
  }
`;
export default AboutPage;

export const Head = () => {
  return <title>Aboutページ</title>;
};

Headコンポーネントを設定後にブラウザのタブを確認するとHeadコンポーネントで設定したtitleた設定されていることがわかります。

Headコンポーネントの設定
Headコンポーネントの設定

descriptionも同様にHeadコンポーネントで設定を行います。


export const Head = () => {
  return (
    <>
      <title>Aboutページ</title>
      <meta
        name="description"
        content="Aboutページにはファイル一覧が表示されています"
      />
    </>
  );
};

ブラウザのデベロッパーツールを利用することでdescriptionが設定されていることを確認することができます。

titleタグとdescriptionを確認
titleタグとdescriptionを確認

about.jsファイルだけではなくindex.jsファイルでも同様の方法で設定を行うことができます。デフォルト値をgatsby-config.jsファイルに記述することでgatsby-config.jsファイルから必要なmetaタグに必要な情報を取得することができます。

gatsby-config.jsのsiteMetadataにdescriptionを追加します。gatsby-config.jsファイルを更新したらnpm run developコマンドを再実行してください。


module.exports = {
  siteMetadata: {
    title: 'はじめてのGatsby Site',
    description:'Gatsbyを利用して構築したブログサイトです。',
    author: 'Reffect',
    category: ['Svelte', 'Vue.js', 'React'],
    user: { name: 'John Doe', email: 'john@example.com' },
  },
//略

gatsby-config.jsファイルに記述したsiteMetadataをHooksを利用して取得できるようにsrcフォルダにhooksフォルダを作成し、その下にuseSiteMetadata.jsファイルを追加します。

useSiteMetadata Hookの中でGraphQLを利用してgatsby-config.jsファイルからsiteMetadataを取得しています。


import { graphql, useStaticQuery } from 'gatsby';

export const useSiteMetadata = () =< {
  const data = useStaticQuery(graphql`
    query {
      site {
        siteMetadata {
          title
          description
        }
      }
    }
  `);

  return data.site.siteMetadata;
};

追加したuseSiteMetadataは新たにseo.jsファイルをcomponentsフォルダ下に作成してseo.jsファイルの中で実行します。propsでtitle, descriptionを受け取れるように設定し、useSiteMetadata Hookから取得した値は初期値として利用します。propsでtitleやdescriptionが渡されない場合はgatsby-config.jsファイルのsiteMetadataで設定した値が利用されることになります。


import React from 'react';
import { useSiteMetadata } from '../hooks/useSiteMetadata';

export const Seo = ({ title, description, children }) => {
  const { title: defaultTitle, description: defaultDescription } =
    useSiteMetadata();

  const seo = {
    title: title || defaultTitle,
    description: description || defaultDescription,
  };

  return (
    >>
      >title>{seo.title}>/title>
      >meta name="description" content={seo.description} />
      {children}
    >/>
  );
};

about.jsファイルでmetaタグを設定するためHeadコンポーネントではimportしたSEOコンポーネントを利用します。


import * as React from 'react';
import Layout from '../components/layout';
import { graphql } from 'gatsby';
import { Seo } from '../components/seo';

//略

export const Head = () => <Seo />;

ブラウザで確認するとsiteMetadataに設定した値がtitleに設定されていることがブラウザのタブから確認できます。

SEOコンポーネントを利用したtitleの確認
SEOコンポーネントを利用したtitleの確認

もしtitleやdescriptionを変更したい場合にはpropsを利用して設定することができます。


export const Head = () => ;

titleを設定することでデフォルト値ではなく設定した値が表示されます。

index.jsやabout.jsではtitleを個別に設定することが可能ですがブログの記事の個別ページの場合には値が動的に変わるためpropsで受け取った値を利用して設定を行います。設定は{markdownRemark.frontmatter__slug}.jsファイルで行います。


import { graphql } from 'gatsby';
import * as React from 'react';
import Layout from '../../components/layout';
import { getImage, GatsbyImage } from 'gatsby-plugin-image';
import { Seo } from '../../components/seo';

export default function BlogPostTemplate({ data: { markdownRemark } }) {
  const { frontmatter, html } = markdownRemark;
  const image = getImage(frontmatter.hero_image);
  return (
    <Layout>
      <GatsbyImage image={image} alt="Hero Image" />
      <h2>{frontmatter.title}</h2>
      <div>{frontmatter.date}</div>
      <div className="post-body" dangerouslySetInnerHTML={{ __html: html }} />
    </Layout>
  );
}

export const query = graphql`
  query ($id: String!) {
    markdownRemark(id: { eq: $id }) {
      id
      html
      frontmatter {
        date(formatString: "MMMM DD, YYYY")
        title
        hero_image {
          childImageSharp {
            gatsbyImageData
          }
        }
      }
    }
  }
`;

export const Head = ({ data: { markdownRemark } }) => {
  const { frontmatter } = markdownRemark;
  return <Seo title={frontmatter.title} />;
};

ブラウザで記事ページを確認するとMarkdownファイルのfront matterで設定したtitleが表示されることが確認できます。

Markdownから取得したtitleが表示
Markdownから取得したtitleが表示

SEOの設定方法を理解することができました。

スクラッチからインターネット上にブログを公開するまでの手順を確認することができました。本格的なブログサイトとして公開するためにtile, description以外のSEOの設定やページネーションの設定が必要となります。