基礎から始めるGatsbyJS入門
本文書では、GatsbyJSを利用してスクラッチからブログサイトの構築方法を確認していきます。Gatsbyの公式のチュートリアルを見てコピー&ペーストするだけで構築することは可能ですが、本ブログでは動的ページ作成や画像の設定など私自身が詰まった箇所を以下の文書を含めできるだけ詳細に記述しています。Gatsbyを理解しながら構築できることを目的にしています。
目次
Gatsbyとは
GatsbyはStatic Site Generator(静的サイトジェネレーター)でReactをベースに開発されているフレームワークです。Gatsbyを理解するためにはJavaScriptだけではなくReact, GraphQLなどの基礎知識が必要となります。
Gatsbyではデータを取得する際にはGraphQLを利用します。GraphQLを使って内部リソースのMarkdownファイル、データベース、CSVファイルまたは外部リソースのContentfulやWordPressなどさまざまなリソースからデータを取得することができます。WordPressのテーマに対応するStarter(スターター)やPlugin(プラグイン)も豊富にあるため効率的にサイト構築を行うことができます。
Gatsbyを使いこなすためにはPluginにどのようなものがあるかも理解する必要があります。ファイルへのアクセスや画像の処理などすべてプラグインを追加することで機能を利用することができます。
Gatsbyを利用する主な理由にはサイトの高速化や画像の最適化、セキュリティ対策といったものがあります。
サイトの高速化は静的サイトジェネレターという機能で実現されています。WordPressのようにブラウザからアクセスがあった場合にデータベースに保存されている記事情報をSQLでデータベースから取得して動的にページ作成するのではなく静的ページを事前に作成(ビルド)しておくことで高速化を図ります。
最近はPCからだけではなくスマホやタブレットPCなどさまざまなデバイスからのアクセスがあります。サイトによってはスマホからのアクセスが大半を占めるサイトもあります。それぞれのデバイスに合わせて自動で画像を調整してくれる画像の最適化機能をGatsbyは持っており画像を調整するための煩雑な設定から開放されます。
Gatsbyでは事前に静的ページを作成するためにデータベースへのアクセスを行う必要がありません。またHeadless CMSのContentfullからデータを取得することもできるためGatsbyが稼働するサーバにデータを持たせないことも可能です。そのためGatsby経由でデータベースに保管されている重要なデータへアクセスされる可能性がなくセキュリティへの不安を下げることができます。
GatsbyJSのインストール
本文書ではMac OSを利用して動作確認を行っています。Gatsbyをインストールするためには事前にnode.jsをインストールしておく必要があります。
GatsbyJSでのアプリケーションを開発するための準備は以下の3つのステップを実行することで開始することができます。
- npmコマンドでグローバルにgatsby-cliのインストール
- gatsbyコマンドを利用して新しいサイトを作成(gatsby new gatsby-site)
- 開発サーバの起動(gatsby develop)
gatsby cliのインストール
npmコマンドを使ってGatsbyJSのCLI(コマンドラインインターフェイス)のインストールを行います。GatsbyJSのCLIをインストールするとgatsbyコマンドを利用することができます。管理者としてインストールするためにsudoをつけて実行します。sudoで実行するとパスワードが必要になるので事前に準備をしておく必要があります。
$ sudo npm install -g gatsby-cli
インストール終了後、gatsby –helpを実行してメッセージが表示されたらインストールは正常に完了しています。
サイトの作成
サイトの作成はインストールを行なったgatsbyコマンドで行います。gatsbyコマンドの書式は下記の通りです。
gatsby new [SITE_DIRECTORY_NAME] [URL_OF_STARTER_GITHUB_REPO]
SITE_DIRECTORY_NAMEには任意の名前のディレクトリ名をつけます。任意の名前のディレクトリ下にGatsbyに関連するファイルがインストールされます。
Gatsbyには作成したいサイトの目的に応じたテンプレートであるstarter(スターター)がいくつもアップされており、starterを利用することで短時間で目的のサイトを作成することができます。starterを指定したい場合は、URL_OF_STARTER_GITHUB_REPOにgithubのURLを指定します。指定しない場合はdefault starter(デフォルトスターター)を元にサイトが作成されます。
starter(スターター)はhttps://www.gatsbyjs.org/starters/?v=2から見つけることができます。
ここではHello-worldのスターターを利用するのでURL_OF_STARTER_GITHUB_REPOにhttps://github.com/gatsbyjs/gatsby-starter-hello-world
$ gatsby new gatsby-site https://github.com/gatsbyjs/gatsby-starter-hello-world
開発サーバの起動
サイトの作成が完了したらインストールディレクトリに移動して、gatsby developコマンドを実行します。起動後のメッセージhttp://localhost:8000/とあるように開発用のサーバはローカルのPCのポート番号8000で起動します。ブラウザでhttp://localhost:8000/にアクセスします。
$ cd gatsby-site/
$ gatsby develop
・
You can now view gatsby-starter-hello-world in the browser.
⠀
http://localhost:8000/
・
画面にHello World!が表示されることを確認してください。Hello World!が表示されたらここまでの設定は問題なく行われています。
Hello World!が記述されているファイルははsrc/pagesの下のindex.jsファイルです。このファイルを更新するとトップページの内容を書き換えることができます。
【参考】Blog Starterでサイト作成
もしブログ用のstarterを利用したい場合はどのように行うのか確認しておきます。gatsby newコマンドのGithubのURLには https://github.com/gatsbyjs/gatsby-starter-blog を指定します。
$ gatsby new gatsby-blog https://github.com/gatsbyjs/gatsby-starter-blog
インストール後gatsby-blogディレクトリに移動してdevelopコマンドを実行します。
$ cd gatsby-blog/
$ gatsby develop
ブラウザで確認するとブログ用のスターターなのでブログのトップページと3つの記事へのリンクが表示されています。
記事を変更したい場合には、インストールディレクトリのcontent¥blogの下のタイトル名のディレクトリの下にMarkdown(マークダウン)で記述されたindex.mdファイルが入っているでそのファイルを更新すると即座に変更が反映されます。
実際にhello-worldディレクトリのindex.mdのtitleをHello WorldからHello Gatsbyに変更すると下記のように反映されます。
---
title: Hello Gatsby
date: "2015-05-01T22:12:03.284Z"
description: "Hello World"
---
This is my first post on my new fake blog! How exciting!
このようにstarterを利用するとReactやGraphQLの知識がなかったとしても記事の更新や追加を行うことができます。
ブログサイトの構築
hello-worldのstarterで作成したサイトを更新しながらブログサイトを構築していきます。ファイルの更新を行う場合は必ず下記のコマンドを実行しておきます。
$ gatsby develop
トップページの変更
src¥pagesディレクトリにあるindex.jsファイルを下記のように更新します。
import React from "react"
const BlogPage = () => {
return (
<div>
<h1>Gatsby Blog Site</h1>
</div>
)
}
export default BlogPage
更新すると手動でリロードすることなくブラウザに変更内容が更新されます。これはホットリロードと呼ばれており効率的に追加した内容をチェックするこができます。更新を行った内容Gatsby Blog Siteが表示されます。
aboutページの追加
index.jsファイルを元にabout.jsファイルをsrc¥pagesディレクトリの下に作成します。
import React from "react"
const AboutPage = () => {
return (
<div>
<h1>About Page</h1>
</div>
)
}
export default AboutPage
ブラウザで/aboutページにアクセスするとAboutページが表示されます。
aboutページを追加したように他にも追加したいページがある場合は同様の方法で行うことができます。
関数の記述方法は下記の形式でも問題はありません。慣れている方法で記述してください。
import React from "react"
export default function AboutPage() {
return (
<div>
<h1>About Page</h1>
</div>
)
}
404ページ
/(ルート)と/aboutページにブラウザからアクセスすることができますが、ユーザがそれ以外のページにアクセスした場合には下記のページが表示されます。
“Preview custom 404 page”のボタンをクリックすると”A custom 404 page wasn’t detected – if you would like to add one, create a component in your site directory at src/pages/404.js
.”を表示されます。
src/pages/404.jsのページを作成するとカスタムページが作成できると記述されているのでsrc/pages/の下に404.jsファイルを作成します。
import React from "react"
const NotFound = () => {
return (
<div>
<p>アクセスしたページは存在しません。</p>
</div>
)
}
export default NotFound
再度存在しないURLにアクセスすると先ほどと同じ画面が表示されますが、”Preview custom 404 page”ボタンをクリックすると404.jsで記述したエラーの内容が表示されます。
開発環境ではGatsby.js Development 404 Pageが表示されますが本番環境では直接作成した404ページの内容が表示されます。確認したい場合はgatsby buildコマンドを実行してビルドを行いgatsby serveを実行してください。Gatsbyが正常に起動した場合は存在しないURLにアクセスすると404ページが表示されます。
ページ間にリンクを貼る
トップページとaboutページを作成しましたが、現時点ではaboutページにアクセスするためにブラウザのURLに/aboutを入力する必要があります。通常のHTMLのようにaタグをつけてリンクを貼ることができますが、Gatsbyではこの方法は使いません。
Gatsbyでリンクを貼るためにはLinkコンポーネントを利用します。Linkコンポーネントをgatsbyからimportします。
import { Link } from "gatsby"
index.jsファイルからaboutページへのリンクを貼るためにLinkタグを下記のように記述します。toにAboutページのurlを指定します。
import React from "react"
import { Link } from "gatsby"
const BlogPage = () => {
return (
<div>
<ul>
<Link to="/about">About</Link>
</ul>
<h1>Gatsby Blog Site</h1>
</div>
)
}
export default BlogPage
ブラウザで確認するとAboutページへのリンクが貼られます。クリックするとAboutページ全体の読み込みが行われずスムーズにAbout Pageが表示されることが確認できます。
通常のaタグを利用した場合はリンクをクリックするとページ全体の再読み込みが行われますがしLinkタグを利用してページを移動した場合はページ内の更新が必要な箇所のみ更新が行われます。確認したい場合はブラウザのデベロッパーツールを起動してElementsタブを開いてリンクをクリックしてください。
ヘッダーとフッターコンポーネントの作成
ブログサイトのようにページ内で表示が異なる部分は投稿の記事部分である場合、ヘッダー、フッターまたサイドバー(ある場合)はすべてのページで共通です。この場合はページ毎に同じコードを記述するのではなくコンポーネントとして部品化してすべてのページで共有して利用します。
ここまでの作業ではindex.jsとabout.jsページの2つしかありませんが、2つのページのリンクを表示するためにHeaderコンポーネントを追加します。srcディレクトリの下にcomponentsディレクトリを作成します。
componentsディレクトリ作成後その下にheader.jsファイルを作成します。
header.jsファイルには各ページへのリンクを追加します。
import 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 React from "react"
import Header from "../components/header.js"
const BlogPage = () => {
return (
<div>
<Header/>
<h1>Gatsby Blog Site</h1>
</div>
)
}
export default BlogPage
Aboutページもindex.jsと同様にHeaderコンポーネントをimportして利用します。
import React from "react"
import Header from "../components/header.js"
const AboutPage = () => {
return (
<div>
<Header/>
<h1>About Page</h1>
</div>
)
}
export default AboutPage
Aboutページの上部にリンクが表示され、リンクをクリックするとページが更新されます。トップページも同様に表示されます。
Footerコンポーネントの作成も行います。header.jsと同様にcomonentsディレクトリの下にfooter.jsファイルを作成します。西暦を自動表示できるように(new Date()).getFullYear()を行なっています。
import React from 'react'
const Footer = () => {
return (
<footer>
<div>© Gatsby Blog Site { (new Date()).getFullYear() }</div>
</footer>
)
}
export default Footer
Headerコンポーネントと同様にFooterコンポーネントもimportします。
import React from "react"
import Header from "../components/header.js"
import Footer from "../components/footer.js"
const BlogPage = () => {
return (
<div>
<Header/>
<h1>Gatsby Blog Site</h1>
<Footer/>
</div>
)
}
export default BlogPage
ブラウザで確認すると上部にHeaderコンポーネントの要素、下部にFooterコンポーネントの要素が表示されることが確認できます。
Layoutコンポーネントの作成
HeaderとFooterコンポーネントを作成しましたが、これらのコンポーネントを含むLayoutコンポーネントを作成します。各ページはLayoutコンポーネントを使ってコンテンツ以外を共通化します。
まだLayoutコンポーネントの作成は完了してませんが、index.jsファイルにLayoutコンポーネントをimportし下記のようにLayoutタグで囲みます。
import React from "react"
import Layout from "../components/layout.js"
const BlogPage = () => {
return (
<div>
<Layout>
<h1>Gatsby Blog Site</h1>
</Layout>
</div>
)
}
export default BlogPage
次にlayout.jsファイルに以下を記述します。これまではHeader、Footerコンポーネントは各ファイルからimportしていましたが、Layoutコンポーネントの中でimportします。index.jsファイルでLayoutタグの間にコンテンツを入れていましたが、コンテンツはpropsを使って受け取ることができます。
import React from 'react'
import Header from './header'
import Footer from './footer'
const Layout = ( props ) => {
return (
<div>
<Header/>
{ props.children }
<Footer/>
</div>
)
}
export default Layout
Layoutコンポーネントを追加しましたが、ブラウザからは先程までと同じ内容が表示されます。
CSSの適用
Gatsyに限らずフレームワークを使ってアプリケーションを構築する際に一番難しい選択の一つがCSSです。CSSはさまざまな種類がありどれもできることは同じですが人によって好みがわかれるためです。
Gatsbyの公式のホームページでも3つのタイプの説明が行われています。
- Global CSS Files
- Modular Stylesheets
- CSS-in-JS
Gatsbyでもどのタイプを利用するかのリコメンドはなくGatsbyは開発者が選ぶスタイリングの方法についての意見はないと言っています。(Gatsby doesn’t have an opinion about which styling approach you choose.)
本文書ではCSSを知っている人ならだれでも困ることのないGlobal CSSファイルを利用します。
src¥componentsディレクトリの下にlayout.cssファイルを作成して、titleクラスを追加します。文字色を赤にする設定です。
.title {
color: red;
}
作成したlayout.cssファイルをlayout.jsファイルからimportします。
import React from "react"
import Header from "./header"
import Footer from "./footer"
import "./layout.css"
//略
titleクラスを適用したいindex.jsファイルを開いてdivタグにclassNameでtitleを設定します。要素にclassを設定したい場合Reactではclass属性ではなくclassName属性を設定する必要があります。
import React from "react"
import Layout from "../components/layout.js"
const BlogPage = () => {
return (
<div>
<Layout>
<h1 className="title">Gatsby Blog Site</h1>
</Layout>
</div<
)
}
export default BlogPage
ブラウザで確認し文字の色が赤になっていればCSSは適用されています。
まとめ
レイアウトが作成できたので次の文書ではGraphQLのqueryを使ってローカルファイルシステムへのアクセスとMarkdownファイルの内容の取得を確認していきます。