138
133

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【Gatsby.js】「ここだけ押さえれば普通に使える」って知識をまとめてみた

Last updated at Posted at 2020-07-19

Gatsby.jsでシンプルな静的サイトを作る際に必要な知識だけをまとめました。CMSとの連携等については今回は扱いません。

Gatsby.jsとは

React製の静的サイトジェネレーターです。webサイトを作る時に使います。

Gatsby.jsのメリット

従来通りHTML/CSS(+Gulp, Webpack)でコーディングする方法と比較した場合の最大のメリットは表示速度がめっちゃ速いことです。びっくりするくらい速いです。

その他のメリットとしては

  • JSXを使うので、HTMLの記法等にミスがあったときにすぐに気が付くことができる
  • プラグインが豊富(Markdownファイルを読み込む、PWA対応、etc)
  • ヘッドレスCMSとの相性が良い
  • Gatsby Themeを使って、既存のデザインを流用することができる
    • カスタマイズが前提ならthemeは使わない方が良さそう

などがあります。

セットアップ

前提

  • node.jsがインストールされている
  • yarnがインストールされている
    • なければnpmコマンドで代用可

Gatsby CLIをインストール

$ npm install -g gatsby-cli
$ gatsby -v

プロジェクト開始

$ gatsby new
✔ What is your project called? … my_project #プロジェクト名
✔ What starter would you like to use? › gatsby-starter-hello-world # 一番シンプルなスターターを選択
$ cd my_project
$ gatsby develop

http://localhost:8000/ にアクセスして、初期表示を確認。

ヘッダー、フッター、レイアウトファイルを作成

複数のページで共通して使うパーツはcomponentsディレクトリに配置します。

$ mkdir src/components
$ touch src/components/header.js
$ touch src/components/footer.js
$ touch src/components/layout.js
src/components/header.js
import React from "react"

export default () => (
  <header>
    <h1>サンプルサイトのヘッダー!</h1>
  </header>
)
src/components/footer.js
import React from "react"

export default () => (
  <footer>
    <small>サンプルサイトのフッター!</small>
  </footer>
)
src/components/layout.js
import React from "react"
import Header from "../components/header"
import Footer from "../components/footer"

export default ({ children }) => (
  <> {/* <React.Fragment>の省略形 */}
    <Header />
    {children}
    <Footer />
  </>
)

トップページを作成

pagesディレクトリに、1ページ1ファイルで配置します。

src/pages/index.js
import React from "react"
import Layout from "../components/layout"

export default () => (
  <Layout>
    <div>
      <p>トップページのメインコンテンツ!</p>
    </div>
  </Layout>
)

リンクを追加

サイト内のリンクは従来の<a href="hoge">の代わりに<Link to={"hoge"}>を使うことで、ページ遷移のスピードを格段に上げることができます。

まずは遷移先のページを作成。

$ touch src/pages/second.js
src/pages/second.js
import React from "react"
import { Link } from "gatsby"
import Layout from "../components/layout"

export default () => (
  <Layout>
    <div>
      <p>2つ目のページのメインコンテンツ!</p>
      <Link to={"/"}>トップページへのリンク</Link>
    </div>
  </Layout>
)

トップページにもリンクを追加

src/pages/index.js
import React from "react"
import { Link } from "gatsby" //追加
import Layout from "../components/layout"

export default () => (
  <Layout>
    <div>
      <p>トップページのメインコンテンツ!</p>
      <Link to={"/second/"}>Secondページへのリンク</Link> {/* 追加 */}
    </div>
  </Layout>
)

画像を最適化して表示

「画像の最適化こそがGatsby.jsを使う最大の理由」と言っても過言では無いくらいの目玉機能です。

  • 劣化が目立たない範囲で圧縮
  • webp対応のブラウザではjpgやpngの画像もwebpで表示
  • デバイスのサイズや解像度に応じて適切なサイズで表示
  • 遅延読み込み

といった画像の最適化を、比較的少ない設定で実現することができます。
ここでは簡単さを重視して細かいな説明は省略します。
より深く知りたい方は、gatsby 画像 static queryというキーワードで調べて見てください。

画像を追加

$ mkdir src/images

作成したimagesディレクトリに適当な画像(sample1.jpg)を追加します。

画像最適化のためのプラグインを追加

$ yarn add gatsby-image gatsby-transformer-sharp gatsby-plugin-sharp gatsby-source-filesystem 
gatsby-config.js
module.exports = {
  /* Your site config here */
  plugins: [
    `gatsby-transformer-sharp`,
    `gatsby-plugin-sharp`,
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        name: `images`,
        path: `${__dirname}/src/images/`,
      },
    },
  ],
}

画像を表示するためのコンポーネントを作成

$ touch src/components/image.js
src/components/image.js
import React from "react"
import { useStaticQuery, graphql } from "gatsby"
import Img from "gatsby-image"

export default props => {
  const { allImageSharp } = useStaticQuery(graphql`
    query {
      allImageSharp {
        nodes {
          fluid(maxWidth: 1600) {
            originalName
            ...GatsbyImageSharpFluid_withWebp
          }
        }
      }
    }
  `)
  return (
    <figure className={props.className} style={props.style}>
      <Img
        fluid={
          allImageSharp.nodes.find(n => n.fluid.originalName === props.filename)
            .fluid
        }
        alt={props.alt}
      />
    </figure>
  )
}

トップページで画像を表示

src/pages/index.js
import React from "react"
import { Link } from "gatsby"
import Layout from "../components/layout"
import Image from "../components/image" //追加

export default () => (
  <Layout>
    <div>
      <p>トップページのメインコンテンツ!</p>
      <Link to={"/second/"}>Secondページへのリンク</Link>
      <Image filename="sample.jpg" alt="サンプル画像" /> {/* 追加 */}
    </div>
  </Layout>
)

メタデータを設定

プラグインを追加

$ yarn add gatsby-plugin-react-helmet react-helmet
gatsby-config.js
module.exports = {
  /* Your site config here */
  plugins: [
    `gatsby-transformer-sharp`,
    `gatsby-plugin-sharp`,
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        name: `images`,
        path: `${__dirname}/src/images/`,
      },
    },
    `gatsby-plugin-react-helmet` //追加
  ],
}

メタデータ管理用のコンポーネントを作成

$ touch src/components/meta.js
src/components/meta.js
import React from "react"
import { Helmet } from "react-helmet"

export default () => (
  <Helmet>
    <html lang="ja" />
    <title>サンプルサイト</title>
    <meta name="description" content="説明文" />
  </Helmet>
)

ページに埋め込む

src/pages/index.js
//...
import Meta from "../components/meta" //追加

export default () => (
  <Layout>
    <Meta /> {/* 追加 */}
    {/* ... */}
  </Layout>
)

ページごとに出力する値を変える

ページの中でtitleが設定されていればタイトル | サンプルサイト、設定がなければサンプルサイトを出力するように編集します。

src/components/meta.js
//...

export default props => { // html部分の前に処理が入ると、( から { に変わることに注意
  const baseTitle = "サンプルサイト"
  const title = props.title ? `${props.title} | ${baseTitle}` : baseTitle
  return (
    <Helmet>
      <html lang="ja" />
      <title>{title}</title>
      <meta name="description" content={props.desc} />
    </Helmet>
  )
}
src/pages/index.js
//...
export default () => (
  <Layout>
    <Meta
      title="トップページ"
      desc="Gatsby.jsの使い方を説明するためのサンプルページです。"
    />
    {/* ... */}
  </Layout>
)
src/pages/second.js
import Meta from "../components/meta"
//...
export default () => (
  <Layout>
    <Meta
      title="2つ目のページ"
      desc="2ページ目です"
    />
    {/* ... */}
  </Layout>
)

CSSの選択肢

Gatsby.jsにおけるCSSの選択肢は大きく4つあります。

グローバルCSS

1つのCSS(or SCSS)ファイルに全てのスタイルを記述する方法です。
従来のやり方とほぼ同じなので、学習コストがかからないことが最大のメリットです。
小規模なサイトであれば選択肢の1つでしょう。

CSS Modules

コンポーネントごとにCSSファイルを作り、それを適用したいコンポーネントからインポートしてスタイルを当てていく方法です。scopeができるので、クラス名が重複する心配を減らすことができます。

src/components/header.module.css
.title {
  color: green;
}
src/components/header.js
import Styles from "./header.module.css"
.
.
return (
  <h1 className={Styles.title}>サンプルサイト</h1>
)

CSS in JS

styled-componentsemotionなどのCSS in JSライブラリを使う方法です。まだ使ったことないです。使い方はライブラリごとに違いますが、どれも色々大変そうです。

Tailwind CSS

個人的にイチオシの方法です。
Tailwind CSSはユーティリティークラス(bootstrapでいうところのmb-4text-centerなど)を大量に集めたCSSフレームワークです。
HTMLにクラスを大量につけて、極力CSSを書かないようにしよう、というアプローチをとっています。

このアプローチには

  • クラス名を決める必要がなくなる
  • クラス名の衝突がなくなる
    • BEM、CSS設計からの開放
  • デザインの修正により不要になったCSSが残ってしまうことがなくなる
  • どの要素にどんなスタイルが当たっているかがすぐにわかる
  • カラーコードやフォントサイズ、ブレイクポイント等の統一性を保ちやすい
    • GitLabでは402のテキスト色、239の背景色、59のフォントサイズが使われています。
  • ネット上に転がっているサンプルコードを気軽に取り入れやすい
    • 通常この手のサンプルはカスタマイズがしんどいけど、Tailwindならその心配なし
    • tailwindcomponents.comに公式のサンプルが大量に公開されている

など様々なメリットがあります。
またメディアクエリや繰り返し使うコンポーネントのスタイリングに関してもうまいこと解決してます。

以下、Tailwind CSSの開発者、Adam Wathanのブログの翻訳記事です。
翻訳:CSSユーティリティクラスと「関心の分離」(いかにしてユーティリティファーストにたどり着いたか) - yuhei blog

Tailwind CSSの導入

TailwindCSS、PostCSSをインストール

$ yarn add gatsby-plugin-postcss # postcssをインストール
gatsby-config.js
module.exports = {
  plugins: [
    //省略
    `gatsby-plugin-postcss`, //追加
  ],
}
$ yarn add tailwindcss --dev # tailwind cssをインストール
$ yarn tailwindcss init # tailwind cssの設定ファイルを生成
$ touch postcss.config.js # postcssの設定ファイルを生成
postcss.config.js
const tailwind = require('tailwindcss')
 
module.exports = () => ({
  plugins: [tailwind('./tailwind.config.js')],
})
$ mkdir src/utils
$ touch src/utils/global.css
src/utils/global.css
@tailwind base;
@tailwind components;
@tailwind utilities;

ページに反映させる

src/components/layout.js
import React from "react"
import '../utils/global.css' //追加
//省略
src/pages/index.js
//省略
export default () => (
  <Layout>
    {/* ... */}
    <div>
      <p>トップページのメインコンテンツ!</p>
      <button class="block uppercase mx-auto shadow bg-indigo-800 hover:bg-indigo-700 focus:shadow-outline focus:outline-none text-white text-xs py-3 px-10 rounded">
        Tailwind test
      </button>
      {/* ... */}
  </Layout>
)

Purge CSS

ビルド時に、実際に使われているクラスをチェックし、そのクラスのスタイルだけをCSSファイルに含めるようにして、ファイルサイズを小さくする設定を行います。

tailwind.config.js
module.exports = {
  purge: ["./src/**/*.js"], //編集
  theme: {
    extend: {},
  },
  variants: {},
  plugins: [],
}

この修正を行う前後でgatsby buildコマンドを叩くと、修正前に表示されていた
Tailwind is not purging unused styles because no template paths have been provided.
のエラーが、修正後には消えていることが確認できます。

その他

VSCodeで開発する場合、Tailwind CSS IntelliSenseという拡張機能を使うと快適にコーディングができます。

デプロイ

NetlifyやVercel等にデプロイすると

  • 無料で公開できる
  • 高速
  • Githubへのプッシュと連動して自動でビルド→デプロイされる

のでおすすめです。
Netlifyの設定はこちらの記事で紹介されています。

参考

138
133
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
138
133

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?