Firebase Hosting + GatsbyJSでWebサイトを作る 2
ページのレイアウトを作ります。
前回(??)の記事Firebase Hosting + GatsbyJSでWebサイトを作るを一通りやると、
次のようなフォルダ構成になっていると思います (以下の画像にはFirebaseに関するファイルがありませんが)。
フォルダ構成
/src
というフォルダの中にファイルやフォルダを作っていきます。
まずはページのレイアウトをとっても大雑把に決定するファイルを作ります。
/src/components/layout
というフォルダを作り、ここに
layout.js
,head.js
,header.js
,header.module.css
,footer.js
,footer.module.css
などの何も書いてないファイルを作ります。
・layout.js
はページのレイアウトを大雑把に決めるファイルです。
・head.js
はHTMLファイルのheadタグの部分に書き込む内容を記述するファイルです。
・header.js
はページのヘッダーを記述するファイルです。
・header.module.css
はヘッダーの内容を装飾するCSSファイルです。
・footer.js
はページのフッターを記述するファイルです。
・footer.module.css
はフッターの内容を装飾するCSSファイルです。
すると次のようになるはずです:
/src
|-- pages
| |-- index.js
| |-- 404.js
|-- images
|-- components
|-- layout.js
|-- head.js
|-- header.js
|-- header.module.css
|-- footer.js
|-- footer.module.js
Headの記述
今度はheadの中身を記述します。
その前に、ターミナルで現在のフォルダ(srcの中じゃなくてもokです。firebase.jsonなどが存在しているフォルダの子孫であればどこでも大丈夫)に移動して、
npm install react-helmet
を実行しておきます。
何かがインストールされると思います。
次にhead.jsの中に最低限の記述をします:
import * as React from "react"
import { Helmet } from "react-helmet"
const Head = (props) => (
<Helmet>
<html lang="ja" />
<meta charset="utf-8" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="description" content={props.description} />
<meta name="author" content={props.author} />
<title>{props.title}</title>
</Helmet>
)
Head.defaultProps = {
title: "不等式botのWebSite",
description: "不等式botのWebSite",
author: "不等式bot"
}
export default Head
ターミナルで何かをインストールしたのは、<Helmet></Helmet>
を使いたかったからです。
これはheadタグの中身を記述する際に使うやつです。
たとえばMathJaxを使いたい場合には、この<Helmet></Helmet>
で囲まれた中にその旨を記述します。
別の.jsファイルでimport Head from (head.jsの相対パス)
と記述することで<Head>
という"タグのようなもの"がつかえるようになります。
後で使います。使うときは"<Head title=... author=... description=... />"のようにして使います。
ここで渡された"title"などは"props.title"のようにして参照されます。
また、reactのルールで、javascriptの定数をHTMLの中で使うときには{}で囲まなければいけません。
なので<title>{props.title}</title>
のようになっています。
最後に書いている
Head.defaultProps = { ...
は、<Head>
に値が渡されなかった場合の初期値の設定です。
とりあえず、あとで使います。
Layoutの記述
layout.js
の中身は以下のようにします (とりあえず、一番シンプルに):
import * as React from "react"
function Layout(props) {
return (
<main>
{props.children}
</main>
);
}
export default Layout
このあと、index.jsなどのファイルの中でLayoutをimportすれば、
<Layout></Layout>
で囲まれた中身が{props.children}
の部分に挿入される感じになります。
とりあえず使います。
とりあえず、/src/pages/index.js
に移動して、index.js
の中身を次にします:
import * as React from "react"
import Head from "../components/layout/head.js"
import Layout from "../components/layout/layout.js"
const IndexPage = () => {
const description = "最初のページ";
return (
<Layout>
<Head description={description} />
{description}
</Layout>
)
}
export default IndexPage
何をしているかというと、
最初のimport
たちで<Head>
と<Layout>
タグを使えるようにします。
<Layout></Layout>
の中に<Head>
がありますが、
<Head>
の中身は<Helmet>
で囲まれているので、
どこに<Head>
を記述しても、コンパイル後のHTMLファイルでは<head>
の部分に持っていかれます。
しかし、Reactの文法ルールがあり、returnの内容にHTMLを含める場合には
「必ず一つのタグに囲まれたものでなければならない」
というものがあるので、このルールに従って全体を<Layout>
で囲んでいます。
定義した定数は{}
で囲んで参照されます。
description
に「"最初のページ"」が渡されていて、
<Layout>
で{description}
が囲まれた状態なので、
layout.js
の{props.children}
の部分に「"最初のページ"」が渡されます。
つまり、だいたい
<main>最初のページ</main>
と書いているような状態です。
とりあえずbuild
とりあえずターミナルでgatsby build
と打ってビルドします。
(前の記事にもある通りですが、ビルドが終了しない場合はnpm add -D cross-env
します)。
ビルドが終了したら、
gatsby serve
と打ちます。
すると
You can now view (サイト名) in the browser.
http://localhost:9000/
と表示されるので、ブラウザでhttp://localhost:9000/
と打ってみます。
すると次のような感じになるはずです:
ちゃんと<Head>
で設定していないtitle
に「"不等式botのWebSite"」が渡されていることが確認できますし、{description}
に渡した「"最初のページ"」が表示されています。
page descriptionoに「"最初のページ"」が渡されているか確認するために、コンソールを見てみます。
右上の「更新」の横の3点をクリックして、
その他のツール → デベロッパーツール
と進みます。
すると右側にコンパイル後のHTMLファイルの中身のような何かが表示されると思います。
以下のような感じです:
<head>...</head>
の横にある▷を押すと、このタグの中身が表示されます:
ちゃんと
<meta data-react-helmet="true" name="author" content="不等式bot">
<meta data-react-helmet="true" name="description" content="最初のページ">
となっていて、初期値の設定や渡した値が反映されていることが確認できます!
今はページの内容があまりに薄いのでとりあえず適当な感じですが、あとは編集していくだけです。
参考
・React公式「Hello World」
・.defaultProps
について:PropTypesを用いた型チェック
・コンポーネントと props
Discussion