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
import React from "react"
export default () => (
<header>
<h1>サンプルサイトのヘッダー!</h1>
</header>
)
import React from "react"
export default () => (
<footer>
<small>サンプルサイトのフッター!</small>
</footer>
)
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ファイルで配置します。
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
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>
)
トップページにもリンクを追加
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
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
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>
)
}
トップページで画像を表示
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
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
import React from "react"
import { Helmet } from "react-helmet"
export default () => (
<Helmet>
<html lang="ja" />
<title>サンプルサイト</title>
<meta name="description" content="説明文" />
</Helmet>
)
ページに埋め込む
//...
import Meta from "../components/meta" //追加
export default () => (
<Layout>
<Meta /> {/* 追加 */}
{/* ... */}
</Layout>
)
ページごとに出力する値を変える
ページの中でtitleが設定されていればタイトル | サンプルサイト
、設定がなければサンプルサイト
を出力するように編集します。
//...
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>
)
}
//...
export default () => (
<Layout>
<Meta
title="トップページ"
desc="Gatsby.jsの使い方を説明するためのサンプルページです。"
/>
{/* ... */}
</Layout>
)
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ができるので、クラス名が重複する心配を減らすことができます。
.title {
color: green;
}
import Styles from "./header.module.css"
.
.
return (
<h1 className={Styles.title}>サンプルサイト</h1>
)
CSS in JS
styled-components、emotionなどのCSS in JSライブラリを使う方法です。まだ使ったことないです。使い方はライブラリごとに違いますが、どれも色々大変そうです。
Tailwind CSS
個人的にイチオシの方法です。
Tailwind CSSはユーティリティークラス(bootstrapでいうところのmb-4
、text-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をインストール
module.exports = {
plugins: [
//省略
`gatsby-plugin-postcss`, //追加
],
}
$ yarn add tailwindcss --dev # tailwind cssをインストール
$ yarn tailwindcss init # tailwind cssの設定ファイルを生成
$ touch postcss.config.js # postcssの設定ファイルを生成
const tailwind = require('tailwindcss')
module.exports = () => ({
plugins: [tailwind('./tailwind.config.js')],
})
$ mkdir src/utils
$ touch src/utils/global.css
@tailwind base;
@tailwind components;
@tailwind utilities;
ページに反映させる
import React from "react"
import '../utils/global.css' //追加
//省略
//省略
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ファイルに含めるようにして、ファイルサイズを小さくする設定を行います。
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の設定はこちらの記事で紹介されています。