GatsbyJSのチュートリアルを読む
目次
- Set Up Your Development Environment
- Get to Know Gatsby Building Blocks
- Introduction to Styling in Gatsby
- Creating Nested Layout Components
- Data in Gatsby
- Source Plugins
- Transformer plugins
- Programmatically create pages from data
- Preparing a Site to Go Live
必要な持ち物を確認
-
Homebrew
のインストール ✅ -
Xcode Command Line Tools
のインストール ✅ -
Node.js
のインストール ✅ -
Git
のインストール ✅ -
Gatsby CLI
(本体)のインストール ✅ -
Visual Studio Code
(エディタ)のインストール ✅ -
Prettier VSCode Plugin
(コードフォーマッタ)のインストール ✅
全部持ってた😊
$ brew --version
Homebrew 3.0.0
$ node --version
v15.8.0
$ git --version
git version 2.30.0
$ gatsby --version
Gatsby CLI version: 2.19.1
$ code --version
1.52.1
Gatsby site を作成する
- チュートリアル用のディレクトリ(
~/sandbox/gatsby-tutorial/
)を作成した
$ mkdir -p ~/sandbox/gatsby-tutorial/
$ cd ~/sandbox/tutorial/
- ページに書いてあるコマンドをコピペして実行した
- スターターのGitHub URLを指定して、ウェブサイト(
hello-world
)を新規作成(new
)している
$ gatsby new hello-world https://github.com/gatsbyjs/gatsby-starter-hello-world
gatsby newを実行した結果
info Creating new site from git: https://github.com/gatsbyjs/gatsby-starter-hello-world.git
Cloning into 'hello-world'...
success Created starter directory layout
info Installing packages...
added 1891 packages, and audited 1892 packages in 26s
6 vulnerabilities (1 low, 5 high)
info Initialising git in hello-world
Your new Gatsby site has been successfully bootstrapped. Start developing it by running:
cd hello-world
gatsby develop
- 出力結果の最後に書いてるとおりにコマンドを実行した
$ cd hello-world
$ gatsby develop
gatsby developを実行した結果
$ gatsby develop
success open and validate gatsby-configs - 0.014s
success load plugins - 0.070s
success onPreInit - 0.025s
success initialize cache - 0.009s
success copy gatsby files - 0.073s
success onPreBootstrap - 0.018s
success createSchemaCustomization - 0.003s
success Checking for changed pages - 0.002s
success source and transform nodes - 0.031s
success building schema - 0.169s
info Total nodes: 18, SitePage nodes: 1 (use --verbose for breakdown)
success createPages - 0.004s
success Checking for changed pages - 0.001s
success createPagesStatefully - 0.035s
success update schema - 0.020s
success write out redirect data - 0.002s
success onPostBootstrap - 0.002s
info bootstrap finished - 3.701s
success onPreExtractQueries - 0.003s
success extract queries from components - 0.082s
success write out requires - 0.007s
success run page queries - 0.027s - 2/2 74.16/s
⠀
You can now view gatsby-starter-hello-world in the browser.
⠀
http://localhost:8000/
⠀
View GraphiQL, an in-browser IDE, to explore your site's data and schema
⠀
http://localhost:8000/___graphql
⠀
Note that the development build is not optimized.
To create a production build, use gatsby build
⠀
success Building development bundle - 4.794s
- ここでも最後に書いてあるとおり
http://localhost:8000/
をブラウザで開いて、表示内容を確認した - シンプルに
Hello World!
と表示された
まとめ
-
gatsby new
で新規にウェブサイトを作成できる -
gatsby develop
でローカルにサーバを立て、内容を確認できる(ホットリロードに対応している)
あっという間にウェブサイトを作成することができた。
ひとつのコマンドを実行したら、次のコマンドを教えてくれるので忘れっぽくても大丈夫。
npm update
1.6 vulnerabilities
と表示されるのが気になった
2. 古くなっているパッケージを npm outdated
で確認した
3.npm update
(省略形 : npm up
)して最新版にしておく(チュートリアルの操作には影響なかった)
$ npm outdated
Package Current Wanted Latest Location Depended by
gatsby 2.26.1 2.32.3 2.32.3 node_modules/gatsby tutorial-part-four
react 16.13.1 16.14.0 17.0.1 node_modules/react tutorial-part-four
react-dom 16.13.1 16.14.0 17.0.1 node_modules/react-dom tutorial-part-four
$ npm up
added 375 packages, removed 240 packages, changed 322 packages, and audited 2027 packages in 37s
149 packages are looking for funding
found 0 vulnerabilities
ウェブサイトとは?
📖 あとで読む
知ってるとよいウェブ技術
- HTML
- CSS
- JavaScript
- React
- GraphQL
これらはあとで必要そうになったら戻って読むことにする
-
src/pages/index.js
を編集してlocalhost:8000/index.html
を更新できた -
JSX
というJavaScriptの中にHTMLを記述する(HTML-in-JS
)方法で書くことがベースになっている - ブラウザは
JSX
を直接理解することができない。その辺りをいい感じにやるのがGatsby
のしごと
Page Component
)
ページコンポーネント(-
src/pages/*.js
のファイルは全部ページコンポーネントになる -
src/pages/about.js
を新規に作成したらlocalhost:8000/about/
が作成されることを確認した -
gatsby develop
を走らせていれば、新規に作成されたファイルも自動で拾ってくれる
sub-components
)
サブコンポーネント(- 複数の場所で使う要素(例:見出し、ボタンなど)はサブコンポーネントとして作成するとよい
- サブコンポーネントは
src/components/*.js
に作成する - 使う場所によって表示する内容を変更したい場合は
props
を使えばよい
ページ間のリンク
-
Link
コンポーネントを使う(import { Link } from "gatsby"
) -
to
プロパティを使ってリンク先のパスを指定する(href="パス"
と同じだと思う)
import { Link } from "gatsby"
<Link to="パス">ページ名</Link>
ウェブサイトをデプロイ
-
gatsby build
を実行するとpublic
ディレクトリが作成される - 必要なものがそこに含まれているので、その中身をアップロードすればOK
-
Surge
というサービスが紹介されているので、あとで試してみよー
スタイルの適用
-
gatsby-browser.js
を使って全体用CSSを読み込む方法 ← これまでCSSの知識をそのまま使えるので、とっつき始めるには便利 -
Component-scoped CSS
(CSS Modules
orCSS-in-JS
)を使う方法 ← これからGatsby
にハマる人には《推奨》みたい - このチュートリアルでは
CSS Modules
の使い方の説明
Globalスタイル
-
/src/styles/global.css
を作成する(ファイル名は好きなようにする) -
/gatsby-browser.js
を作成し、上のglobal.css
をimport
する
import
or require
Note: Both CommonJS (require) and ES Module (import) syntax work here. If you’re not sure which to choose, import is usually a good default. When working with files that are only run in a Node.js environment however (like gatsby-node.js), require will need to be used.
こういう注釈があるのはありがたい。
基本的にimport
を使えばよいことが分かった。
CSS Modules
-
/src/components/container.js
と/src/components/container.module.css
を作成した - (
Gatsby
では)CSS Modules
の拡張子は.module.css
にする -
container.js
はJSX
で書く -
.module.css
は普通のCSS
で書く -
container.js
の中でcontainer.module.css
を読み込むことで使えるようになる -
JSX
が展開されるときにCSS Modules
のファイルパスをベースにCSSのクラス名が自動で生成されるから、クラス名が重複する心配をしなくてよい。(逆に、クラス名を見ればどのファイルを確認すればよいかが分かる)
デバッグ
import React from "react"
import styles from "./about-css-modules.module.css"
import Container from "../components/container"
console.log(styles)
- 新しくモジュールを読み込んだ場合(
import styles from "./about-css-modules.module.css"
) - きちんと読み込めてるか
console.log(styles)
を使って確認すればよい
レイアウトコンポーネント
- 全体的なサイトのデザインには、レイアウトコンポーネントを使う
- ナビゲーションやフッタなどの全ページを通して共通なコンポーネントをひとつにまとめることができる
-
/src/components/layout.js
(ファイル名は何でもいいはず)を作成して、ページコンポーネント(/src/pages/*.js
)のファイルでimport
する
ここまでのまとめ
- ここまで(チュートリアル3)で、いちおう
Gatsby
の基本的な使い方を俯瞰した - ページを作成する場合はページコンポーネント(
/src/pages/*.js
)にJSX
で書けばよい - 共通部分はコンポーネントとしてまとめればよい(
/src/components/*.js
) - スタイルは
CSS Modules
を使えばよい(/src/components/*.module.css
) - サイト全体の設計はレイアウトコンポーネントを使えばよい(
/src/components/layout.js
)
で、次は
- ページを作成する場合に、毎回
JSX
ファイルを作成するのはちょっと手間(JSX
を生で書くのは大変) -
Markdown
で書いたものを読み込むことができるとハッピー😊
データのクエリ(呼び出し方)
-
page query
: ページコンポーネントの中で使えるGraphQL
クエリ -
StaticQuery
: ページコンポーネント以外で使えるGrraphQL
クエリ
他にもnode
のcreatePages
を使うことでunstructured dataを使ってページを生成することができるらしいけど、これはまた調べる。
Gatsby
ではGraphQL
を仲介することで、元データがどんな形式であってもプラグインで対応できるようになる。
ソースの指定
-
gatsby-source-filesystem
プラグインをインストールする -
gatsby-config.js
にプラグインを追加、データ源のパスを指定する - ローカルの
GraphiQL
(http://localhost:8000/___graphql
)にアクセスしてクエリを作成する -
allFiles
とかfiles
を選んで、いろいろ欲しい情報をぽちぽち選択すればOK -
GraphiQL
の使い方は簡単そうなので、使っていたら分かりそう
gatsby-config.js
を編集したあとはリスタート
warn develop process needs to be restarted to apply the changes to gatsby-config.js
-
gatsby-config.js
を編集するとgatsby develop
を実行しているターミナルに上記のwarning
が出力される - 書いてある内容に従って
gatsby develop
をリスタートさせることで、変更した設定が反映される
-
gatsby-config.js
を編集したあとwarning
が出るときと出ないときがある。原因はよく分かってない。 - リスタートが必要な時は、ブラウザにポップアップがでる。そのポップアップから
gatsby-develop
をリスタートすることもできる(わざわざターミナルに打ち込まなくてもいいので便利)
Markdown
ファイルの読み込み
-
gatsby-transformer-remark
プラグインをインストール -
gatsby-config.js
にプラグインを追加 -
src/pages/*.md
を作成する -
GraphiQL
のallMarkdownRemark
/markdownRemark
を使ってクエリを作成する -
src/pages/index.js
にクエリを埋め込むことでトップページにMarkdown
ファイルの一覧を表示することができた
-
gatsby-source-filesystem
といろいろなtransformer
プラグインを使うことで、ありとあらゆるデータをページに変換することができる
他のデータの読み込み方
ページを自動的に生成する方法
- ページ(記事ページとか)の
path
orslug
を作成する(このチュートリアルでは以降slug
を使う) - ページを作成する
Gatsby API
ページを作成するためのonCreateNode
createPages
編集する設定ファイル
gatsby-node.js
onCreateNode
- 新しいノードが作成されたり、更新されたりしたときに
Gatsby
がコールするAPI -
MarkdownRemark
ノードだけにフィルタする
exports.onCreateNode = ({ node }) => {
console.log(`Node created of type "${node.internal.type}"`)
}
出力結果
Node created of type "SitePage"
Node created of type "SitePlugin"
Node created of type "SitePlugin"
Node created of type "SitePlugin"
Node created of type "SitePlugin"
Node created of type "SitePlugin"
Node created of type "SitePlugin"
Node created of type "SitePlugin"
Node created of type "SitePlugin"
Node created of type "SitePlugin"
Node created of type "SitePlugin"
Node created of type "SitePlugin"
Node created of type "SitePlugin"
Node created of type "SitePlugin"
Node created of type "SitePlugin"
Node created of type "SitePlugin"
Node created of type "SitePlugin"
Node created of type "SitePlugin"
Node created of type "SitePlugin"
Node created of type "SitePlugin"
Node created of type "SitePlugin"
Node created of type "SitePlugin"
Node created of type "SitePlugin"
Node created of type "SitePlugin"
Node created of type "Site"
Node created of type "SiteBuildMetadata"
Node created of type "Directory"
Node created of type "Directory"
Node created of type "Directory"
Node created of type "Directory"
Node created of type "File"
Node created of type "File"
Node created of type "File"
Node created of type "File"
Node created of type "File"
Node created of type "MarkdownRemark"
Node created of type "File"
Node created of type "MarkdownRemark"
Node created of type "File"
exports.onCreateNode = ({ node, getNode }) => {
if (node.internal.type === `MarkdownRemark`) {
console.log(`Node created of type "${node.internal.type}"`)
const fileNode = getNode(node.parent)
console.log(`\n`, fileNode.relativePath)
}
}
- このままだと何も起きないので
pandas-and-bananas.md
を適当に編集
出力結果
changed file at /Users/shotakaha/repos/sandbox/gatsby-tutorial/tutorial-part-four/src/pages/sweet-pandas-eating-sweets.md
Node created of type "MarkdownRemark"
pages/sweet-pandas-eating-sweets.md
const { createFilePath } = require(`gatsby-source-filesystem`)
exports.onCreateNode = ({ node, getNode }) => {
if (node.internal.type === `MarkdownRemark`) {
console.log(`node.internal.type: "${node.internal.type}"`)
const fileNode = getNode(node.parent)
console.log(`fileNode.relativePath:`, fileNode.relativePath)
console.log(
`createFilePath:`,
createFilePath({ node, getNode, basePath: `pages` })
)
}
}
出力結果
node.internal.type: "MarkdownRemark"
fileNode.relativePath: pages/pandas-and-bananas.md
createFilePath: /pandas-and-bananas/
node.internal.type: "MarkdownRemark"
fileNode.relativePath: pages/sweet-pandas-eating-sweets.md
createFilePath: /sweet-pandas-eating-sweets/
-
.md
のファイル名 → スラッグ ができてる
スラッグの作り方
-
/src/pages/*.md
のファイル名をスラッグとして使う - 具体的に
/src/pages/pandas-and-bananas.md
→localhost:8000/pandas-and-bananas/
にする - ファイル名を取得するために
getNode()
を使う
・・・とりあえずコピペして動かしてから、いろいろ考えよ
const { createFilePath } = require(`gatsby-source-filesystem`)
exports.onCreateNode = ({ node, getNode, actions }) => {
const { createNodeField } = actions
if (node.internal.type === `MarkdownRemark`) {
console.log(`node.internal.type: "${node.internal.type}"`)
const fileNode = getNode(node.parent)
console.log(`fileNode.relativePath:`, fileNode.relativePath)
const slug = createFilePath({ node, getNode, basePath: `pages` })
console.log(`slug:`, slug)
createNodeField({
node,
name: `slug`,
value: slug,
})
}
}
-
gastsby develop
をリスタート -
http://localhost:8000/___graphql
をブラウザで開き、チュートリアルにあるクエリをコピペして実行
出力結果
{
"data": {
"allMarkdownRemark": {
"edges": [
{
"node": {
"fields": {
"slug": "/sweet-pandas-eating-sweets/"
}
}
},
{
"node": {
"fields": {
"slug": "/pandas-and-bananas/"
}
}
}
]
}
},
"extensions": {}
}
-
slug
が追加されていることが確認できた
- 別の要素をベースにスラッグを生成したい場合にも使えそう
- 別の要素:ノードのIDを使う/日付を使う、など
ここまででできたこと
-
*.md
のファイル名をベースにスラッグを作成できた - スラッグを
GraphQL
でクエリできるようになった
まだできていないこと
- ページの生成
ページテンプレートコンポーネントの作成
-
src/templates/blog-post.js
を作成する - レイアウトコンポーネント(
src/component/layout.js
)をimport
する - 単一の
.md
に対してGraphQL
クエリを発行する - 戻ってくる値を、表示したい箇所に配置する
gatsby-node.js
最終的な- チュートリアルに乗っているものをコピペして、ちゃんと動くことが確認できた
- 内容についてはそのうちちゃんと読んで理解する
チュートリアルのコピペ
const path = require(`path`)
const { createFilePath } = require(`gatsby-source-filesystem`)
exports.onCreateNode = ({ node, getNode, actions }) => {
const { createNodeField } = actions
if (node.internal.type === `MarkdownRemark`) {
const slug = createFilePath({ node, getNode, basePath: `pages` })
createNodeField({
node,
name: `slug`,
value: slug,
})
}
}
exports.createPages = async ({ graphql, actions }) => {
const { createPage } = actions
const result = await graphql(`
query {
allMarkdownRemark {
edges {
node {
fields {
slug
}
}
}
}
}
`)
result.data.allMarkdownRemark.edges.forEach(({ node }) => {
createPage({
path: node.fields.slug,
component: path.resolve(`./src/templates/blog-post.js`),
context: {
// Data passed to context is available
// in page queries as GraphQL variables.
slug: node.fields.slug,
},
})
})
}
サブディレクトリもOK
-
src/pages/2021/pandas-and-bananas.md
を作成(pandas-and-bananas.md
をコピー) -
localhost:8000/2021/pandas-and-bananas/
に表示できることを確認 -
gatsyb-config.js
やgatsby-node.js
の変更はいらなかった
トップページを修正
-
src/pages/index.js
を修正して、各記事へのリンクを追加する -
slug
をGraphQL
でコールできるようにしておくと、こういうところでも使える
ここまでのまとめ
-
Gatsby
で新規サイトを作成した(gatsby new
) - ページやコンポーネントを作成した(
src/pages/*.js
/src/components/js
) - スタイルコンポーネントを作成した(
src/components/*.module.css
) -
source
とtransformer
プラグインを追加した(gatsby-config.js
) -
GraphQL
クエリを使ってページを作成した(src/pages/*.md
) - ファイル名を使って自動でページを作成した(
gatsby-node.js
)
これでチュートリアルは(ほぼ)完了🎉
最後の章はLighthouse
を使ってパフォーマンスを確認しながら、改善するためのプラグインの導入とかなので、あとで読むことにする
プロダクションビルド
$ gatsby build
$ gatsby serve
PWA対策のために追加するとよいプラグイン
gatsby-plugin-manifest
gatsby-plugin-offline
-
gatsby-plugin-react-helmet
,react-helmet
Gatsby Theme
-
gatsby-starter
を使う方法 -
gatsby-themes
を使う方法 -
gatsby-themes
はnpmパッケージとして提供されている - 1つのウェブサイトで複数のテーマ(npmパッケージ)を導入することができる
- テーマによって機能が違うけど、あの機能とこの機能を合わせて使うこともできる
テーマの使い方
-
npm install
する -
gatsby-config.js
でカスタマイズできる
複数のテーマを使う方法
-
Gatsby themes
はもともとcomposable
な設計になっている -
gatsby-config.js
に書かれた最後のテーマがoverrideするようになっている
チュートリアルがある
Shadowing
- テーマの機能(コンポーネント)の一部だけをカスタマイズできる機能
- インストールしたテーマのパッケージ構造を確認する
-
テーマ/src/components/コンポーネント.js
→(自分のサイト)/src/テーマ/components/コンポーネント.js
にコピーして必要箇所を書き換える
- チュートリアルを読んでみて、なんだかできそうな気がしてきた
- とりあえずよさげなテーマを探してみた
- これ使ってみようかな
サンプルサイト
リポジトリ
できた!😊
- テーマのリポジトリを指定して
gatsby new
した -
gatsby new
すると勝手にGitリポジトリにしてくれる -
src/pages/*.js
とsrc/components/*.js
を直接編集 - あれこれ編集し、ひと段落したところで自分の
GitLab
にpush
した - 下記のCI設定を
.gitlab-ci.yml
にコピペして、GitLab Pagesが自動生成&確認できるようにした
まとめ
- チュートリアルをきちんと読むことで
Gatsby
の大枠を理解できた - 次は必要な部分の
How-to Guides
を読んでいくことにする - 画像周りの
How-to
かなぁ
ということで、このスクラップはおしまい🎉