Gatsby.jsでシンプルな静的サイトを作る際に必要な知識だけをまとめました。CMSとの連携等については今回は扱いません。
Gatsby.jsとは
React製の静的サイトジェネレーターです。webサイトを作る時に使います。
Gatsby.jsのメリット
従来通りHTML/CSS(+Gulp, Webpack)でコーディングする方法と比較した場合の最大のメリットは表示速度がめっちゃ速いことです。びっくりするくらい速いです。
その他のメリットとしては
- JSXを使うので、HTMLの記法等にミスがあったときにすぐに気が付くことができる
- GitHubにpushしたら自動でビルド→デプロイされる
- Tailwind CSS(他様々なライブラリ)が使える
- プラグインが豊富(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
importReactfrom"react"exportdefault()=>(<header><h1>サンプルサイトのヘッダー!</h1></header>)
importReactfrom"react"exportdefault()=>(<footer><small>サンプルサイトのフッター!</small></footer>)
importReactfrom"react"importHeaderfrom"../components/header"importFooterfrom"../components/footer"exportdefault({children})=>(<>{/* <React.Fragment>の省略形 */}<Header/>{children}<Footer/></>)
トップページを作成
pages
ディレクトリに、1ページ1ファイルで配置します。
importReactfrom"react"importLayoutfrom"../components/layout"exportdefault()=>(<Layout><div><p>トップページのメインコンテンツ!</p></div></Layout>)
リンクを追加
サイト内のリンクは従来の<a href="hoge">
の代わりに<Link to={"hoge"}>
を使うことで、ページ遷移のスピードを格段に上げることができます。
まずは遷移先のページを作成。
$ touch src/pages/second.js
importReactfrom"react"import{Link}from"gatsby"importLayoutfrom"../components/layout"exportdefault()=>(<Layout><div><p>2つ目のページのメインコンテンツ!</p><Linkto={"/"}>トップページへのリンク</Link></div></Layout>)
トップページにもリンクを追加
importReactfrom"react"import{Link}from"gatsby"//追加importLayoutfrom"../components/layout"exportdefault()=>(<Layout><div><p>トップページのメインコンテンツ!</p><Linkto={"/second/"}>Secondページへのリンク</Link>{/* 追加 */}</div></Layout>)
画像を最適化して表示
「画像の最適化こそがGatsby.jsを使う最大の理由」と言っても過言では無いくらいの目玉機能です。
- 劣化が目立たない範囲で圧縮
- webp対応のブラウザではjpgやpngの画像もwebpで表示
- デバイスのサイズや解像度に応じて適切なサイズで表示
- 遅延読み込み
といった画像の最適化を、比較的少ない設定で実現することができます。
画像を追加
$ 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
importReactfrom"react"import{useStaticQuery,graphql}from"gatsby"importImgfrom"gatsby-image"exportdefaultprops=>{const{allImageSharp}=useStaticQuery(graphql`
query {
allImageSharp {
nodes {
fluid(maxWidth: 1600) {
originalName
...GatsbyImageSharpFluid_withWebp
}
}
}
}
`)return(<figure><Imgfluid={allImageSharp.nodes.find(n=>n.fluid.originalName===props.filename).fluid}alt={props.alt}/></figure>)}
トップページで画像を表示
importReactfrom"react"import{Link}from"gatsby"importLayoutfrom"../components/layout"importImagefrom"../components/image"//追加exportdefault()=>(<Layout><div><p>トップページのメインコンテンツ!</p><Linkto={"/second/"}>Secondページへのリンク</Link><Imagefilename="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
importReactfrom"react"import{Helmet}from"react-helmet"exportdefault()=>(<Helmet><htmllang="ja"/><title>サンプルサイト</title><metaname="description"content="説明文"/></Helmet>)
ページに埋め込む
//...importMetafrom"../components/meta"//追加exportdefault()=>(<Layout><Meta/>{/* 追加 */}{/* ... */}</Layout>)
ページごとに出力する値を変える
ページの中でtitleが設定されていればタイトル | サンプルサイト
、設定がなければサンプルサイト
を出力するように編集します。
//...exportdefaultprops=>{// html部分の前に処理が入ると、( から { に変わることに注意constbaseTitle="サンプルサイト"consttitle=props.title?`${props.title} | ${baseTitle}`:baseTitlereturn(<Helmet><htmllang="ja"/><title>{title}</title><metaname="description"content={props.desc}/></Helmet>)}
//...exportdefault()=>(<Layout><Metatitle="トップページ"desc="Gatsby.jsの使い方を説明するためのサンプルページです。"/>{/* ... */}</Layout>)
importMetafrom"../components/meta"//...exportdefault()=>(<Layout><Metatitle="2つ目のページ"desc="2ページ目です"/>{/* ... */}</Layout>)
CSSの選択肢
Gatsby.jsにおけるCSSの選択肢は大きく4つあります。
グローバルCSS
1つのCSS(or SCSS)ファイルに全てのスタイルを記述する方法です。
従来のやり方とほぼ同じなので、学習コストがかからないことが最大のメリットです。
小規模なサイトであれば選択肢の1つでしょう。
CSS Modules
コンポーネントごとにCSSファイルを作り、それを適用したいコンポーネントからインポートしてスタイルを当てていく方法です。scopeができるので、クラス名が重複する心配を減らすことができます。
.title{color:green;}
importStylesfrom"./header.module.css"..return(<h1className={Styles.container}>サンプルサイト</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をインストール$ npx tailwindcss init # tailwind cssの設定ファイルを生成$ touch postcss.config.js # postcssの設定ファイルを生成
consttailwind=require('tailwindcss')module.exports=()=>({plugins:[tailwind('./tailwind.config.js')],})
$ mkdir src/utils
$ touch src/utils/global.css
@tailwindbase;@tailwindcomponents;@tailwindutilities;
ページに反映させる
importReactfrom"react"import'../utils/global.css'//追加//省略
//省略exportdefault()=>(<Layout>{/* ... */}<div><p>トップページのメインコンテンツ!</p><buttonclass="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やVersel等にデプロイすると
- 無料で公開できる
- 高速
- Githubへのプッシュと連動して自動でビルド→デプロイされる
のでおすすめです。
Netlifyの設定はこちらの記事で紹介されています。