2020年の夏から、ブログをWordPressからGatsbyに変えて一年ほど運用していました。
2021年9月現在は、ブログ自体はWordPressに戻しましたが、ポートフォリオはGatsbyJSで制作しています。
この記事では、はじめてGatsbyJSをブログを完成させるまでの手順をまとめておきます。
2021/09/30 Gatsby v3の変更点をふまえて、全体的にリバイスしました。
- GatsbyJSってそもそもなんなのか知りたい
- GatsbyJSとWordPressの違いを知りたい
- GatsbyJSでブログを作ってみたい
GatsbyJSとは?
GatsbyJSは、Reactベースの静的サイトジェネレーター。Reactで作られたフレームワークで、WebサイトのHTMLファイルを生成してくれるツールです。
WordPressなどのCMSは、データベースで記事を管理しています。
これは、ユーザーがURLにアクセスしたときに、データベースから必要な記事を取得して、HTMLファイルを生成して表示させる仕組みで動いています。
一方で、静的ジェネレーターは、コンパイル時に全てのHTMLファイルをあらかじめ生成していきます。URLにアクセスされた時には、生成済みのHTMLファイルを表示するだけなので、表示速度が早くなります。
また、サーバーやデータベースの管理も不要になるので、運営費用が安くすむ&セキュリティリスクが低くなるというメリットもあります。
GatsbyJSでブログを作るメリット
- サーバーが必要ないので、サーバー代が0円になる
- ブログ記事をバージョン管理できる
- ホームページの表示が早くなる
特にGatsbyは画像のプラグインが優秀で、画像を早く最適化して表示してくれます。
- 画像の圧縮
- 画面サイズに応じた表示
- 遅延読み込み
- 大量の記事を扱うメディアには向かない
- gitやReact、GraphQLの知識が必要
- 記事の装飾やレイアウトなどは自分でプログラムを書く必要がある
私は2020年の夏から、一年ほど、Gatsbyでブログを運営していました。
マークダウンで記事を管理できるのはとても便利でした。
ただ、吹き出しをいれる、飾り枠を入れるなど、HTML/CSSを書いて都度組み込む必要があるのが大変でした。
シンプルに文章を書く、画像を掲載するだけなら、問題ありません。
しかし、記事のレイアウトにこだわる場合は、WordPressのブロックエディターの方が使いやすいです。
一方で、画像の表示は早いですし、コンテンツの管理楽。
ポートフォリオの作品など、決まった項目を好きなレイアウトで表示させる系のウェブサイトには向いていると思います。
GatsbyJSのインストールとプロジェクト作成
2021/09/30 Gatsby v3の変更点を反映しました。
ここからは、GatsbyJSでブログの作り方を紹介していきます。
基本は、Gatsbyのチュートリアルに沿って作っていくと間違いがないと思います。
- Gatsby v3で作成
- CMSは使用せず、プロジェクト内で記事を保管
- Markdownで記事を管理
- 固定ページ/ブログ記事一覧/個別記事を作成
Githubでプログラムを公開しているので、ご参照ください。公開しているプロジェクトはポートフォリオサイトですが、この記事では、ブログ作成用に必要なプラグインや手順を解説していきます。
1. Gatsbyをインストール
Gatsbyをインストールします。
npm install -g gatsby-cli
2. スターターテーマのインストール
スターターテーマをインストールします。
npx gatsby new gatsby-starter-default https://github.com/gatsbyjs/gatsby-starter-default
gatsby-starter-defaultはプロジェクト名で、好きな名前に変えてOK。
そのディレクトリの中に初期ファイルが作成されます。
gatsby-starter-defaultディレクトリ内に移動し、開発サーバーを起動します。
cd gatsby-starter-default
gatsby develop
起動したら、Webブラウザで下記URLにアクセスします
http://localhost:8000/
画面上にGatsby Default Starterのレイアウトが表示されればOK!
ctrl+Cでサーバーを終了できます。
コマンド | 説明 |
gatsby build | ビルド |
gatsby develop | 開発用サーバーの起動 |
gatsby clean | .cache とpublic を空にする |
GatsbyJSでブログを作るまでにやったこと
プロジェクトの中身はこのようになっています。
gatsby-browser.js // グローバルCSSやフォントのパッケージをここで読み込む
gatsby-config.js // 基本情報、プラグインの設定
gatsby-node.js // 特に使わない
gatsby-ssr.js // 特に使わない
src/
├ components/
// ページ内で利用するパーツを入れる
├ header.js
├ layout.css
├ layout.js
└ seo.js
├ images/
// 画像を格納する場所
└ gatsby-astronaut.png
└ pages/
// ページのレイアウト
├ 404.js // 404ページ
├ index.js // indexページ
├ page-2.js
└ using-typescript.tsx //使わないので削除
1 gatsby-config.jsの設定
gatsby-config.jsには、サイトの情報や、サイトに使うプラグインなどの設定を記載します。
サイトの基本情報を設定
siteMetadata: {
title: `Zero Forest`,
description: `フリーランスエンジニアのブログ`,
author: `@emmie0works`,
siteUrl: `https://0forest.com/`,
},
siteMetadata内のtitle, description, author, siteURLを自分のサイト用に書き換えます。
Faviconを設定
plugin内のgatsby-plugin-manifestのoptionに、自分のサイト用に変更します。
plugins: [
// 中略
{
resolve: `gatsby-plugin-manifest`,
options: {
name: `Zero Forest`,
short_name: `0forest`,
start_url: `/`,
background_color: `#663399`,
theme_color: `#663399`,
display: `minimal-ui`,
icon: `src/images/gatsby-icon.png`,
},
},
],
}
アイコンはsrc/images内に保管して、相対パスを記載します。
入力したら、ターミナルで「gatsby build」コマンドを実行すると、public/icons内が指定したアイコンになります。
2. ページの作成
ページの基本レイアウト
src/components/layout.jsで、ページのレイアウトを構成しています。
layout.js内で、ヘッダー部分(src/components/header.js)、フッター部分(src/components/footer.js)をインポートしています。
import * as React from "react"
import PropTypes from "prop-types"
import { useStaticQuery, graphql } from "gatsby"
import Header from "./header"
import Footer from "./footer"
const Layout = ({ children }) => {
const data = useStaticQuery(graphql`
query SiteTitleQuery {
site {
siteMetadata {
title
}
}
}
`)
return (
<>
<Header siteTitle={data.site.siteMetadata?.title || `Title`} />
<main>{children}</main>
<Footer />
</>
)
}
Layout.propTypes = {
children: PropTypes.node.isRequired,
}
export default Layout
ヘッダー
import * as React from "react"
import PropTypes from "prop-types"
import { Link } from "gatsby"
import logo from "../images/logo.png"
import * as styles from "../styles/_header.module.scss"
const Header = ({ siteTitle }) => (
<header>
<h1><Link to ="/"><img src={logo} alt={siteTitle} className={styles.logo} /></Link></h1>
<nav>
<ul>
<li><Link to ="/">Top</Link></li>
<li><Link to ="/blog">Blog</Link></li>
<li><Link to ="/about/">About</Link></li>
<li><Link to ="/contact/">Contact</a></li>
</ul>
</nav>
</header>
)
Header.propTypes = {
siteTitle: PropTypes.string,
}
Header.defaultProps = {
siteTitle: ``,
}
export default Header
//画像のインポート
import logo from "../images/logo.png"
//画像の表示
<img src={logo} alt={siteTitle} className={styles.logo} />
フッター
import * as React from "react"
import { Link } from "gatsby"
import * as styles from "../styles/_footer.module.scss"
const Footer = () => (
<footer>
<nav>
<ul>
<li><Link to ="/">Top</Link></li>
<li><Link to ="/blog/">Gallery</Link></li>
<li><Link to ="/about/">About</Link></li>
<li><Link to ="/contact/">Contact</Link></li>
</ul>
</nav>
<div className={styles.copyright}>© <a href="https://0forest.com">{siteTitle}</a></div>
</footer>
)
export default Footer
内部リンクについては、<Link>タグを使います。(import { Link } from “gatsby”を忘れずに。)
外部リンクは<a>タグを使います。
各ページ
src/pages内のjsファイルが各ページのコンテンツになります。
- index.js → /
- about.js → /about/
- 404.js → /404/
3. 画像の表示
GatsbyJSには2種類の画像コンポーネントがあります。
1.StaticImage
ヒーローイメージなど、テンプレート内で毎回同じ画像を表示させるときはStatic Imageコンポーネントを使う。
2.GatsbyImage
ブログ記事のアイキャッチ画像など、同じテンプレート内でもページによって表示する画像が変わるときにはDynamic Imageコンポーネントを使います。
GatsbyImageはブログページを作成するときに説明するので、ここではStaticImageコンポーネントの使い方を説明します。
- gatsby-plugin-image
- gatsby-transformer-sharp
- gatsby-plugin-sharp
- gatsby-source-filesystem
画像表示には、上記のプラグインを利用します。(今回のスターターテーマには、すでにインストールされているので、改めてプラグインをインストールする必要はありません。)
インストールされていないテーマの場合は下記コマンドでプラグインをインストールします。
※gatsby-config.js内に上記プラグイン名が記載されていれば、インストール済みです。
npm install gatsby-plugin-image gatsby-plugin-sharp gatsby-source-filesystem gatsby-transformer-sharp
続いて、gatsby-config.jsにプラグインの情報を追記します。
source-file-system内のpathは画像フォルダへの相対パスになります。
plugins: [
// 中略
`gatsby-plugin-image`,
{
resolve: `gatsby-source-filesystem`,
options: {
name: `images`,
path: `${__dirname}/src/images`,
},
},
`gatsby-transformer-sharp`,
`gatsby-plugin-sharp`,
],
画像の表示方法
① gatsby-plugin-imageをインポートし、
② StaticImageタグで画像を表示させます。
index.js内に見本として、宇宙飛行士の画像が掲載されています。
import * as React from "react"
import { Link } from "gatsby"
import { StaticImage } from "gatsby-plugin-image" // ①gatsby-plugin-imageをインポート
import Layout from "../components/layout"
import Seo from "../components/seo"
const IndexPage = () => (
<Layout>
<Seo title="Home" />
<h1>Hi people</h1>
<p>Welcome to your new Gatsby site.</p>
<p>Now go build something great.</p>
<StaticImage
src="../images/gatsby-astronaut.png"
width={300}
quality={95}
formats={["auto", "webp", "avif"]}
alt="A Gatsby astronaut"
style={{ marginBottom: `1.45rem` }}
/> // ②StaticImageタグで画像を表示
<p>
<Link to="/page-2/">Go to page 2</Link> <br />
</p>
</Layout>
)
export default IndexPage
StaticImageにはいろんなオプションを指定できます。
OPTION | 説明 |
---|---|
src | 画像への相対パスをいれる。外部の画像であればURLでもOK。 |
placeholder | 画像ロード中の表示方法を指定 dominantColor: デフォルト。元画像の主色を計算して表示 blurred: ぼやけた状態(低解像度)で表示 |
layout | 画像のサイズ方法を指定 constrained: デフォルト。画像の元サイズまたはwidth/heightのサイズで表示。比率を保持してコンテナ幅にフィットするようにリサイズされる。 fixed: 固定サイズでの表示。リサイズされない。 FullWidth: 常にコンテナ幅最大で表示。ヒーローイメージなどに最適。 |
width / height | 高さ、幅を指定 |
- Gatsby公式:Gatsby Image plugin
4 GatsbyJSでSassとCSS Moduleを使う
GatsbyJSni
CSSを扱う方法はいろいろとありますが、今回はSassとCSS Moduleを導入します。
- 参考記事:【Gatsby】Sass + CSS Modulesな環境を作る
- そのほかのCSS導入について→Gatsby公式:Built-in CSS Support
Sassの導入
Sass用のプラグインをインストールします。
npm install --save node-sass gatsby-plugin-sass
gatsby-config.jsにプラグインを追記します。
module.exports = {
siteMetadata: {
// ...
},
plugins: [
// ↓ここを追加
`gatsby-plugin-sass`,
// ...
]
}
プロジェクトの構成はこのとおり。stylesフォルダを作って、そこにscssファイルを入れていきます。
src/
└ styles/
├ _global.scss
├ _setting.scss
└ _button.module.scss
「_XXXX.module.scss」ファイルに、Sass形式でスタイルを記述していきます。
@charset "UTF-8";
@import 'setting';
.btn{
margin-top: 2rem;
margin-right: 1rem;
border:1px solid $main_color;
padding: 8px 30px;
display: inline-block;
color: $main_color;
text-align: center;
text-decoration: none;
font-size: 0.9rem;
position: relative;
&:hover{
background: $main_color;
color: $white_color;
}
transition: all .2s linear;
}
jsファイル内でSCSSファイルをインポートして使います。
import React from "react"
import Layout from "../components/layout"
import * as styles from '../styles/_button.module.scss' // 追加
const Index = ({ data }) => {
return (
<Layout>
<div style={{textAlign:`center`, margin:`2rem auto`}}>
<Link to ="/service/" className={styles.btn}>ボタン</Link>
</div>
{/* その他省略 */}
</Layout>
)
}
export default Index
<div className={`aaa ${styles.bbb} ${styles.ccc}`}></div>
5 GatsbyJSでGoogle Fontを使う
fontsourceを使うと、GatsbyJSでもGoogle Fontが使えます。
フォントパッケージから、使いたいGoogle fontを選びます。
例えば、Open-Sansというgoogle fontを使う場合には下記のようになります。
npm install @fontsource/open-sans
続いて、gatsby-browser.jsにインポートします。
import "@fontsource/open-sans"
CSSにフォントファミリーを追記します。
body{ font-family: 'Open Sans', sans-serif; }
6 GatbyJSでFontAweseomeなどのアイコンを利用する
こちらの記事を参考にさせていただきました。
react-iconsのプラグインをインストール。
npm install react-icons –saveアイコンを使いたい時はreact-icons/xxからアイコンコンポーネントに名前をつけてインポートして、アイコンの表示箇所にタグを記載します。
パッケージ名やアイコンの名前は、React Icons の公式サイトから探します。
import * as React from 'react'
import {FaPinterest, FaGithub, FaTwitter, FaInstagram } from "react-icons/fa"
const Sns = () => {
return (
<div>
<a
style={{marginRight:10}}
href={`https://twitter.com/@emmie0works`}
target="_blank"
rel="noopener noreferrer"
>
<FaTwitter />
</a>
</div>
)
}
export default Sns
7 ブログ記事を表示する
- 参考記事→公式:Adding Markdown Pages
記事を用意する
プロジェクトディレクトリの直下にブログ記事を格納するフォルダを用意します。
その中に、1記事1フォルダで記事を入れていきます。
プロジェクトディレクトリ/
├ blog/
├ post01/
├ ├ icatch.png // アイキャッチ
│ ├ image.jpg // 記事内で使う画像
│ └ index.md // 記事
├ post02/
│ ├ icatch.png // アイキャッチ
│ └ index.md // 記事
├ ...
├ src/
記事はこんな感じで記載します。
---
title: 記事タイトル
date: 2021-09-24
category: diary
featured: icatch.png
slug: hello-world
---
ここに本文を入れる。
↓このように、マークダウン形式で画像も表示できます。
[記事内で使う画像](image.jpg)
—から—の間に、メタ情報を入れていきます。
title | 記事のタイトル |
category | 記事のカテゴリー |
featured | アイキャッチの画像ファイル名 |
slug | 記事のスラッグ |
他にも、tags(タグ)やmodifiedDate(更新日付)など、ブログ記事に入れたい情報をつけておくといいでしょう。
transformer-remarkをインストール
gatsby-transformer-remarkを導入することで記事のメタ情報(title, category, slugなど)を取得することができます。
gatsby-remark-imagesは記事から画像ファイルを相対パスで指定できるようにするためのプラグインで、本文内で画像を表示させるために使います。
npm install --save gatsby-transformer-remark gatsby-remark-images
{
resolve: `gatsby-transformer-remark`,
options: {
plugins: [
// 中略
{ // ↓ブログの記事パスを追記
resolve: `gatsby-source-filesystem`,
options: {
name: `blog`,
path: `${__dirname}/content/blog`,
},
},
{ // ↓プラグインを追記
resolve: `gatsby-remark-images`,
options: {
maxWidth: 800,
linkImagesToOriginal:false,
},
},
],
},
},
ここから、GraphQLを使っていきます。
gatsby developで開発サーバーを起動したら、下記URLにアクセスします。
http://localhost:8000/___graphql
下記のクエリを中央の欄に入力して、上部の「▶︎」ボタンを押して、実行してみましょう。
右側に取得された記事一覧が表示されます。
{
allMarkdownRemark(sort: {fields: [frontmatter___date], order: DESC}) {
edges {
node {
frontmatter {
category
date
slug
featured {
childImageSharp {
gatsbyImageData
}
}
}
}
}
}
}
記事一覧の作成
src/
├ components
├ ...
├ pages
│ └ blog
│ ├ {MarkdownRemark.frontmatter__slug}.js // 各記事のテンプレート
│ └ index.js // 記事一覧ページ
├ 404.js
├ index.js
├ ...
上記のファイル名にすることで、
記事一覧(index.js)のURLは/blog/、
各記事({MarkdownRemark.frontmatter__slug}.js)のURLは、/blog/スラッグ名/になります。
import * as React from 'react'
import { graphql } from "gatsby"
import Layout from '../../components/layout'
import Seo from "../../components/seo"
import PostCard from "../../components/postcard"
const Blog = ({data}) => {
const posts = data.allMarkdownRemark.edges
return (
<Layout>
<Seo title="Blog" />
<section>
<h2>Blog</h2>
<div>
{posts.map(({ node }) => {
return <PostCard key={node.frontmatter.slug} node={node} />;
})}
</div>
</section>
</Layout>
)
}
export default Blog
export const pageQuery = graphql`
{
allMarkdownRemark(sort: {fields: [frontmatter___date], order: DESC}) {
edges {
node {
frontmatter {
category
date
featured {
childImageSharp {
gatsbyImageData
}
}
slug
}
}
}
}
}
`
export const pageQuery以降は先ほど、GraphQLで実行した記事一覧のクエリです。
このクエリの結果を、const posts = data.allMarkdownRemark.edgesに格納しています。
postsの配列から、各記事のデータを抜き出して、記事一覧を表示させています。
【Postcard:記事パーツ共通化】
import React from "react"
import { Link} from "gatsby"
import { GatsbyImage } from "gatsby-plugin-image"
const PostCard = ({ node }) => {
return (
<Link to={`/blog/${node.frontmatter.slug}`}>
<GatsbyImage
image={node.frontmatter.featured.childImageSharp.gatsbyImageData}
alt={node.frontmatter.title} />
<div>{node.frontmatter.title}</div>
</Link>
);
}
export default PostCard
記事のテンプレート
import React from "react"
import { graphql } from "gatsby"
import { GatsbyImage } from "gatsby-plugin-image"
import Layout from '../../components/layout'
const PostTemplate = ({data}) => {
const { markdownRemark } = data
const { frontmatter, html } = markdownRemark
return (
<Layout>
<article style={{margin: `4rem auto`}}>
<div>
<div style={{margin: `0 auto`, textAlign:`center`}}>
{frontmatter.featured && (
<GatsbyImage
image={frontmatter.featured.childImageSharp.gatsbyImageData}
alt={frontmatter.title} />
)}
</div>
<dl style={{marginTop: `4rem`}}>
<dt>タイトル</dt>
<dd>{frontmatter.title}</dd>
</dl>
<dl>
<dt>日付</dt>
<dd>{frontmatter.date}</dd>
</dl>
<div
dangerouslySetInnerHTML={{ __html: html }}
/>
</div>
</article>
</Layout>
)
}
export default PostTemplate
export const pageQuery = graphql`
query($id: String!) {
markdownRemark(id: { eq: $id }) {
html
frontmatter {
title
date(formatString: "YYYY/MM")
category
featured {
childImageSharp {
gatsbyImageData(width: 800, placeholder: BLURRED, layout: CONSTRAINED)
}
}
}
}
}
`
GraphQLに画像の表示条件などを記載して、画像情報を取得します。
featured {
childImageSharp {
gatsbyImageData(width: 800, placeholder: BLURRED, layout: CONSTRAINED)
}
}
表示するときは<GatsbyImage>タグを使います。(import { GatsbyImage } from “gatsby-plugin-image”を忘れずに。)
<GatsbyImage
image={frontmatter.featured.childImageSharp.gatsbyImageData}
alt={frontmatter.title} />
もっとカスタマイズしたい人向けの参考図書:Webサイト高速化のための静的サイトジェネレーター
以上が、ブログの基本構成になります。
実際に作り始めると、もっとカスタマイズしたい部分が出てくるかもしれません。
- Contentful(CMS)を使って記事を管理したい
- カテゴリーページを作成したい
- Google Analyticsを入れたい
- RSSを導入したい
GatsbyJSの本格カスタマイズには、「Webサイト高速化のための静的サイトジェネレーター」が参考になります。
体系立ててGatsbyでサイトを作る方法が解説されています。
- GraphQLの使い方、クエリの書き方
- 画像を背景に表示させるやり方
- メタデータ、OGPの追加方法
- ページネーションの追加
とっても役に立ちました。
ただし、本の記載内容はGatsbyの前のverでの実装になります。
最新版のGatsby v3では画像の表示方法と記事ページの生成方法が変わったので、この記事のコードを参考にしていただいた方がシンプルな記述になると思います。
8 GatsbyブログをNetlifyで公開する
最後に、作成したブログをWeb上に無料で公開する方法です。
以上、GatsbyJSで基本的なブログの作り方でした。