gatsby new xxx https://github.com/gatsbyjs/gatsby-starter-blog
xxx
という名前のプロジェクトを作成。
(xxx
というディレクトリが作成される)
スターター
として、https://github.com/gatsbyjs/gatsby-starter-blog
のようなURLを指定する。
Gatsby.js公式・Gatsby Startersから、好みのスターターを検索できる。
1番人気のgatsby-starter-blog
はスター数が3000
程度。
2番人気のgatsby-starter-netlify-cms
はスター数が1800
程度。
初心者はgatsby-starter-blog
を使ったほうがいい。
チュートリアルはgatsby-starter-blog
がベースとなっているので学習しやすい。
カスタマイズのための情報も多い。
npm run develop
Gatsby.jsでWebサイトを作成後、
npm run develop
のコマンドでWebサービスが起動する。
ブラウザに
http://localhost:8000
というURLを入力すると、Gatsby.jsで作成したサイトが表示される。
npm run build npm run serve
npm run build
でプロジェクトをビルド後、
npm run serve
のコマンドでWebサービスが起動する。
ブラウザに
http://localhost:9000
というURLを入力すると、Gatsby.jsで作成したサイトが表示される。
デフォルトの設定では、
http://localhost:8000
のようなURLでアクセスできるが
http://192.168.1.1:8000
のようなURLではアクセスできない。
(IPアドレス指定でページを表示できない)
そのため、コマンドを実行した端末上からしかアクセスできない。
スマホで表示が確認できないため、レスポンシブが機能しているか確認しづらい。
サービスの起動オプションにhostを設定することで、IPアドレスでのアクセスを可能にする。
npm run develop
やnpm run serve
の実態は、
package.json
に定義されている。
{ "scripts": { "develop": "gatsby develop", "serve": "gatsby serve", } }
上記の部分を、下記のように変更。
{ "scripts": { "develop": "gatsby develop -H=0.0.0.0", "serve": "gatsby serve -H=0.0.0.0", } }
-H=0.0.0.0
オプションを指定することで、
http://192.168.1.1:8000
のようなURLでサイトを表示できるようになる。
IPアドレスは、npm run develop
やnpm run serve
コマンドを実行したホストのもの。
-H=0.0.0.0
の部分は、
-H 0.0.0.0
(イコールなし)や
–host=0.0.0.0
でもOK。
{ "scripts": { "develop": "gatsby develop -H=0.0.0.0 -p=8001", "serve": "gatsby serve -H=0.0.0.0 -p=9002", } }
-p
オプションを指定することで、
デフォルトの8000
や9000
以外のポートでサービスを起動する。
Gatsby.jsで複数のサイトを起動したとき、デフォルトのポートのままでは競合するので、ポートの変更が必須となる。
不要なプラグインなどは削除した方が全体のファイルサイズが小さくなり、ビルド時間の短縮になる。
prismjs
は、ソースコードをシンタックスハイライトするためのプラグイン。
Gatsby.jsのサイトでソースコードを表示させないなら不要。
npm uninstall prismjs npm uninstall gatsby-remark-prismjs
prismjs
本体と、
prismjs
をmarkdownで扱うためのプラグイン(gatsby-remark-prismjs
)をアンインストール。
gatsby-browser.js
ファイルから下記の部分を削除。
import "prismjs/themes/prism.css"
gatsby-plugin-google-analytics
は、Gatsby.jsでGoogle Analyticsを設定するためのプラグイン。
Google Tag Managerを通してGoogle Analyticsを利用するので
直接Google Analyticsを扱うgatsby-plugin-google-analytics
は不要。
npm uninstall gatsby-plugin-google-analytics
gatsby-config.js
のplugins
の項目から以下を削除。
// { // resolve: `gatsby-plugin-google-analytics`, // options: { // trackingId: `ADD YOUR TRACKING ID HERE`, // }, // },
元々コメントアウトされているので、消さなくても影響はない。
しかし、gatsby-plugin-google-analytics
を使わない場合は、完全に不要な設定なので削除した方が分かりやすい。
npm uninstall typeface-merriweather npm uninstall typeface-montserrat
gatsby-browser.js
から下記の部分を削除。
// custom typefaces import "typeface-montserrat" import "typeface-merriweather"
gatsby-browser.js
から下記の部分を削除。
// normalize CSS across browsers import "./src/normalize.css" // custom CSS styles import "./src/style.css"
下記のファイルを削除
グローバルcssを削除した代わりに、
Material UIのThemeProvider
でcssを管理する。
npm install @material-ui/core npm install gatsby-plugin-material-ui
material-ui
の本体と、
material-ui
をgatsbyで利用するためのプラグインをインストール。
gatsby-config.js
のplugins
に下記を追加。
"gatsby-plugin-material-ui",
src/components
ディレクトリにMuiThemeProvider.jsx
というファイルを新規作成。
import React from "react" import { CssBaseline } from "@material-ui/core" import { ThemeProvider, createMuiTheme, responsiveFontSizes, } from "@material-ui/core/styles" const MuiThemeProvider = ({ children }) => { let theme = createMuiTheme({ // 背景色を適用すると、cssが適用される前に一瞬白背景が映るので画面がちらつく // palette: { // background: { // default: "#dddddd", // }, // }, // フォントを適用すると、最初にブラウザのデフォルトフォントで表示され、 // 一瞬後にここで指定したフォントに切り替わるので画面がちらつく // typography: { // fontFamily: ["Noto Serif", "Noto Sans JP"].join(","), // }, }) theme = responsiveFontSizes(theme) return ( <ThemeProvider theme={theme}> <CssBaseline /> {children} </ThemeProvider> ) } export default MuiThemeProvider
createMuiTheme
を使って背景色やフォントなどを指定できる。
responsiveFontSizes
フォントサイズをレスポンシブ対応できる。
CssBaseline
により、最低限のcssを適用した状態になる。
残りは各コンポーネント単位で、makeStyles
を使ってcssを適用していく。
gatsby-browser.js
に下記を追加。
import React from "react" import MuiThemeProvider from "./src/components/MuiThemeProvider" export const wrapRootElement = ({ element }) => { return <MuiThemeProvider>{element}</MuiThemeProvider> }
wrapRootElement
の中でMuiThemeProvider
を適用することで、全体ページにスタイルが適用される。
dotenvを使うと、開発環境と本番環境などステージ別で環境変数を定義することができる。
npm install dotenv
プロジェクトのルートディレクトリに下記の2つのファイルを作成する。
.env.development
には、開発環境用の環境変数を、
.env.production
には、本番環境用の環境変数を書く。
.env*
.env.development
と.env.production
をgitの管理対象外とする。
一般的に、.env
系のファイルではデータベースのパスワードなどの機密事項を管理する。
そのため、Githubなどにアップロードしてはならない。
gatsby-confi.js
の先頭付近に下記を記載。
const fs = require("fs") const envPath = `.env.${process.env.NODE_ENV}` if (fs.existsSync(envPath)) { require("dotenv").config({ path: envPath, }) }
npm run develop
コマンド実行時には、process.env.NODE_ENV
にdevelopment
という文字列が入る。
よって、require(“dotenv”)
では.env.development
が読み込まれる。
npm run build
コマンド実行時には、process.env.NODE_ENV
にproduction
という文字列が入る。
よって、require(“dotenv”)
では.env.production
が読み込まれる。
Gatsby Cloudなどのホスティングサービスにデプロイするときは、
git対象管理外の.env.production
のデータは読み込まれない。
そのため、ホスティングサービスに備え付けの管理画面から環境変数を別途設定する。
npm install gatsby-plugin-sitemap
sitemap生成用のプラグインをインストール。
gatsby-config.js
のplugins
に下記を追加。
{ resolve: "gatsby-plugin-sitemap", options: { output: "/", }, },
npm run build
ビルドのタイミングで、public
ディレクトリ直下に
というファイルが作成される。
gatsby-config.js
への設定で、
output: “/”,
を指定しなかった場合はバグが発生する。
(2021年7月現在)
output: “/”,
を指定しないと
public/
ディレクトリではなく
public/sitemap/
ディレクトリに
sitemap-0.xml
とsitemap-index.xml
が作成される。
しかし、/sitemap/sitemap-index.xml
からの内部リンクで
/sitemap/sitemap-0.xml
になるべきところが
/sitemap-0.xml
になってしまう。
/sitemap-0.xml
は404エラーになるので、サイトマップとして機能しない。
Google Search Consoleの使い方を参考に、
サイトマップとしてsitemap-index.xml
を登録する。
sitemap-index.xml
を登録すれば、sitemap-0.xml
は連動してGoogleに認識される。
canonial
とは、Googleなどの検索エンジンに正規のURLをお知らせする機能。
http://example.com
と
http://www.example.com
の両方のURLでサイトにアクセスできるようなとき、
どちらが正規のURLかを宣言する。
npm install gatsby-plugin-canonical-urls
canonical設定用のプラグインをインストール。
gatsby-config.js
のplugins
に以下を追加。
{ resolve: `gatsby-plugin-canonical-urls`, options: { siteUrl: process.env.SITE_URL, stripQueryString: true, }, },
SITE_URL
は環境変数。
開発環境と本番環境でURLが変わるので、環境変数で管理する。
gatsby-plugin-canonical-urls
の効果により、
htmlのhead
タグに
<link rel="canonical" href="http://example.com">
のようなタグが追加される。
npm install react-helmet npm install gatsby-plugin-react-helmet
react-helmet
本体と、
react-helmet
をGatsby.jsで扱うためのプラグイン(gatsby-plugin-react-helmet
)をインストール。
gatsby-config.js
のplugins
に以下を追加。
"gatsby-plugin-react-helmet",
Seo.jsx
というコンポーネントを作成。
import React from "react" import { Helmet } from "react-helmet" const Seo = ({location}) => { // helmetに渡すメタデータ let metaDatas = [ // OGPの設定、全ページ共通 { property: "og:site_name", content: "xxxxx", }, { property: "og:locale", content: "ja", }, { name: "twitter:site", content: "xxxxx", }, { name: "twitter:creator", content: "xxxxx", }, { name: "twitter:card", content: "summary_large_image", }, // OGPの設定、ページごとに異なる部分 { property: "og:type", content: "article", }, { property: "og:url", content: "xxxxx", }, { property: "og:title", content: "xxxxx", }, { property: "og:description", content: "xxxxx", }, { property: "og:image", content: "xxxxx", }, // OGP以外のメタデータ { name: "description", content: "xxxxx", }, ] return ( <Helmet htmlAttributes={{ lang: "ja", prefix: "og: http://ogp.me/ns#", }} title="xxxxx" meta={metaDatas} > </Helmet> ) } export default Seo
xxxxx
の部分は各自の環境に合わせて文字列を設定する。
<Helmet htmlAttributes={{ lang: "ja", prefix: "og: http://ogp.me/ns#", }} > </Helmet>
の部分の効果により、htmlのソースに
<html lang="ja" prefix="og: http://ogp.me/ns#" data-react-helmet="lang,prefix">
のようなタグが出力される。
<Helmet title="xxxxx" > </Helmet>
の部分の効果により、htmlソースのhead
タグ内に
<title>xxxxx</title>
のようなタグが出力される。
<Helmet meta={metaDatas} > </Helmet>
の部分の効果により、htmlソースのhead
タグ内に
<meta data-react-helmet=“true” property=“og:site_name” content=“xxxxx”>
<meta data-react-helmet=“true” property=“og:locale” content=“ja”>
<meta data-react-helmet=“true” name=“twitter:site” content=“xxxxx”>
<meta data-react-helmet=“true” name=“twitter:creator” content=“xxxxx”>
<meta data-react-helmet=“true” name=“twitter:card” content=“summary_large_image”>
<meta data-react-helmet=“true” property=“og:type” content=“article”>
<meta data-react-helmet=“true” property=“og:url” content=“xxxxx”>
<meta data-react-helmet=“true” property=“og:title” content=“xxxxx”>
<meta data-react-helmet=“true” property=“og:description” content=“xxxxx”>
<meta data-react-helmet=“true” property=“og:image” content=“xxxxx”>
<meta data-react-helmet=“true” name=“description” content=“xxxxx”>
のようなタグが出力される。
Gatsby.jsで作成したプロジェクトをGatsby Cloudへデプロイすると、
http://xxx.gatsbyjs.io
のようなURLが割り当てられる。
Gatsby Cloudでは独自ドメインの設定が可能。
example.com
というドメインを割り当てたと仮定する。
このとき、
http://xxx.gatsbyjs.io
と
http://example.com
の両方でページが表示できてしまう。
Gatsby Cloudには301リダイレクトの機能がないので
http://xxx.gatsbyjs.io
から
http://example.com
へmeta refresh
で転送する。
つまり、
<meta http-equiv="refresh" content="0;URL=https://example.com">
のようなタグを生成する。
import React, { useState, useEffect } from "react" import { Helmet } from "react-helmet" const Seo = ({location}) => { const [refreshContent, setRefreshContent] = useState() useEffect(() => { if (location.host.endsWith("gatsbyjs.io")) { const urlRedirect = `http://example.com${location.pathname}${location.search}` setRefreshContent(`0;URL="${urlRedirect}"`) } else { setRefreshContent(undefined) } }, [location]) let metaDatas = [ { property: "og:site_name", content: "xxxxx", }, { property: "og:locale", content: "ja", }, 中略 ] if (refreshContent !== undefined) { metaDatas = metaDatas.concat([ { "http-equiv": "refresh", content: refreshContent, }, ]) } return ( <Helmet htmlAttributes={{ lang: "ja", prefix: "og: http://ogp.me/ns#", }} title="xxxxx" meta={metaDatas} > </Helmet> ) } export default Seo
if (location.host.endsWith("gatsbyjs.io")) { const urlRedirect = `http://example.com${location.pathname}${location.search}` setRefreshContent(`0;URL="${urlRedirect}"`) }
元のURLが
http://xxx.gatsbyjs.io/aaa/bbb?ccc=ddd
だったら、
${location.pathname}
は、/aaa/bbb
、
${location.search}
は、?ccc=ddd
のような値が格納されている。
location.host
(ドメイン名)の末尾がgatsbyjs.io
のときだけ、
0;URL="http://example.com/aaa/bbb?ccc=ddd"
のような文字列を生成、stateに値を保存(setRefreshContent)している。
location.host
の値は、useEffect
の中でのみ有効。
useEffect
の外ではundefined
になるので注意。
if (refreshContent !== undefined) { metaDatas = metaDatas.concat([ { "http-equiv": "refresh", content: refreshContent, }, ]) }
<meta http-equiv="refresh" content="0;URL=https://example.com">
のようなタグを出力するために、Helmet
に渡す値を設定している。
元々のURLがexample.com
ドメインの場合は、
refreshContent
の値がundefined
なので、
<meta http-equiv=“refresh”>
のタグは生成されない。
Google Analyticsで、測定ID
を発行する。
測定ID
は、Google Tag Manager
でコンテナID
を発行するときに必要。
Google Tag Managerで、<head>
タグ用コードを発行する。
<head>
タグ用コードのGTM-XXXXXXX
の部分(コンテナID
)だけを使う。
<!-- Google Tag Manager --> <script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start': new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0], j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src= 'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f); })(window,document,'script','dataLayer','GTM-XXXXXXX');</script> <!-- End Google Tag Manager -->
のようなコード自体は、プラグインが自動的に挿入してくれるので、自分で設定は不要。
gatsby
やreact
ではページ遷移が普通のサイトとは違う。
URLを疑似的に変更して、変更のあるDOMだけを再描画している。
この疑似的なページ移動を計測するために専用のトリガー設定が必要。
コンテナ
を選択。
トリガー
を選択。
新規
をクリック。
トリガーの設定
をクリック。
トリガーのタイプを選択
: カスタム イベント
イベント名
: gatsby-route-change
保存
をクリック。
トリガー名
: gatsby-route-change
保存
をクリック。
タグ
を選択。
Google アナリティクス GA4 設定
をクリック。
トリガー
をクリック。
+
アイコンをクリック。
トリガーの選択
: gatsby-route-change
配信トリガー
に、All Pages
とgatsby-route-change
が表示されていることを確認。
保存
をクリック。
公開
をクリック。
npm install gatsby-plugin-google-tagmanager
gatsby-plugin-google-tagmanager
をインストール。
.env
ファイルに、
GTM_CONTAINER_ID=GTM-XXXXXXX
を追加。
Gatsby Cloudへアクセス。
サイトを選択。
Site Settings
タブで、Edit Variables
を選択。
Key
: GTM_CONTAINER_ID
Value
: GTM-XXXXXXX
Save
をクリック。
gatsby-config.js
のplugins
に以下を追加。
{ resolve: `gatsby-plugin-google-tagmanager`, options: { id: process.env.GTM_CONTAINER_ID, includeInDevelopment: false, defaultDataLayer: { platform: "gatsby" }, routeChangeEventName: "gatsby-route-change", }, },
process.env.GTM_CONTAINER_ID
の部分は、環境変数から読み込ませる値。
routeChangeEventName
のgatsby-route-change
は、
Google Tag Managerでコンテナ作成時に、イベントトリガーのイベント名
に設定した値。
Google AdSense解説を参考に、
プロジェクトの.cache
ディレクトリにあるdefault-html.js
ファイルをコピーして、
src
ディレクトリにhtml.js
というファイルを作成する。
<head>
タグの末尾に自動広告用のコード
を追加する。
import React from "react" import PropTypes from "prop-types" export default function HTML(props) { return ( <html {...props.htmlAttributes}> <head> <meta charSet="utf-8" /> <meta httpEquiv="x-ua-compatible" content="ie=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" /> {props.headComponents} {process.env.GATSBY_FLAG_ADSENSE === "on" && ( <script data-ad-client="ca-pub-1234567890123456" async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js" ></script> )} </head> <body {...props.bodyAttributes}> {props.preBodyComponents} <div key={`body`} id="___gatsby" dangerouslySetInnerHTML={{ __html: props.body }} /> {props.postBodyComponents} </body> </html> ) } HTML.propTypes = { htmlAttributes: PropTypes.object, headComponents: PropTypes.array, bodyAttributes: PropTypes.object, preBodyComponents: PropTypes.array, body: PropTypes.string, postBodyComponents: PropTypes.array, }
追加した部分だけ抜粋。
{process.env.GATSBY_FLAG_ADSENSE === "on" && ( <script data-ad-client="ca-pub-1234567890123456" async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js" ></script> )}
process.env.GATSBY_FLAG_ADSENSE === “on” &&
により、
環境変数GATSBY_FLAG_ADSENSE
がon
のときだけ、広告が表示されるようにしている。
開発環境ではGATSBY_FLAG_ADSENSE
をoff
にしておき、
本番環境だけGATSBY_FLAG_ADSENSE
をon
にする。
src/components
ディレクトリに、AdsenseMain.jsx
ファイルを新規作成。
import React, { useEffect } from "react" const AdsenseMain = ({ path }) => { useEffect(() => { if (window) { window.adsbygoogle = window.adsbygoogle || [] window.adsbygoogle.push({}) } }, [path]) return ( <ins className="adsbygoogle" style={{ display: "block" }} data-ad-client="ca-pub-1234567890123456" data-ad-slot="1234567890" data-ad-format="auto" data-full-width-responsive="true" ></ins> ) } export default AdsenseMain
return
には、ディスプレイ広告
のコードから<ins></ins>
の部分だけを書いている。
useEffect(() => { if (window) { window.adsbygoogle = window.adsbygoogle || [] window.adsbygoogle.push({}) } }, [path])
上記の部分が、広告コードの
<script>(adsbygoogle = window.adsbygoogle || []).push({});</script>
に相当する。
useEffect
を使い、location.path
が変更した時に(ページが遷移した時に)広告が更新されるようにしている。
コンポーネントの引数path
は、親コンポーネントからlocation.path
を受け取っている。
src/components
ディレクトリに、AdsenseMatched.jsx
ファイルを新規作成。
import React, { useEffect } from "react" const AdsenseMatched = ({ path }) => { useEffect(() => { if (window) { window.adsbygoogle = window.adsbygoogle || [] window.adsbygoogle.push({}) } }, [path]) return ( <ins className="adsbygoogle" style={{ display: "block" }} data-ad-client="ca-pub-1234567890123456" data-ad-slot="9876543210" data-ad-format="autorelaxed" ></ins> ) } export default AdsenseMatched
return
には、関連コンテンツ
のコードから<ins></ins>
の部分だけを書いている。
Layout.jsx
などのコンポーネントから、AdsenseMain
やAdsenseMatched
のjsxを読み込めば、その位置に広告が表示される。
{process.env.GATSBY_FLAG_ADSENSE === "on" && ( <AdsenseMain path={location.pathname} /> )}
{process.env.GATSBY_FLAG_ADSENSE === "on" && ( <AdsenseMatched path={location.pathname} /> )}
process.env.GATSBY_FLAG_ADSENSE === “on” &&
により、
環境変数GATSBY_FLAG_ADSENSE
がon
のときだけ広告を表示する。
a
タグだと、ページ全体が読み込まれる。
gatsby
のLink
タグだと、変更のあるコンポーネントだけが再描画される。
(ページの表示が速くなる)
gatsby
のLink
タグは、内部リンクにしか使えない。
import { Link } from "gatsby" 中略 <Link to="/xxx" > xxx </Link>
warning Using target="_blank" without rel="noreferrer" is a security risk: see https://html.spec.whatwg.org/multipage/links.html#link-type-noopener react/jsx-no-target-blank
a
タグにtarget=“_blank”
を使うと、Eslintのせいで上記のような警告が出る。
<a href="http://example.com" target="_blank" rel="noopener" > example.com </a>
rel=“noopener”
のところを、rel=“noopener noreferrer”
にすれば警告は出なくなる。
import { Link as MuiLink } from "@material-ui/core" 中略 <MuiLink href="http://example.com" target="_blank" rel="noopener" > example.com </MuiLink>
または、material-ui
のLink
を使えばnoreferrer
に関する警告は出なくなる。
Link as MuiLink
のように、Link
に別名をつけているのは、
import { Link } from “gatsby”
のLink
と区別するため。
warning: LF will be replaced by CRLF in xxxxx.md. The file will have its original line endings in your working directory
という警告が大量に表示されるときの対処方法。
Gatsby.jsで.md
を扱うと、環境によっては改行コードの自動変換が発生する。
このとき改行の数だけwarningが表示されてうっとうしい。
git config --global core.autoCRLF false
gitコマンドで、改行変換機能をオフにする。
VSCodeのターミナルで
git add .
VSCodeのSource Controlの画面から
コメントを入れてコミット
VSCodeのターミナルで
npm run build
ビルド完了後に
VSCodeのターミナルで
git push