Gatsby公式チュートリアルやったよ


https://www.gatsbyjs.org/docs/
ずっと気になっていたGatsby、やってみました!

ほとんど公式の訳となりますが、備忘録としてまとめておきます。
公式がかなり優しめだったので、優しすぎる部分（nodeの設定・reactについて等)は省いていきます。

##  1.Gatsbyチュートリアル基礎の基礎

GatsbyにはCLIがありますので、インストールします。

```
$ npm install -g gatsby-cli
```

ターミナル再起動後、以下のコマンドでインストールできたか確認してください。
コマンドの説明が出たら成功です!

```
$ gatsby --help
```

get Startedなので、すぐにギャツビーが試せるように、公式が専用のスターターなるものを準備してくれています。
スターターというのは、プロジェクトを作る際に指定するサイトの根幹部分です。公式のgatsby-starter-hello-worldスターターからサイトを作ります。

```
$ gatsby new hello-world https://github.com/gatsbyjs/gatsby-starter-hello-world
```

`gatsby new` でgatsbyのプロジェクトを作成できます。 
`hello-world`は任意のサイト名です。これがフォルダ名になります。
`https://github.com/gatsbyjs/gatsby-starter-hello-world`はスターターがあるgithubのURLですね。
このURLを省略すると[デフォルトスターター](https://github.com/gatsbyjs/gatsby-starter-default)が割り当てられるようです。


次は下記のコマンドでフォルダ移動後、developモードをスタートします。

```
$ cd hello-world
$ gatsby develop
```
 ※エラーとなる場合、`node modules`と`package-lock.json`を削除し`npm install`

node_moduleやpublicがダウンロードされて、localhost:8000が立ち上がりました!
http://localhost:8000/ をみてみましょう。

![スクリーンショット 2020-04-29 17.50.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/441432/846e21a6-eb37-39aa-19d1-8dac164a5eeb.png)


殺風景!ここから始まるサクセスストーリーって感じです。
ちなみにGatsbyはホットリロードが標準で仕込まれています🎉


##2. react普通に使えちゃう&デプロイしてみる
`Link`コンポーネントも標準で入っています。


```react:src/pages/index.js
import React from "react"
import { Link } from "gatsby"
import Header from "../components/header"
export default () => (
  <div style={{ color: `purple` }}>
    <Link to="/contact/">Contact</Link>
    <Header headerText="Hello Gatsby!" />
    <p>What a world.</p>
    <img src="https://source.unsplash.com/random/400x200" alt="" />
  </div>
)
```

```react:src/components/header.js
import React from "react"

export default props => <h1>{props.headerText}</h1>

```

```react:src/pages/contact.js
import React from "react"
import { Link } from "gatsby"
import Header from "../components/header"
export default () => (
  <div style={{ color: `teal` }}>
    <Link to="/">Home</Link>
    <Header headerText="Contact" />
    <p>Send us a message!</p>
  </div>
)
```
上記3ファイルを用意してください。
コンポーネントも使えるし、Linkがきちんと動いているのもわかると思います。
しかもルーティング勝手にやってくれていますね...すごい

### デプロイしてみよう
surgeを使ってデプロイしてみます。
初めてsurge使ったんですけどお手軽めっちゃ便利でした。

```
$ npm i -g surge
```

ターミナル再起動後、

```
$ gatsby build   // buildファイル生成
$ surge public/  // デプロイ
```

surge public後はメールアドレスやパスワード設定を求められるので打ち込んでください。
生成できたら http:// surgeが吐き出した文字列 でアクセスできます。末尾がだいたいsurge.shぽいです。

## 3. スタイリングについて

###グローバルCSS
グローバルなスタイリングは何と言っても不可欠。
その簡単な解決法として、スタイルシートを用意することがチュートリアルでは進められています。

```
├── package.json
├── src
│   └── pages
│       └── index.js
│   └── styles
│       └── global.css
├── gatsby-browser.js
```
このようなファイル構成にします。
追加するのはstyleフォルダ,global.css,gatsby-browser.jsになります。
gatsby-browser.jsはこのファイル名じゃないといけないので注意です。

```css:global.css
html {
  background-color: lavenderblush;
}
```

```js:gatsby-browser.js
import "./src/styles/global.css"

// または:
// require('./src/styles/global.css')
```

`gatsby develop`　で起動すると、ちゃんと背景にスタイルが効いていると思います。
今までのreactでの苦労がみるみる消えて無くなっていくような感覚です。

ただ公式曰く `これは早く始めるためのものでもっといい方法あるぞ(共有レイアウトコンポーネント)`とのことなので、ちょっと脱線して確認したい方は[こちらをご覧ください。](https://www.gatsbyjs.org/docs/global-css/)

###CSSモジュール
次はコンポーネント固有のCSSを実装していきます。
下記のコンポーネントを作成します。

```react:src/components/container.js
import React from "react"
import containerStyles from "./container.module.css"
export default ({ children }) => (
  <div className={containerStyles.container}>{children}</div>
)
```

そして本命の　`container.module.css`を作成します。

```css:src/components/container.module.css
.container {
  margin: 3rem auto;
  max-width: 600px;
}

.user {
  display: flex;
  align-items: center;
  margin: 0 auto 12px auto;
}

.user:last-child {
  margin-bottom: 0;
}

.avatar {
  flex: 0 0 96px;
  width: 96px;
  height: 96px;
  margin: 0;
}

.description {
  flex: 1;
  margin-left: 18px;
  padding: 12px;
}

.username {
  margin: 0 0 12px 0;
  padding: 0;
}

.excerpt {
  margin: 0;
}
```

拡張子を `.css`　ではなく `.module.css` にすることによって、
Gatsbyはこのファイルを**グローバルCSSじゃなくてCSSモジュールね!** と解釈してくれます。

下記のファイルを作成し、 `http://localhost:8000/about-css-modules
 `をみてみましょう。

```react:src/pages/about-css-modules.js
import React from "react"

import Container from "../components/container"

export default () => (
  <Container>
    <h1>About CSS Modules</h1>
    <p>CSS Modules are cool</p>
  </Container>
)
```

containerStyles.containerがちゃんと効いていることがわかると思います。
実際に開発者モードでスタイルを見ると、クラス名がめちゃめちゃ長い文字列担っているかと思います。
これは必ずユニークになるように生成されています。
about-css-modules.jsに下記のコードをコピペしてみてください。
スタイルがしっかり効いているのがわかると思います。



```react:src/pages/about-css-modules.js
import React from "react"
import styles from "./about-css-modules.module.css"
import Container from "../components/container"

console.log(styles)

const User = props => (
  <div className={styles.user}>
    <img src={props.avatar} className={styles.avatar} alt="" />
    <div className={styles.description}>
      <h2 className={styles.username}>{props.username}</h2>
      <p className={styles.excerpt}>{props.excerpt}</p>
    </div>
  </div>
)

export default () => (
  <Container>
    <h1>About CSS Modules</h1>
    <p>CSS Modules are cool</p>
    <User
      username="Jane Doe"
      avatar="https://s3.amazonaws.com/uifaces/faces/twitter/adellecharles/128.jpg"
      excerpt="I'm Jane Doe. Lorem ipsum dolor sit amet, consectetur adipisicing elit."
    />
    <User
      username="Bob Smith"
      avatar="https://s3.amazonaws.com/uifaces/faces/twitter/vladarbatov/128.jpg"
      excerpt="I'm Bob Smith, a vertically aligned type of guy. Lorem ipsum dolor sit amet, consectetur adipisicing elit."
    />
  </Container>
)
```
![スクリーンショット 2020-04-29 19.12.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/441432/a7b2f6a3-198c-6c9c-359b-127683cd928a.png)

CSS-in-JSについてはチュートリアルでは取り上げられていませんが、
ほとんどのCSSライブラリはgatsby用のプラグインが存在するらしいです　（よかった...)
EmotionとStyled Componentについては別でチュートリアルが設けられているそうなのでよかったらみてみてください。

SassやStylusなんかもGatsbyではサポートされています。

## 3. Gatsbyの拡張機能について
Gastbyは拡張可能なように設計されています。Gatsby用のプラグインを使用することを学んでみます。

プラグインはコミュニティーメンバーが作成していて、
[たくさんのプラグインが公開されているようです。](https://www.gatsbyjs.org/plugins/)

公式チュートリアルでは、Typography.js用のGatsbyプラグインを使用して学ぶ形になっています。
Typography.jsは、フォントのスタイルを簡単に設定できちゃうAPIです。

フォルダをたくさんいじってしまったので、新しいフォルダを作成します。

```
$ gatsby new tutorial-part-three https://github.com/gatsbyjs/gatsby-starter-hello-world
cd tutorial-part-three
```

まず、必要パッケージ群をインストールします。
インストールするべきパッケージは、プラグインのインストールページで紹介されています。

```
$ npm install --save gatsby-plugin-typography react-typography typography typography-theme-fairy-gates
```

そして、`gatsby-config.js`ファイルを下記のように変更します。

```js
module.exports = {
  plugins: [
    {
      resolve: `gatsby-plugin-typography`,
      options: {
        pathToConfigModule: `src/utils/typography`,
      },
    },
  ],
}
```
くわしい書き方は公式のdocumentをみてください。

次は、typography.jsのための設定ファイルを書いていきます。

utilディレクトリを作成し、typography.jsを以下のように記述してください。

```js:src/utils/typography.js
import Typography from "typography"
import fairyGateTheme from "typography-theme-fairy-gates"
const typography = new Typography(fairyGateTheme)
export const { scale, rhythm, options } = typography
export default typography
```

全てのファイルが準備できたら、一度立ち上げているサーバーを落として、再度
`gatsby develop`で立ち上げてサイトにアクセスしてください。

![スクリーンショット 2020-04-30 16.44.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/441432/24eef2c1-f564-48c5-76e8-7544e2d7e389.png)

typography.jsのスタイルが読み込まれています!good!

下記のコードを貼り付けてサイトを見ると、
素敵なフォントに仕上がっているのを実感できると思います。

```react:src/pages/index.js
import React from "react"
export default () => (
  <div style={{ margin: `3rem auto`, maxWidth: 600 }}>
    <h1>Hi! I'm building a fake Gatsby site as part of a tutorial!</h1>
    <p>
      What do I like to do? Lots of course but definitely enjoy building
      websites.
    </p>
  </div>
)
```

## 4. ギャツビーでのデータの扱い
ギャツビーではGraphQLを扱うとのこと。これはとても便利な予感ですね!
https://www.howtographql.com/
GraphQLについてはこちらのチュートリアルがおすすめだそうです。
ちょっとみた感じ、英語ですがわかりやすかったです。

非構造化データを直接Gatsbyに取り込む（小規模向け)こともできるし
GraphQLのプラグインを使うこともできるとのことです（大規模向け)。

ひとまずGraphQLでのやり方をやってみましょう!
まずは新しいプロジェクトを用意します。

```
$ gatsby new tutorial-part-four https://github.com/gatsbyjs/gatsby-starter-hello-world
$ cd tutorial-part-four
```

そしてtypography.jsのKirkhamテーマ、CSS-in-JSライブラリの Emotionをインストールします。


```
$ npm install --save gatsby-plugin-typography typography react-typography typography-theme-kirkham gatsby-plugin-emotion @emotion/core
```

https://kyleamathews.github.io/typography.js/
こちらのサイトの pick themeでTypographyのテーマの見た目を確認できます。

下記の4ファイルを準備します。ページコンポーネントが2つ、
レイアウトコンポーネントが1つ,
typographyの設定ファイルが1つです。

```react:src/components/layout.js
import React from "react"
import { css } from "@emotion/core"
import { Link } from "gatsby"
import { rhythm } from "../utils/typography"
export default ({ children }) => (
  <div
    css={css`
      margin: 0 auto;
      max-width: 700px;
      padding: ${rhythm(2)};
      padding-top: ${rhythm(1.5)};
    `}
  >
    <Link to={`/`}>
      <h3
        css={css`
          margin-bottom: ${rhythm(2)};
          display: inline-block;
          font-style: normal;
        `}
      >
        Pandas Eating Lots
      </h3>
    </Link>
    <Link
      to={`/about/`}
      css={css`
        float: right;
      `}
    >
      About
    </Link>
    {children}
  </div>
)
```

```react:src/pages/index.js
import React from "react"
import Layout from "../components/layout"
export default () => (
  <Layout>
    <h1>Amazing Pandas Eating Things</h1>
    <div>
      <img
        src="https://2.bp.blogspot.com/-BMP2l6Hwvp4/TiAxeGx4CTI/AAAAAAAAD_M/XlC_mY3SoEw/s1600/panda-group-eating-bamboo.jpg"
        alt="Group of pandas eating bamboo"
      />
    </div>
  </Layout>
)
```

```react:src/pages/about.js
import React from "react"
import Layout from "../components/layout"

export default () => (
  <Layout>
    <h1>About Pandas Eating Lots</h1>
    <p>
      We're the only site running on your computer dedicated to showing the best
      photos and videos of pandas eating lots of food.
    </p>
  </Layout>
)
```

```react:src/utils/typography.js
import Typography from "typography"
import kirkhamTheme from "typography-theme-kirkham"

const typography = new Typography(kirkhamTheme)

export default typography
export const rhythm = typography.rhythm
```

そしてgatsby-config.jsを下記のように編集して、プラグインを設定をします。

```react:gatsby-config.js
module.exports = {
  plugins: [
    `gatsby-plugin-emotion`,
    {
      resolve: `gatsby-plugin-typography`,
      options: {
        pathToConfigModule: `src/utils/typography`,
      },
    },
  ],
}
```

その後`gatsby develop｀を実行すると、パンダの画像があるページが出てくると思います。🐼
ここからクエリをやってみます!

http://localhost:8000/about/  をみてください。
About Pandas Eating Lots というタイトルが表示されています。
もしこのページ名を変更するときは、この部分を調整することになります。
しかし将来サイトがもっと大規模になり、タイトルがあちこちで使用されていたら、私たちは全ての該当箇所を探し出して修正しないといけませんね。大変ですしミスも増えます。

なので、そのようなデータは一纏めにし、そこからデータを持ってくる方が効率がいいです。
Gatsbyでは`atsby-config.js`の`siteMetadata`オブジェクトに記述することでデータの一元管理が可能となります。

```react:gatsby-config.js
module.exports = {
  siteMetadata: {
    title: `Title from siteMetadata`,
  },
  plugins: [
    `gatsby-plugin-emotion`,
    {
      resolve: `gatsby-plugin-typography`,
      options: {
        pathToConfigModule: `src/utils/typography`,
      },
    },
  ],
}
```

上記ファイルでデータを定義した上で、データを使用するコンポーネントは以下のように
設定します。

```react:src/pages/about.js
import React from "react"
import { graphql } from "gatsby"
import Layout from "../components/layout"
export default function About({ data }) {
  return (
    <Layout>
      <h1>About {data.site.siteMetadata.title}</h1>
      <p>
        We're the only site running on your computer dedicated to showing the
        best photos and videos of pandas eating lots of food.
      </p>
    </Layout>
  )
}
export const query = graphql`
  query {
    site {
      siteMetadata {
        title
      }
    }
  }
`
```
gatsbyからgraphqlを読み込んでおり、それを元に const queryを作成しています。
これは　pageコンポーネントでしか使えないので注意してください。
使用コンポーネントのpropsに、graphQLのデータが渡っていますね。
`gatsby develop`でサイトを読み込み直し、aboutページにアクセスして確認してみてください。

### staticQuery 
staticQueryは、Gatsbyのv2から登場したpageコンポーネント以外でも使用可能なAPIです。
`useStaticQuery`を使用します。
下記のようにlayout.jsを書き直してください。

```react:src/components/layout.js
import React from "react"
import { css } from "@emotion/core"
import { useStaticQuery, Link, graphql } from "gatsby"
import { rhythm } from "../utils/typography"
export default function Layout({ children }) {
  const data = useStaticQuery(
    graphql`
      query {
        site {
          siteMetadata {
            title
          }
        }
      }
    `
  )
  return (
    <div
      css={css`
        margin: 0 auto;
        max-width: 700px;
        padding: ${rhythm(2)};
        padding-top: ${rhythm(1.5)};
      `}
    >
      <Link to={`/`}>
        <h3
          css={css`
            margin-bottom: ${rhythm(2)};
            display: inline-block;
            font-style: normal;
          `}
        >
          {data.site.siteMetadata.title}
        </h3>
      </Link>
      <Link
        to={`/about/`}
        css={css`
          float: right;
        `}
      >
        About
      </Link>
      {children}
    </div>
  )
}
```

gatsby-config.jsのtitleを書き直せば、すぐにその実行結果が反映されたものが確認できます。

##5.Source Pluginについて
Gatsbyのデータ取り込みを覚えるために、まず **GraphiQL**について知る必要があります。
GraphiQLはGraphQLの統合開発環境（IDE）です。
Gatsbyはこれを標準で持っているので、`http://localhost:8000/___graphql` にアクセスすると確認できます。

`option` + `space` もしくは　`shift` + `space`キーで自動補完機能が使えます。
`command` + `enter` キーで実行のショートカットです。めっちゃ便利。


### Source Plugin
対応するソースプラグインがあれば、fileやCMSからデータを引っ張ってくることができます。
今回は例として `gatsby-source-filesystem`を使ってみます。

```
$ npm install --save gatsby-source-filesystem
```
`gatsby-config.js`を編集します。

```js:gatsby-config.js
module.exports = {
  siteMetadata: {
    title: `Title from siteMetadata`,
  },
  plugins: [
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        name: `src`,
        path: `${__dirname}/src/`,
      },
    },
    `gatsby-plugin-emotion`,
    {
      resolve: `gatsby-plugin-typography`,
      options: {
        pathToConfigModule: `src/utils/typography`,
      },
    },
  ],
}
```

サーバーを立ち上げ直してもう一度`http://localhost:8000/___graphql`にアクセスすると、
`gatsby-source-filesystem`によって　**allFile,file**の２項目が追加されているのがわかるかと思います。
allFileの項目を`commandキー`を押しながらクリックしてください。
これによって、各ファイルのidが事前に入力されます。
node部分の項目を選択していくと、各node以下のアイテムを追加することができます。

実際にこれらの値をJSから取得してみましょう。
新しく `my-file.js`を作成し、以下のように編集します。

```react:src/pages/my-file.js
import React from "react"
import { graphql } from "gatsby"
import Layout from "../components/layout"

export default ({ data }) => {
  console.log(data)
  return (
    <Layout>
      <div>Hello world</div>
    </Layout>
  )
}

export const query = graphql`
  query {
    allFile {
      edges {
        node {
          relativePath
          prettySize
          extension
          birthTime(fromNow: true)
        }
      }
    }
  }
`
```

実際にページを確認すると、allFile以下がコンソールで取得できているのがわかるかと思います。

これらを実際にビューに起こしたコードが以下になります。

```react:src/pages/my-file.js
import React from "react"
import { graphql } from "gatsby"
import Layout from "../components/layout"

export default ({ data }) => {
  console.log(data)
  return (
    <Layout>
      <div>
        <h1>My Site's Files</h1>
        <table>
          <thead>
            <tr>
              <th>relativePath</th>
              <th>prettySize</th>
              <th>extension</th>
              <th>birthTime</th>
            </tr>
          </thead>
          <tbody>
            {data.allFile.edges.map(({ node }, index) => (
              <tr key={index}>
                <td>{node.relativePath}</td>
                <td>{node.prettySize}</td>
                <td>{node.extension}</td>
                <td>{node.birthTime}</td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    </Layout>
  )
}

export const query = graphql`
  query {
    allFile {
      edges {
        node {
          relativePath
          prettySize
          extension
          birthTime(fromNow: true)
        }
      }
    }
  }
`
```

`http://localhost:8000/my-files`を確認してみてください。

以上がsource Pluginの使い方になります。次はTransformer Pluginについて学びます。
Transformer Pluginはsource Pluginで取得したデータを加工する役割を担っています。

## 6. Transformer Pluginについて
チュートリアルでは例として、markdownで書かれたファイルをTransformer Pluginを使ってHTMLに書き直します。

まずはマークダウンのファイルを準備します。

```md:src/pages/sweet-pandas-eating-sweets.md
---
title: "Sweet Pandas Eating Sweets"
date: "2017-08-10"
---

パンダ超かわいい.

超かわいいパンダのビデオあるよ.

<iframe width="560" height="315" src="https://www.youtube.com/embed/4n0xNbfJLR8" frameborder="0" allowfullscreen></iframe>

```

再度`http://localhost:8000/my-file`にアクセスすると、
sweet-pandas-eating-sweets.mdの情報が増えていることがわかると思います。

マークダウンファイルを変換するためのTransformer Pluginをインストールします。

```
npm i --save gatsby-transformer-remark
```

`gatsby-config`に以下を追加します。
チュートリアルでは`gatsby-plugin-emotion`,の真上に差し込まれています。
階層は`gatsby-plugin-emotion`,と同様の階層です。

```react:gatsby-config
`gatsby-transformer-remark`,
```

gatsby-config後は　`gatsby develop`をし直す事を忘れないようにしてください。

GraphiQL（`http://localhost:8000/___graphql`）を見ると、
- allMarkdownRemark
- markdownRemark
の2項目が追加されているのがわかるかと思います。

![スクリーンショット 2020-05-07 16.56.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/441432/b9b5f89c-0761-f20a-5ab1-ebb0767bc30c.png)

上記のように項目を洗濯していくと、マークアップのデータが取得できているのがわかると思います!
トップページを以下のようにすれば、自動で記事リストを生成することができます。

```react:src/page:index.js
import React from "react"
import { graphql } from "gatsby"
import { css } from "@emotion/core"
import { rhythm } from "../utils/typography"
import Layout from "../components/layout"

export default ({ data }) => {
  console.log(data)
  return (
    <Layout>
      <div>
        <h1
          css={css`
            display: inline-block;
            border-bottom: 1px solid;
          `}
        >
          Amazing Pandas Eating Things
        </h1>
        <h4>{data.allMarkdownRemark.totalCount} Posts</h4>
        {data.allMarkdownRemark.edges.map(({ node }) => (
          <div key={node.id}>
            <h3
              css={css`
                margin-bottom: ${rhythm(1 / 4)};
              `}
            >
              {node.frontmatter.title}{" "}
              <span
                css={css`
                  color: #bbb;
                `}
              >
                — {node.frontmatter.date}
              </span>
            </h3>
            <p>{node.excerpt}</p>
          </div>
        ))}
      </div>
    </Layout>
  )
}

export const query = graphql`
  query {
    allMarkdownRemark {
      totalCount
      edges {
        node {
          id
          frontmatter {
            title
            date(formatString: "DD MMMM, YYYY")
          }
          excerpt
        }
      }
    }
  }
`
``

```

私はこのコードを読んだ時 frontmatterって何だ？　となってしまいました。
https://www.gatsbyjs.org/docs/adding-markdown-pages/#frontmatter-for-metadata-in-markdown-files

先ほど mdファイルでダッシュ３つでくくった部分がfrontmatterとして解釈され、
メタデータとして使用することができるようになるそうです。

記事が１つだと寂しいのでマークアップのページを１つ増やしてみましょう。


```md:src/pages/pandas-and-bananas.md
---
title: "Pandas and Bananas"
date: "2017-08-21"
---

パンダはバナナを食べるの？　このビデオを見れはそれが事実だとわかります。
パンダはバナナが大好きみたいです。

<iframe width="560" height="315" src="https://www.youtube.com/embed/4SZl1r2O_bY" frameborder="0" allowfullscreen></iframe>
```

![スクリーンショット 2020-05-07 17.04.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/441432/a658749a-18b5-76e3-6ec1-beaf38e1f434.png)

ちゃんと追加されましたね!
でも、新しい記事の方が上に来て欲しいですよね？
GraphQLに引数を渡すことでnodeを抽出したりソートしたり、フィルターをかけたりすることが可能です。
詳細は
https://www.gatsbyjs.org/docs/graphql-reference/
こちらの公式ガイドをみてください。

この場合であれば、index.jsの`allMarkdownRemark`を以下のように書き換えればOKです。

```react:src/pages/index.js
export const query = graphql`
  query {
    allMarkdownRemark(sort: { fields: [frontmatter___date], order: DESC }) { 
      totalCount
      edges {
...
```

現在はトップの記事リストのみですが、記事ページも必要になります。
１つ１つpageを追加していくこともできますが、ページを自動生成する方法を学習してみましょう。

## 7. データからページを自動生成する

###slugを作る 
slugは　`https://www.gatsbyjs.org/tutorial/part-seven/`で言う所の`/tutorial/part-seven/`の部分です。

マークダウンのHTMLページ生成では 
- **onCreateNode** 
- **createPages**
の２つのgatsbyのAPIを学ぶ必要があります。

GatsbyのAPIを使用するには、　`gatsby-node.js`ファイルを作成し,functionをエクスポートします。

```react:gatsby-node.js
exports.onCreateNode = ({ node }) => {
  console.log(node.internal.type)
}
```
上記のonCreateNodeはnodeが更新、もしくは作成された時に呼ばれます。
`gatsby develop`を実行すると、多くのNodeがconsole.logによってターミナル上に流れてくるのが確認できます。

<img width="789" alt="スクリーンショット 2020-05-07 17.34.30.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/441432/a64a8f5a-5750-3970-efbf-a5e8696136cc.png">

`gatsby-node.js`を以下のように書き換えてください。

```react:gatsby-node.js
exports.onCreateNode = ({ node, getNode }) => {
  if (node.internal.type === `MarkdownRemark`) {
    const fileNode = getNode(node.parent)
    console.log(`\n`, fileNode.relativePath)
  }
}
```

上記は何をしているかと言うと、まずMarkdownRemarkのnodeを取得します。
しかしMarkdownRemarkにはslugの情報が含まれていないので、その親ノードであるfileNodeから
relativePathを取得しています。
![スクリーンショット 2020-05-07 17.50.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/441432/174a952f-ef55-085e-0768-ae868afe2b6f.png)


では、これを元にスラッグを生成します。実は上記部分は`gatsby-source-filesystem`がすでに持っている機能だったりします。

```react:gatsby-node.js
const { createFilePath } = require(`gatsby-source-filesystem`)

exports.onCreateNode = ({ node, getNode }) => {
  if (node.internal.type === `MarkdownRemark`) {
    console.log(createFilePath({ node, getNode, basePath: `pages` }))
  }
}
```
上記の実装で、前実装と同じように親ノードを探し出し、slugの生成までやってくれます。
slugが追加できたので、次はnodeを生成しましょう。**createNodeField**APIを用います。


```react:gatsby-node.js
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
    })
  }
}
```

GraphiQLのallMarkdownRemark.edges.node.fields.slugに,新たなslugが加わっていることが確認できます。
次はページを生成します。

```react: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,
      },
    })
  })
}
```

graphqlファンクションはPromiseを返すことに注意してください。
resultでgraphQLから取得したページをforEachで回して、`createPage`でページを生成しています。
contextで指定したデータは、そのページのデータとしてgraphQLから使用可能になります。
`./src/templates/blog-post.js`を雛形としていますので、blog-post.jsを作成する必要があります。


```react:/src/templates/blog-post.js
import React from "react"
import { graphql } from "gatsby"
import Layout from "../components/layout"
export default function BlogPost({ data }) {
  const post = data.markdownRemark
  return (
    <Layout>
      <div>
        <h1>{post.frontmatter.title}</h1>
        <div dangerouslySetInnerHTML={{ __html: post.html }} />
      </div>
    </Layout>
  )
}
export const query = graphql`
  query($slug: String!) {
    markdownRemark(fields: { slug: { eq: $slug } }) {
      html
      frontmatter {
        title
      }
    }
  }
`
```

`query($slug: String!)`
!マークは値が必須であることを表しています。 文字列の型定義がなされていますね。

https://qiita.com/NagaokaKenichi/items/d341dc092012e05d6606

`markdownRemark(fields: { slug: { eq: $slug } })`

この部分は、MongoDBのような指定方法でオブジェクトをフィルタリングすることができる機能を使っています。
（私はMongoDBの書き方を知りませんが🙇‍♂️)
つまり、fieldsのslugが　$slugと　イコールであるもののみを取得しているということになります。
https://www.gatsbyjs.org/docs/graphql-reference/#query-variables

ここまで編集したら、`gatsby develop`で再度立ち上げ直してください。
自動生成したページリストを取得するには、　`http://localhost:8000/denden` のように、存在しないページにアクセスするといいです。
![スクリーンショット 2020-05-08 11.39.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/441432/6fc5271b-88c5-5ab6-e87a-f9878f72b04e.png)

このようにページ一覧が表示されます。
各ページのリンクを押すと、ページが生成できていることが確認できるかと思います。

## 8. プロジェクトのbuildとLighthouseによるサイト診断

Lighthouseってなんだい？
(意訳) `https://developers.google.com/web/tools/lighthouse/`から
>LighthouseはWebページの品質向上のためのオープンソースの自動ツールです。
パブリックなページ、認証が必要なページ、どんなページにでも使うことができます。
パフォーマンス・アクセシビリティ・PWAなどに関することを検査します。

まず、Gastbyのプロダクションが必要になるので、 buildを行います。
developを走らせてる場合はそれを一旦止めて、下記を実行します。

```
$ gatsby build 
```

buildできたら、productionをローカルで確認するためのコマンドを打ちます。

```
$ gatsby serve
```

初期では `http://localhost:9000/`　に立ち上がります。
立ち上がったら、 **Chromeの**devToolを開きます。
`Audits`タブを開いてください。
`Perform an audit…` をクリックしてしばらくすると診断結果が表示されます。

とても便利ですね!
これらの値を向上させるために色々な改善を行う必要があります。
gatsbyには様々なプラグインが用意されているので、それらを使って改善するのもいいでしょう。
チュートリアルでは下記が紹介されていました。

- gatsby-plugin-manifest (PWAのためのmanifest.webmanifestファイルを作成するプラグイン)
- gatsby-plugin-offline(PWAのためのserver worker用のプラグイン)
- gatsby-plugin-react-helmet(メタデータ編集のためのプラグイン)

以上です、お疲れ様でした。

【参考】 https://www.gatsbyjs.org/tutorial/