tag:crieit.net,2005:https://crieit.net/tags/Gatsby/feed
「Gatsby」の記事 - Crieit
Crieitでタグ「Gatsby」に投稿された最近の記事
2021-11-05T21:44:25+09:00
https://crieit.net/tags/Gatsby/feed
tag:crieit.net,2005:PublicArticle/17741
2021-11-05T21:44:25+09:00
2021-11-05T21:44:25+09:00
https://crieit.net/posts/microcms-api-update-gatsby-update-20211106
microCMS の X-API-KEY リニューアルに合わせて Vercel の設定と Gatsby のプロジェクトを更新する
<p>メール通知で microCMS の X-API-KEY がリニューアルされたという通知を受け取って対応することにしました。</p>
<ul>
<li><a target="_blank" rel="nofollow noopener" href="https://blog.microcms.io/renew-x-microcms-api-key/">APIキーをX-MICROCMS-API-KEYへとリニューアルしました。 | microCMSブログ</a></li>
</ul>
<blockquote>
<p>従来のX-API-KEY, X-WRITE-API-KEY, X-DRAFT-KEYは統合され、X-MICROCMS-API-KEYに変更となります。</p>
<p><a target="_blank" rel="nofollow noopener" href="https://blog.microcms.io/renew-x-microcms-api-key/">APIキーをX-MICROCMS-API-KEYへとリニューアルしました。 | microCMSブログ</a></p>
</blockquote>
<p>とのことなので、これに対応することにします。</p>
<h2 id="microCMS"><a href="#microCMS">microCMS</a></h2>
<p>まずは microCMS 側の作業。新しいAPIキーを発行し直します。</p>
<p><a href="https://crieit.now.sh/upload_images/b639bdef8b9834d65ed80dcb79d999e46185263f658dd.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/b639bdef8b9834d65ed80dcb79d999e46185263f658dd.jpg?mw=700" alt="APIキーの一覧" /></a></p>
<p>「APIキー管理」のAPIキーの一覧で「旧X-API-KEY」があることを確認。</p>
<p><a href="https://crieit.now.sh/upload_images/6adc5584ea41a4d7620ea61147890b1261852649a9f13.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/6adc5584ea41a4d7620ea61147890b1261852649a9f13.jpg?mw=700" alt="APIキーの詳細" /></a></p>
<p>選択して詳細画面から「削除」を選択。</p>
<p>続いて新しいAPIキーを発行し直します。</p>
<p><a href="https://crieit.now.sh/upload_images/eef5b0f7a42cda381863a3eae0f6894361852651849ef.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/eef5b0f7a42cda381863a3eae0f6894361852651849ef.jpg?mw=700" alt="新X-MICROCMS-API-KEYの発行" /></a></p>
<p>X-MICROCMS-API-KEY を発行します。今回はAPI経由では参照しかしないので GET のみの権限とします。</p>
<p><a href="https://crieit.now.sh/upload_images/8febcc76cb4c74b656c4720ed16f44a06185265a7d678.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/8febcc76cb4c74b656c4720ed16f44a06185265a7d678.jpg?mw=700" alt="APIキーをコピー" /></a></p>
<p>発行されたAPIキーをコピーして控えます。</p>
<p>これで microCMS 側の作業は完了です。</p>
<h2 id="Vercel"><a href="#Vercel">Vercel</a></h2>
<p>続いて Vercel にログインします。</p>
<p><a href="https://crieit.now.sh/upload_images/1ae9a58b4f0e8ee01d8a591c1629ff9b618526623540c.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/1ae9a58b4f0e8ee01d8a591c1629ff9b618526623540c.jpg?mw=700" alt="Vercel の環境変数の一覧" /></a></p>
<p>プロジェクトの「Settings」から「Enviroment Variables」に進みます。</p>
<p><a href="https://crieit.now.sh/upload_images/3a0751306ac22bdcc1333827ce44d7f16185266ada888.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/3a0751306ac22bdcc1333827ce44d7f16185266ada888.jpg?mw=700" alt="API_KEYの変更" /></a></p>
<p><code>API_KEY</code>の値を先ほど控えた値に変更します。</p>
<p>これでOKかと思ったのですが……。</p>
<pre><code class="bash">00:03:22.489 error microCMS API ERROR:
00:03:22.489 statusCode: 401
00:03:22.489 message: X-MICROCMS-API-KEY header is invalid.
00:03:22.492 not finished source and transform nodes - 1.046s
00:03:23.631 Error: Command "npm run build" exited with 1
</code></pre>
<p>ビルドログを見ると 401エラー でコケていますね。認証に失敗しているようです。</p>
<ul>
<li><a target="_blank" rel="nofollow noopener" href="https://vanilla-note.com/posts/gatsby4-1-microcms-3/">microCMSの新しいX-MICROCMS-API-KEYに対応する | Vanilla note</a></li>
</ul>
<p>検索すると、 Gatsby の microCMS 連携のパッケージも更新しないといけないとのこと。</p>
<h2 id="Gatsby プロジェクト"><a href="#Gatsby+%E3%83%97%E3%83%AD%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88">Gatsby プロジェクト</a></h2>
<p>そこで該当パッケージのバージョンをアップデートします。</p>
<pre><code class="json"> "dependencies": {
// 略
"gatsby-source-microcms": "^1.2.1",
// 略
}
</code></pre>
<p><code>gatsby-source-microcms</code> を</p>
<pre><code class="json"> "dependencies": {
// 略
"gatsby-source-microcms": "^2.0.0",
// 略
}
</code></pre>
<p><code>2.0.0</code> にアップデート。</p>
<p>これでビルドを走らせ、正常に完了することを確認しました。</p>
<h2 id="参考"><a href="#%E5%8F%82%E8%80%83">参考</a></h2>
<ul>
<li><a target="_blank" rel="nofollow noopener" href="https://blog.microcms.io/renew-x-microcms-api-key/">APIキーをX-MICROCMS-API-KEYへとリニューアルしました。 | microCMSブログ</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://vanilla-note.com/posts/gatsby4-1-microcms-3/">microCMSの新しいX-MICROCMS-API-KEYに対応する | Vanilla note</a></li>
</ul>
<p>Vercel に関しては自分の過去の記事も参考にして辿りつつ……。</p>
<ul>
<li><a target="_blank" rel="nofollow noopener" href="https://labor.ewigleere.net/2021/08/29/gatsby-vercel-microcms-cooprate-2/">Gatsby.js + Vercel + microCMS の JAMStack 環境を構築する – Ewig Leere(Lab2)</a></li>
</ul>
arm-band
tag:crieit.net,2005:PublicArticle/17623
2021-08-29T00:49:34+09:00
2021-08-29T00:49:34+09:00
https://crieit.net/posts/gatsby-vercel-microcms-cooprate-20210829-2
Gatsby.js + Vercel + microCMS の JAMStack 環境を構築する
<p><a href="https://crieit.net/posts/gatsby-vercel-microcms-cooprate-20210829-1">microCMS の設定が完了した</a>ので、次は microCMS からデータを取得するように Gatsby.js の方に手を入れます。また、 microCMS と Vercel に設定を加えて連携させ、 Gatsby.js + Vercel + microCMS の JAMStack 環境を構築します。</p>
<h2 id="改修"><a href="#%E6%94%B9%E4%BF%AE">改修</a></h2>
<p>今回は<a target="_blank" rel="nofollow noopener" href="https://www.gatsbyjs.com/starters/renyuanz/leonids">leonids: Gatsby Starter | Gatsby</a>を使用しているので、その前提で。</p>
<p>テーマが変わったり、 microCMS のスキーマが変われば諸々の調整が必要となります。</p>
<h3 id="パッケージの追加"><a href="#%E3%83%91%E3%83%83%E3%82%B1%E3%83%BC%E3%82%B8%E3%81%AE%E8%BF%BD%E5%8A%A0">パッケージの追加</a></h3>
<pre><code class="bash">> yarn add yarn add gatsby-source-microcms
## 略
Done in 231.79s.
> yarn add marked
## 略
Done in 7.30s.
</code></pre>
<p>今回は microCMS を利用するので <code>gatsby-source-microcms</code> を追加します。また、本文コンテンツは Markdown で記述しているのですが Gatsby.js の自前の Markdownパーサ まで手が届かなかったので安直に <code>marked</code> を使いました。</p>
<p>それから、内部的には <code>dotenv</code> も使用していますが <code>yarn.lock</code> を見たら既に入っていたので追加はしていません。</p>
<h3 id="gatsby-config.js"><a href="#gatsby-config.js">gatsby-config.js</a></h3>
<p>さて、改修の最初は Gatsby.js の設定から。</p>
<pre><code class="javascript">module.exports = {
// 略
plugins: [
{
resolve: `gatsby-source-filesystem`,
options: {
path: `${__dirname}/content/blog`,
name: `blog`,
},
},
// 略
},
`gatsby-plugin-feed`,
{
// 略
],
// 略
}
</code></pre>
<p>これを以下のように修正。</p>
<pre><code class="js">const activeEnv = process.env.GATSBY_ACTIVE_ENV || process.env.NODE_ENV
if(activeEnv === "development") {
require("dotenv").config({
path: `.env.${activeEnv}`,
})
}
module.exports = {
// 略
plugins: [
{
resolve: 'gatsby-source-microcms',
options: {
apiKey: process.env.API_KEY,
serviceId: process.env.SERVICE_ID,
apis: [{
endpoint: process.env.APIS_ENDPOINT,
}],
},
},
// 略
{
resolve: `gatsby-plugin-feed`,
options: {
query: `
{
site {
siteMetadata {
title
description
siteUrl
}
}
}
`,
feeds: [
{
serialize: ({ query: { site, allMicrocmsHogeHogeBlog } }) => {
return allMicrocmsHogeHogeBlog.edges.map(edge => {
return Object.assign({}, edge.node, {
description: edge.node.keywords,
date: edge.node.date,
url: site.siteMetadata.siteUrl + edge.node.slug,
guid: site.siteMetadata.siteUrl + edge.node.slug,
custom_elements: [{ "content:encoded": edge.node.body }],
})
})
},
query: `
{
allMicrocmsHogeHogeBlog(sort: {fields: [date], order: DESC}) {
totalCount
pageInfo {
perPage
pageCount
}
edges {
node {
body
createdAt
date
id
keywords
publishedAt
revisedAt
slug
title
updatedAt
}
}
}
}
`,
output: "/rss.xml",
title: "HogeHoge Blog's RSS Feed",
},
],
},
},
// 略
],
// 略
}
</code></pre>
<p>変更点は以下。</p>
<ul>
<li>ローカルのファイルをコンテンツのリソース参照先としていたのを microCMS をリソースとするように修正</li>
<li><code>gatsby develop</code> 時は問題なかったのですが、 <code>gatsby build</code> 時に RSSフィードを生成する <code>gatsby-plugin-feed</code>プラグイン が通常の Markdown の構成をデフォルトにしており、 microCMS に置き換えたことでデータスキーマが異なるとエラーになってしまいました (本番ビルド時に気付いた)。
<ul>
<li>そこで、 <code>gatsby-plugin-feed</code>プラグイン の GraphQL も今回定義した microCMS のスキーマに沿って変更しました。併せて <code>serialize</code>メソッド の中身もスキーマに合わせて調整。</li>
</ul></li>
<li><a target="_blank" rel="nofollow noopener" href="https://www.gatsbyjs.com/plugins/gatsby-source-microcms/">gatsby-source-microcms | Gatsby</a>のサンプルコードでは Git 管理下になる <code>gatsby-config.js</code> に APIキー 等の情報がそのままベタ書きになってしまうので、 <code>dotenv</code> で外部ファイルに取り出すことで隠蔽しました
<ul>
<li>後述しますが、 Vercel の環境変数も <code>process.env</code> で渡ってくるので、<code>development</code> の場合は <code>dotenv</code> 経由の外部ファイルをパラメータのリソースに、 <code>production</code> の場合は Vercel の環境変数をリソースとするように書き分けました</li>
</ul></li>
</ul>
<h3 id="gatby-node.js"><a href="#gatby-node.js">gatby-node.js</a></h3>
<pre><code class="javascript">const path = require(`path`)
const { createFilePath } = require(`gatsby-source-filesystem`)
exports.createPages = async ({ graphql, actions }) => {
const { createPage } = actions
const blogPost = path.resolve(`./src/templates/blog-post.js`)
const result = await graphql(
`
{
allMarkdownRemark(
sort: { fields: [frontmatter___date], order: DESC }
limit: 1000
) {
edges {
node {
fields {
slug
}
frontmatter {
title
}
}
}
}
}
`
)
if (result.errors) {
throw result.errors
}
// Create blog posts pages.
const posts = result.data.allMarkdownRemark.edges
posts.forEach((post, index) => {
const previous = index === posts.length - 1 ? null : posts[index + 1].node
const next = index === 0 ? null : posts[index - 1].node
createPage({
path: post.node.fields.slug,
component: blogPost,
context: {
slug: post.node.fields.slug,
previous,
next,
},
})
})
// Create blog post list pages
const postsPerPage = 5
const numPages = Math.ceil(posts.length / postsPerPage)
Array.from({ length: numPages }).forEach((_, i) => {
createPage({
path: i === 0 ? `/` : `/${i + 1}`,
component: path.resolve("./src/templates/blog-list.tsx"),
context: {
limit: postsPerPage,
skip: i * postsPerPage,
numPages,
currentPage: i + 1,
},
})
})
}
exports.onCreateNode = ({ node, actions, getNode }) => {
const { createNodeField } = actions
if (node.internal.type === `MarkdownRemark`) {
const value = createFilePath({ node, getNode })
createNodeField({
name: `slug`,
node,
value,
})
}
}
</code></pre>
<p>これを以下のように修正。</p>
<pre><code class="javascript">const path = require(`path`)
const { createFilePath } = require(`gatsby-source-filesystem`)
exports.createPages = async ({ graphql, actions }) => {
const { createPage } = actions
const result = await graphql(
`
{
allMicrocmsHogeHogeBlog(sort: {fields: [date], order: DESC}) {
totalCount
pageInfo {
perPage
pageCount
}
edges {
node {
body
createdAt
date
id
keywords
publishedAt
revisedAt
slug
title
updatedAt
}
}
}
}
`
)
if (result.errors) {
throw result.errors
}
// Create blog posts pages.
const posts = result.data.allMicrocmsHogeHogeBlog.edges
result.data.allMicrocmsHogeHogeBlog.edges.forEach((post, index) => {
const previous = index === posts.length - 1 ? null : posts[index + 1].node
const next = index === 0 ? null : posts[index - 1].node
createPage({
path: post.node.slug,
component: path.resolve('./src/templates/blog-post.js'),
context: {
slug: post.node.slug,
previous,
next,
},
});
});
// Create blog post list pages
const postsPerPage = result.data.allMicrocmsHogeHogeBlog.pageInfo.limit || 10
const numPages = Math.ceil(result.data.allMicrocmsHogeHogeBlog.totalCount / postsPerPage)
console.log(result.data.allMicrocmsHogeHogeBlog.totalCount, postsPerPage)
Array.from({ length: numPages }).forEach((_, i) => {
createPage({
path: i === 0 ? `/` : `/${i + 1}`,
component: path.resolve("./src/templates/blog-list.tsx"),
context: {
limit: postsPerPage,
skip: i * postsPerPage,
numPages,
currentPage: i + 1,
},
})
})
}
exports.onCreateNode = ({ node, actions, getNode }) => {
const { createNodeField } = actions
if (node.internal.type === `microcmsHogeHogeBlog`) {
const value = createFilePath({ node, getNode })
createNodeField({
name: `slug`,
node,
value,
})
}
}
</code></pre>
<ul>
<li><a target="_blank" rel="nofollow noopener" href="https://www.gatsbyjs.com/plugins/gatsby-source-microcms/">gatsby-source-microcms | Gatsby</a>のサンプルコードはシンプル過ぎて GraphQL初心者には分かりづらかったので、 <code>gatsby develop</code> で起動した <code>http://localhost:8000/___graphql</code> の GraphQL を試すGUIでひたすらAPIを叩いてパラメータを変えたりしてどういう GraphQL を作れば望んだレスポンスを得られるか確認しながら地道に調整していきました</li>
<li>ベースのコードをなるべく変えないように調整して、各種プロパティの階層等を調整しました</li>
<li><code>MarkdownRemark</code> や <code>allMarkdownRemark</code> が Markdownファイル をリソースとする場合のキーのような働きをしているのが分かったので、それを <code>http://localhost:8000/___graphql</code> で表示された microCMS のキーに変更したり</li>
</ul>
<p>GraphQL の構造やレスポンスに慣れるまで時間がかかりましたが、最終的には <code>http://localhost:8000/___graphql</code> であれこれ試したのが一番効果がありました。</p>
<h3 id="blog-list.tsx"><a href="#blog-list.tsx">blog-list.tsx</a></h3>
<p>記事一覧ページ。トップページもこのテンプレートから生成されています。</p>
<pre><code class="javascript">// Gatsby supports TypeScript natively!
import React from "react"
import { PageProps, Link, graphql } from "gatsby"
import Layout from "../components/layout"
import SEO from "../components/seo"
import { rhythm } from "../utils/typography"
type PageContext = {
currentPage: number
numPages: number
}
type Data = {
site: {
siteMetadata: {
title: string
}
}
allMarkdownRemark: {
edges: {
node: {
excerpt: string
frontmatter: {
title: string
date: string
description: string
}
fields: {
slug: string
}
}
}[]
}
}
const BlogIndex = ({
data,
location,
pageContext,
}: PageProps<Data, PageContext>) => {
const siteTitle = data.site.siteMetadata.title
const posts = data.allMarkdownRemark.edges
const { currentPage, numPages } = pageContext
const isFirst = currentPage === 1
const isLast = currentPage === numPages
const prevPage = currentPage - 1 === 1 ? "/" : `/${currentPage - 1}`
const nextPage = `/${currentPage + 1}`
return (
<Layout location={location} title={siteTitle}>
<SEO title="All posts" />
{posts.map(({ node }) => {
const title = node.frontmatter.title || node.fields.slug
return (
<article key={node.fields.slug}>
<header>
<h3
style=<span>{</span><span>{</span>
marginBottom: rhythm(1 / 4),
<span>}</span><span>}</span>
>
<Link style=<span>{</span><span>{</span> boxShadow: `none` <span>}</span><span>}</span> to={node.fields.slug}>
{title}
</Link>
</h3>
<small>{node.frontmatter.date}</small>
</header>
<section>
<p
dangerouslySetInnerHTML=<span>{</span><span>{</span>
__html: node.frontmatter.description || node.excerpt,
<span>}</span><span>}</span>
/>
</section>
</article>
)
})}
<nav>
<ul
style=<span>{</span><span>{</span>
display: `flex`,
flexWrap: `wrap`,
justifyContent: `space-between`,
listStyle: `none`,
padding: 0,
<span>}</span><span>}</span>
>
<li>
{!isFirst && (
<Link to={prevPage} rel="prev">
← Previous Page
</Link>
)}
</li>
<li>
{!isLast && (
<Link to={nextPage} rel="next">
Next Page →
</Link>
)}
</li>
</ul>
</nav>
</Layout>
)
}
export default BlogIndex
export const pageQuery = graphql`
query blogPageQuery($skip: Int!, $limit: Int!) {
site {
siteMetadata {
title
}
}
allMarkdownRemark(
sort: { fields: [frontmatter___date], order: DESC }
limit: $limit
skip: $skip
) {
edges {
node {
excerpt
fields {
slug
}
frontmatter {
date(formatString: "MMMM DD, YYYY")
title
description
}
}
}
}
}
`
</code></pre>
<p>これを以下のように改修。</p>
<pre><code class="javascript">// Gatsby supports TypeScript natively!
import React from "react"
import { PageProps, Link, graphql } from "gatsby"
import Layout from "../components/layout"
import SEO from "../components/seo"
import { rhythm } from "../utils/typography"
type PageContext = {
currentPage: number
numPages: number
}
type Data = {
site: {
siteMetadata: {
title: string
}
}
allMicrocmsHogeHogeBlog: {
edges: {
node: {
id: string
keywords: string
title: string
updatedAt: string
slug: string
revisedAt: string
publishedAt: string
date: string
createdAt: string
body: string
}
}[]
}
}
const BlogIndex = ({
data,
location,
pageContext,
}: PageProps<Data, PageContext>) => {
const siteTitle = data.site.siteMetadata.title
const posts = data.allMicrocmsHogeHogeBlog.edges
const { currentPage, numPages } = pageContext
const isFirst = currentPage === 1
const isLast = currentPage === numPages
const prevPage = currentPage - 1 === 1 ? "/" : `/${currentPage - 1}`
const nextPage = `/${currentPage + 1}`
return (
<Layout location={location} title={siteTitle}>
<SEO title="All posts" />
{posts.map(({ node }) => {
const title = node.title || node.slug
return (
<article key={node.slug}>
<header>
<h3
style=<span>{</span><span>{</span>
marginBottom: rhythm(1 / 4),
<span>}</span><span>}</span>
>
<Link style=<span>{</span><span>{</span> boxShadow: `none` <span>}</span><span>}</span> to={node.slug}>
{title}
</Link>
</h3>
<small>{node.date}</small>
</header>
<section>
<p
dangerouslySetInnerHTML=<span>{</span><span>{</span>
__html: node.keywords,
<span>}</span><span>}</span>
/>
</section>
</article>
)
})}
<nav>
<ul
style=<span>{</span><span>{</span>
display: `flex`,
flexWrap: `wrap`,
justifyContent: `space-between`,
listStyle: `none`,
padding: 0,
<span>}</span><span>}</span>
>
<li>
{!isFirst && (
<Link to={prevPage} rel="prev">
← Previous Page
</Link>
)}
</li>
<li>
{!isLast && (
<Link to={nextPage} rel="next">
Next Page →
</Link>
)}
</li>
</ul>
</nav>
</Layout>
)
}
export default BlogIndex
export const pageQuery = graphql`
query blogPageQuery($skip: Int!, $limit: Int!) {
site {
siteMetadata {
title
}
}
allMicrocmsHogeHogeBlog(
sort: {fields: [date], order: DESC}
limit: $limit
skip: $skip
) {
edges {
node {
body
createdAt
date(formatString: "YYYY/MM/DD")
id
keywords
publishedAt
revisedAt
slug
title
updatedAt
}
}
}
}
`
</code></pre>
<p>ここは大々的な改修というよりは、 GraphQL の変更と、それに併せて変化したデータ構造に合わせてプロパティ名やチェーンを調整した感じです。</p>
<h3 id="blog-post.js"><a href="#blog-post.js">blog-post.js</a></h3>
<pre><code class="javascript">import React from "react"
import { Link, graphql } from "gatsby"
import Bio from "../components/bio"
import Layout from "../components/layout"
import SEO from "../components/seo"
import { rhythm, scale } from "../utils/typography"
const BlogPostTemplate = ({ data, pageContext, location }) => {
const post = data.markdownRemark
// const siteTitle = data.site.siteMetadata.title
const { previous, next } = pageContext
return (
<Layout location={location} title="Home">
<SEO
title={post.frontmatter.title}
description={post.frontmatter.description || post.excerpt}
/>
<article>
<header>
<h1
style=<span>{</span><span>{</span>
marginBottom: 0,
<span>}</span><span>}</span>
>
{post.frontmatter.title}
</h1>
<p
style=<span>{</span><span>{</span>
...scale(-1 / 5),
display: `block`,
marginBottom: rhythm(1),
<span>}</span><span>}</span>
>
{post.frontmatter.date}
</p>
</header>
<section dangerouslySetInnerHTML=<span>{</span><span>{</span> __html: post.html <span>}</span><span>}</span> />
<hr
style=<span>{</span><span>{</span>
marginBottom: rhythm(1),
<span>}</span><span>}</span>
/>
<footer>
<Bio />
</footer>
</article>
<nav>
<ul
style=<span>{</span><span>{</span>
display: `flex`,
flexWrap: `wrap`,
justifyContent: `space-between`,
listStyle: `none`,
padding: 0,
<span>}</span><span>}</span>
>
<li>
{previous && (
<Link to={previous.fields.slug} rel="prev">
← {previous.frontmatter.title}
</Link>
)}
</li>
<li>
{next && (
<Link to={next.fields.slug} rel="next">
{next.frontmatter.title} →
</Link>
)}
</li>
</ul>
</nav>
</Layout>
)
}
export default BlogPostTemplate
export const pageQuery = graphql`
query BlogPostBySlug($slug: String!) {
site {
siteMetadata {
title
}
}
markdownRemark(fields: { slug: { eq: $slug } }) {
id
excerpt(pruneLength: 160)
html
frontmatter {
title
date(formatString: "MMMM DD, YYYY")
description
}
}
}
`
</code></pre>
<p>これを以下のように改修。</p>
<pre><code class="javascript">import React from "react"
import { Link, graphql } from "gatsby"
import Bio from "../components/bio"
import Layout from "../components/layout"
import SEO from "../components/seo"
import { rhythm, scale } from "../utils/typography"
import marked from "marked"
const BlogPostTemplate = ({ data, pageContext, location }) => {
const post = data.microcmsHogeHogeBlog
// const siteTitle = data.site.siteMetadata.title
const { previous, next } = pageContext
return (
<Layout location={location} title="Home">
<SEO
title={post.title}
description={post.keywords}
/>
<article>
<header>
<h1
style=<span>{</span><span>{</span>
marginBottom: 0,
<span>}</span><span>}</span>
>
{post.title}
</h1>
<p
style=<span>{</span><span>{</span>
...scale(-1 / 5),
display: `block`,
marginBottom: rhythm(1),
<span>}</span><span>}</span>
>
{post.date}
</p>
</header>
<section dangerouslySetInnerHTML=<span>{</span><span>{</span> __html: marked(post.body) <span>}</span><span>}</span> />
<hr
style=<span>{</span><span>{</span>
marginBottom: rhythm(1),
<span>}</span><span>}</span>
/>
<footer>
<Bio />
</footer>
</article>
<nav>
<ul
style=<span>{</span><span>{</span>
display: `flex`,
flexWrap: `wrap`,
justifyContent: `space-between`,
listStyle: `none`,
padding: 0,
<span>}</span><span>}</span>
>
<li>
{previous && (
<Link to={'../'+previous.slug} rel="prev">
← {previous.title}
</Link>
)}
</li>
<li>
{next && (
<Link to={'../'+next.slug} rel="next">
{next.title} →
</Link>
)}
</li>
</ul>
</nav>
</Layout>
)
}
export default BlogPostTemplate
export const pageQuery = graphql`
query BlogPostBySlug($slug: String!) {
site {
siteMetadata {
title
}
}
microcmsHogeHogeBlog(slug: { eq: $slug }) {
id
keywords
title
updatedAt
slug
revisedAt
publishedAt
date(formatString: "YYYY/MM/DD")
createdAt
body
}
}
`
</code></pre>
<p>こちらも <code>blog-list.tsx</code> と同様 GraphQL の変更とそれに伴うプロパティ名やチェーンの調整がメインです。本文の Markdown は冒頭の通り時短のため <code>marked</code> を使いました。</p>
<p>こうして見てみると、 GraphQL に慣れるまでかなり紆余曲折した気がするのですが、 <code>blog-list.tsx</code> や <code>blog-post.js</code> は特に出来上がったコードがあまり元から変化していませんね……。</p>
<h2 id="microCMS で APIキー を参照"><a href="#microCMS+%E3%81%A7+API%E3%82%AD%E3%83%BC+%E3%82%92%E5%8F%82%E7%85%A7">microCMS で APIキー を参照</a></h2>
<p>microCMS で APIキー を控えます。</p>
<p><a href="https://crieit.now.sh/upload_images/949bd68fc9e6b312266c6dd7d831ade5612a583ed1bd6.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/949bd68fc9e6b312266c6dd7d831ade5612a583ed1bd6.jpg?mw=700" alt="APIキーの取得" /></a></p>
<p>「サービス設定」→「APIキー」と進みます。今回必要なのは「X-API-KEY」。これを控えておきます。</p>
<h2 id="Vercel の設定"><a href="#Vercel+%E3%81%AE%E8%A8%AD%E5%AE%9A">Vercel の設定</a></h2>
<p>続いて Vercel の設定へ。</p>
<h3 id="環境変数の設定"><a href="#%E7%92%B0%E5%A2%83%E5%A4%89%E6%95%B0%E3%81%AE%E8%A8%AD%E5%AE%9A">環境変数の設定</a></h3>
<p>まずは環境変数の設定。</p>
<p><a href="https://crieit.now.sh/upload_images/57a8cc2a08598bf78b631bbd9da2a024612a5842798b2.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/57a8cc2a08598bf78b631bbd9da2a024612a5842798b2.jpg?mw=700" alt="環境変数の設定" /></a></p>
<p>プロジェクトを選択後、「Settings」から「Enviroment Variables」へ。</p>
<p>「NAME」にコードに記載したキーの名前を付けて、実際の値を入力します。画面では APIキー なので上述の microCMS の管理画面で控えた APIキー を入力。</p>
<p><a href="https://crieit.now.sh/upload_images/3bbfd322b71fb32df23894afdd5853d5612a584583337.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/3bbfd322b71fb32df23894afdd5853d5612a584583337.jpg?mw=700" alt="環境変数の設定2" /></a></p>
<p>他、必要な変数をセットします。</p>
<h3 id="Deploy Hooks を登録"><a href="#Deploy+Hooks+%E3%82%92%E7%99%BB%E9%8C%B2">Deploy Hooks を登録</a></h3>
<p>次に Deploy Hooks をひっかけます。</p>
<p>プロジェクトの「Settings」から今度は「Git」へ。</p>
<p><a href="https://crieit.now.sh/upload_images/4f89b78a73ad66c2fab07245a0b599ac612a58482a821.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/4f89b78a73ad66c2fab07245a0b599ac612a58482a821.jpg?mw=700" alt="Deploy hooks" /></a></p>
<p>Deploy Hooks に名前を入力、ブランチは通常は <code>main</code> になるかと。</p>
<p><a href="https://crieit.now.sh/upload_images/792d34407a2e1061c785101139250868612a584aeed86.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/792d34407a2e1061c785101139250868612a584aeed86.jpg?mw=700" alt="Deploy Hooks を控える" /></a></p>
<p>登録されたら Hook の URL を控えます。</p>
<h2 id="microCMS の設定"><a href="#microCMS+%E3%81%AE%E8%A8%AD%E5%AE%9A">microCMS の設定</a></h2>
<p>お次は microCMS の画面へ。</p>
<p><a href="https://crieit.now.sh/upload_images/16478a5b69bd9cb593abea925cd2c925612a584d45b74.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/16478a5b69bd9cb593abea925cd2c925612a584d45b74.jpg?mw=700" alt="Webhook" /></a></p>
<p>サービスの管理画面から「API設定」→「Webhook」へ。</p>
<p><a href="https://crieit.now.sh/upload_images/192e10d26803bfa0dcf31470a2553f63612a58505802c.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/192e10d26803bfa0dcf31470a2553f63612a58505802c.jpg?mw=700" alt="カスタム通知" /></a></p>
<p>Vercel は一覧にはないので「カスタム通知」を選択。</p>
<p><a href="https://crieit.now.sh/upload_images/b93547fbc6ca4f11e11986ec1869d7d5612a5853d80e0.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/b93547fbc6ca4f11e11986ec1869d7d5612a5853d80e0.jpg?mw=700" alt="Vercel の Hook を設定" /></a></p>
<p>名前は任意の名前を。</p>
<p>Hook の URL に先ほど控えた URL を入力します。</p>
<p><a href="https://crieit.now.sh/upload_images/39693fd99f7447504a37a4bfd38afea0612a58568376c.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/39693fd99f7447504a37a4bfd38afea0612a58568376c.jpg?mw=700" alt="Hook の権限" /></a></p>
<p>権限はこのような感じ。基本的に公開されているデータに変更が加わったら Hook が通知を行うものとします。</p>
<h2 id="テスト投稿"><a href="#%E3%83%86%E3%82%B9%E3%83%88%E6%8A%95%E7%A8%BF">テスト投稿</a></h2>
<p><a href="https://crieit.now.sh/upload_images/58704ee832c977a18796e1a3e05c2c8f612a5859db3dd.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/58704ee832c977a18796e1a3e05c2c8f612a5859db3dd.jpg?mw=700" alt="記事を試しに追加" /></a></p>
<p>ここまで設定できたら、試しに記事を新しく追加してみます。</p>
<p><a href="https://crieit.now.sh/upload_images/b79d4f2666aaa6c98f4c010011c12e6f612a585d5f4c4.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/b79d4f2666aaa6c98f4c010011c12e6f612a585d5f4c4.jpg?mw=700" alt="Vercel 側が反応" /></a></p>
<p>すると、 Vercel 側でプロジェクトが反応してビルドが走り始めました。</p>
<p><a href="https://crieit.now.sh/upload_images/75c7890bf380c4b476fea57535096623612a586141166.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/75c7890bf380c4b476fea57535096623612a586141166.jpg?mw=700" alt="デプロイ完了" /></a></p>
<p>microCMS に記事を追加すると、 Github のリポジトリに push することなく勝手にビルドが走ってサイトが更新されることが確認できました。</p>
<p>これで Gatsby.js + Vercel + microCMS で JAMStack なブログの仕組みが構築できました。実験成功です。</p>
<h2 id="参考"><a href="#%E5%8F%82%E8%80%83">参考</a></h2>
<h3 id="改修"><a href="#%E6%94%B9%E4%BF%AE">改修</a></h3>
<ul>
<li><a target="_blank" rel="nofollow noopener" href="https://zenn.dev/k1_style/scraps/07cce0dd3611e3">Gatsby + microcms + Vercel でブログを作って公開したい</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://www.gatsbyjs.com/plugins/gatsby-source-microcms/">gatsby-source-microcms | Gatsby</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://zenn.dev/rokki188/articles/948d53199508c7">microCMS + Next.js でJamStackブログを作ってみた</a></li>
</ul>
<h3 id="コード、GraphQL、microCMSの設定、環境変数"><a href="#%E3%82%B3%E3%83%BC%E3%83%89%E3%80%81GraphQL%E3%80%81microCMS%E3%81%AE%E8%A8%AD%E5%AE%9A%E3%80%81%E7%92%B0%E5%A2%83%E5%A4%89%E6%95%B0">コード、GraphQL、microCMSの設定、環境変数</a></h3>
<ul>
<li><a target="_blank" rel="nofollow noopener" href="https://blog.microcms.io/microcms-next-jamstack-blog/">microCMS + Next.jsでJamstackブログを作ってみよう | microCMSブログ</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://blog.microcms.io/gatsby-microcms-media/">GatsbyJS + microCMSでJamstackなオウンドメディアを作ろう | microCMSブログ</a></li>
</ul>
<h3 id="Vercel の環境変数"><a href="#Vercel+%E3%81%AE%E7%92%B0%E5%A2%83%E5%A4%89%E6%95%B0">Vercel の環境変数</a></h3>
<ul>
<li><a target="_blank" rel="nofollow noopener" href="https://vercel.com/docs/environment-variables">Vercel – Environment Variables - Vercel Documentation</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://www.snorerelax.com/posts/tech-vercel-environment/">Vercelで環境変数を設定する | Next.js Blog Example with すのりら</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/Slowhand0309/items/f954237520d343fa9e4c">Vercelで設定した環境変数をNext.jsで使用する - Qiita</a></li>
</ul>
<h4 id="環境変数の分かち書き"><a href="#%E7%92%B0%E5%A2%83%E5%A4%89%E6%95%B0%E3%81%AE%E5%88%86%E3%81%8B%E3%81%A1%E6%9B%B8%E3%81%8D">環境変数の分かち書き</a></h4>
<ul>
<li><a target="_blank" rel="nofollow noopener" href="https://blog.gaji.jp/2020/06/09/4030/">GatsbyJSで開発環境にのみページを存在させる方法 ++ Gaji-Laboブログ</a></li>
</ul>
<h3 id="gatsby-plugin-feed"><a href="#gatsby-plugin-feed">gatsby-plugin-feed</a></h3>
<ul>
<li><a target="_blank" rel="nofollow noopener" href="https://www.gatsbyjs.com/plugins/gatsby-plugin-feed/">gatsby-plugin-feed | Gatsby</a></li>
</ul>
<p>基本 Gatsby.js のプラグインのページはシンプルなサンプルなので <code>http://localhost:8000/___graphql</code> で GraphQL を試して感覚をつかむ方が早かった気がします。</p>
arm-band
tag:crieit.net,2005:PublicArticle/17615
2021-08-25T22:14:35+09:00
2021-08-29T20:33:12+09:00
https://crieit.net/posts/publish-blog-by-gatsvyjs-vercel-20210825
Gatsby.js + Vercel でブログを作ってみる
<p>兼ねてより試してみたかった Gatsby.js + Vercel の組み合わせに着手してみました。</p>
<h2 id="1. Gatsby.js のインストールと Gitリポジトリ の準備"><a href="#1.+Gatsby.js+%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E3%81%A8+Git%E3%83%AA%E3%83%9D%E3%82%B8%E3%83%88%E3%83%AA+%E3%81%AE%E6%BA%96%E5%82%99">1. Gatsby.js のインストールと Gitリポジトリ の準備</a></h2>
<p>まずは Gatsby.js のプロジェクトを作って Gitホスティングサービス に push します。</p>
<pre><code class="bash">> yarn init
## 略
success Saved package.json
Done in 2.33s.
</code></pre>
<p>適当なディレクトリで <code>package.json</code> を生成。</p>
<pre><code class="bash">> yarn add gatsby-cli
## 略
Done in 26.05s.
</code></pre>
<p>続いて <code>gatsby-cli</code> をインストールします。一応グローバルではなくローカルで。</p>
<ul>
<li><a target="_blank" rel="nofollow noopener" href="https://www.gatsbyjs.com/static/203f352fa59959029a106ffe821ad0bb/85e35/93d59e2b139dc14ee2118ff7410333c9.webp">: Gatsby Starter | Gatsby</a></li>
</ul>
<p>今回のテーマはこれにします。</p>
<pre><code class="bash">> gatsby new mptotkb https://github.com/renyuanz/leonids
╔════════════════════════════════════════════════════════════════════════╗
║ ║
║ Gatsby collects anonymous usage analytics ║
║ to help improve Gatsby for all users. ║
║ ║
║ If you'd like to opt-out, you can use `gatsby telemetry --disable` ║
║ To learn more, checkout https://gatsby.dev/telemetry ║
║ ║
╚════════════════════════════════════════════════════════════════════════╝
info Creating new site from git: https://github.com/renyuanz/leonids.git
Cloning into 'mptotkb'...
remote: Enumerating objects: 60, done.
remote: Counting objects: 100% (60/60), done.
remote: Compressing objects: 100% (44/44), done.
Receiving objects: 100% (60/60), 542.69 KiB | 5.32 MiB/s, done.eceiving objects: 100% (60/60)
success Created starter directory layout
info Installing packages...
info Preferred package manager set to "npm"
## 略
Your new Gatsby site has been successfully bootstrapped. Start developing it by running:
cd mptotkb
gatsby develop
</code></pre>
<p>プロジェクト作成完了。</p>
<pre><code class="bash">> cd mptotkb
> gatsby develop
## 略
info
Hi from the Gatsby maintainers! Based on what we see in your site, these coming
features may help you. All of these can be enabled within gatsby-config.js via
flags (samples below)
Preserve webpack's Cache (https://github.com/gatsbyjs/gatsby/discussions/28331), which changes Gatsby's cache clearing behavior to not clear webpack's
cache unless you run "gatsby clean" or delete the .cache folder manually.
Here's how to try it:
module.exports = {
flags: { PRESERVE_WEBPACK_CACHE: true },
plugins: [...]
}
⠀
You can now view gatsby-starter-leonids 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 - 48.261s
</code></pre>
<p>OK。完了しました。</p>
<p>最初は手始めということでこの状態でいったん push しておきたいと思います。 Gitリポジトリ に登録するのは親ディレクトリではなく作成したプロジェクト (今回は <code>mptotkb</code> 下) です。</p>
<p><a href="https://crieit.now.sh/upload_images/c767731cd51656a0324d46f4f80e7af261263f776ecdc.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/c767731cd51656a0324d46f4f80e7af261263f776ecdc.jpg?mw=700" alt="GitHub でリポジトリを作成" /></a></p>
<p>GitHub でリポジトリを作成して、このリポジトリに先ほどのプロジェクトを push 。ちなみにリポジトリは public である必要があります。</p>
<h2 id="2. Vercel と Gitホスティングサービス の連携"><a href="#2.+Vercel+%E3%81%A8+Git%E3%83%9B%E3%82%B9%E3%83%86%E3%82%A3%E3%83%B3%E3%82%B0%E3%82%B5%E3%83%BC%E3%83%93%E3%82%B9+%E3%81%AE%E9%80%A3%E6%90%BA">2. Vercel と Gitホスティングサービス の連携</a></h2>
<p>次に Vercel でアカウントを作ります。</p>
<p><a href="https://crieit.now.sh/upload_images/77ce0ff86a6de3b873bb06d7f1de0c8e61263f822ba39.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/77ce0ff86a6de3b873bb06d7f1de0c8e61263f822ba39.jpg?mw=700" alt="Vercel で Sign Up をクリック" /></a></p>
<p>Sign Up をクリック。</p>
<p><a href="https://crieit.now.sh/upload_images/43666c5f16041fc59fdb8d593a9b955561263f8d448dd.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/43666c5f16041fc59fdb8d593a9b955561263f8d448dd.jpg?mw=700" alt="GitHub と連携" /></a></p>
<p>今回は GitHub を使用しているので「Continue with GitHub」を選択。</p>
<p><a href="https://crieit.now.sh/upload_images/1f94d557606bdff1448bcb340a9d56b861263f98c6f6f.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/1f94d557606bdff1448bcb340a9d56b861263f98c6f6f.jpg?mw=700" alt="Vercel のアクセスを認証して権限を付与" /></a></p>
<p>「Authorize Vercel」で Vercel のアクセスを認証します。</p>
<p><a href="https://crieit.now.sh/upload_images/0e40bf8259a51bb7dea9189426fb3f5961263faa0614f.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/0e40bf8259a51bb7dea9189426fb3f5961263faa0614f.jpg?mw=700" alt="Vercel にログイン成功" /></a></p>
<p>ログインできました。</p>
<h2 id="3. リポジトリのインポート"><a href="#3.+%E3%83%AA%E3%83%9D%E3%82%B8%E3%83%88%E3%83%AA%E3%81%AE%E3%82%A4%E3%83%B3%E3%83%9D%E3%83%BC%E3%83%88">3. リポジトリのインポート</a></h2>
<p><a href="https://crieit.now.sh/upload_images/9b1b79698c430d0d958f3d770e4c62bf61263fbda9d17.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/9b1b79698c430d0d958f3d770e4c62bf61263fbda9d17.jpg?mw=700" alt="ダッシュボードから「New Project」" /></a></p>
<p>一度中断してしまったのでダッシュボードから。ここからであれば「New Project」で次へ進みます。</p>
<p><a href="https://crieit.now.sh/upload_images/490785baeef1275ccb89cdb6d4a5db7861263fc869e4e.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/490785baeef1275ccb89cdb6d4a5db7861263fc869e4e.jpg?mw=700" alt="Import Git Repository から「Add GitHub Org or Account」" /></a></p>
<p>Import Git Repository から「Add GitHub Org or Account」。</p>
<p><a href="https://crieit.now.sh/upload_images/92eb299d6668bdba87d40c089976f9fc61263fd566948.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/92eb299d6668bdba87d40c089976f9fc61263fd566948.jpg?mw=700" alt="インポートするリポジトリを選択" /></a></p>
<p>インポートするリポジトリを選択します。今回は1つのリポジトリだけに Vercel に連携させます。</p>
<p><a href="https://crieit.now.sh/upload_images/95606ef51dd06912c5fe460301a1d09361263fe080aa9.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/95606ef51dd06912c5fe460301a1d09361263fe080aa9.jpg?mw=700" alt="リポジトリの確認" /></a></p>
<p>リポジトリの確認です。使用しているフレームワークが自動判別されるのはありがたいですね。</p>
<p><a href="https://crieit.now.sh/upload_images/676cf8e4e4edee1f6c692cd0a445524e61263fea8e98f.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/676cf8e4e4edee1f6c692cd0a445524e61263fea8e98f.jpg?mw=700" alt="チームの作成は「Skip」" /></a></p>
<p>次の画面でフローに沿って設定を進めていきます。最初に Vercel のチームを作成する画面が有効になっていますが、今回は個人なので「Skip」。</p>
<p><a href="https://crieit.now.sh/upload_images/fa75aa33dba45c6b8029ab0a0a3695bc61263ff3507ed.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/fa75aa33dba45c6b8029ab0a0a3695bc61263ff3507ed.jpg?mw=700" alt="Configure Project" /></a></p>
<p>プロジェクトの設定。出力の設定や環境変数を設定できますが、今回はそのままで。</p>
<p><a href="https://crieit.now.sh/upload_images/64a16b6c3867805df977e0ac9704d57361263ffb9d76a.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/64a16b6c3867805df977e0ac9704d57361263ffb9d76a.jpg?mw=700" alt="デプロイ中" /></a></p>
<p>デプロイ中。</p>
<p><a href="https://crieit.now.sh/upload_images/eb14aeca4ce6114b32dd4f90697d064361264004d26ec.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/eb14aeca4ce6114b32dd4f90697d064361264004d26ec.jpg?mw=700" alt="デプロイされた画面を実際に確認" /></a></p>
<p>少し待つとデプロイが完了します。そこでURLから実際の画面を表示させると……きちんとデプロイされていました!</p>
<p>ここまでで Gatsby.js + Vercel でブログを作成することができました。</p>
<p>今後の課題としては以下の通り。</p>
<ul>
<li>サイト名や著者情報といった基本情報のカスタマイズ</li>
<li>どうやらブログ記事の Markdown ファイルを生成する CLI やユーティリティはなさそうで、手作業で記事をちまちま作っていくのは手間なので記事リソースを別の場所 (<a href="https://crieit.net/posts/gatsby-vercel-microcms-cooprate-20210829-1">Headless CMS</a> とか) で管理して <a href="https://crieit.net/posts/gatsby-vercel-microcms-cooprate-20210829-2">JAMStack にする</a></li>
</ul>
<p>あとは折角なので GraphQL にも少しは触ってみたいところですね。</p>
<h2 id="参考"><a href="#%E5%8F%82%E8%80%83">参考</a></h2>
<h3 id="Gatsby.js + Vercel"><a href="#Gatsby.js+%2B+Vercel">Gatsby.js + Vercel</a></h3>
<ul>
<li><a target="_blank" rel="nofollow noopener" href="https://webcraftlog.net/gatsbyjs-site-deploy-to-vercel/">【ZEIT Now】Gatsbyサイトを無料サーバーVercelで公開する方法を徹底解説 | WebCraftLog</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://zenn.dev/k1_style/scraps/07cce0dd3611e3">Gatsby + microcms + Vercel でブログを作って公開したい</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://vercel.com/docs/git">Vercel – Git - Vercel Documentation</a>
<ul>
<li>参考記事とは画面構成が変わっていたため、最終的には Vercel のドキュメントが頼りでした</li>
</ul></li>
</ul>
<h3 id="Gatsby.js のテーマ"><a href="#Gatsby.js+%E3%81%AE%E3%83%86%E3%83%BC%E3%83%9E">Gatsby.js のテーマ</a></h3>
<ul>
<li><a target="_blank" rel="nofollow noopener" href="https://www.gatsbyjs.com/starters/?c=Blog">Gatsby Starters: Library | Gatsby</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://www.gatsbyjs.com/starters/renyuanz/leonids">: Gatsby Starter | Gatsby</a></li>
</ul>
<h3 id="Vercel"><a href="#Vercel">Vercel</a></h3>
<ul>
<li><a target="_blank" rel="nofollow noopener" href="https://dev.classmethod.jp/articles/vercel/">NetlifyキラーのVercelでウェブサイトをホストしたら簡単すぎて笑顔になった | DevelopersIO</a></li>
</ul>
<h3 id="Gatsby.js"><a href="#Gatsby.js">Gatsby.js</a></h3>
<ul>
<li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/k-penguin-sato/items/7554e5e7e90aa10ae225">GatsbyとNetlifyで簡単にブログを作成 - Qiita</a></li>
</ul>
arm-band
tag:crieit.net,2005:PublicArticle/16694
2021-02-20T15:13:23+09:00
2021-02-20T15:13:43+09:00
https://crieit.net/posts/Netlify-GitHub-Actions-0
Netlifyのビルド時間をGitHub Actionsで0時間にして月末のヒヤヒヤから解放されよう!
<h1 id="Netlifyのビルド時間をGitHub Actionsで0時間にして月末のヒヤヒヤから解放されよう!"><a href="#Netlify%E3%81%AE%E3%83%93%E3%83%AB%E3%83%89%E6%99%82%E9%96%93%E3%82%92GitHub+Actions%E3%81%A70%E6%99%82%E9%96%93%E3%81%AB%E3%81%97%E3%81%A6%E6%9C%88%E6%9C%AB%E3%81%AE%E3%83%92%E3%83%A4%E3%83%92%E3%83%A4%E3%81%8B%E3%82%89%E8%A7%A3%E6%94%BE%E3%81%95%E3%82%8C%E3%82%88%E3%81%86%EF%BC%81">Netlifyのビルド時間をGitHub Actionsで0時間にして月末のヒヤヒヤから解放されよう!</a></h1>
<h2 id="Netlify"><a href="#Netlify">Netlify</a></h2>
<p>みなさんもご存じ超便利ありがたサービスNetlifyですが、<strong>無料で使ってる貧民</strong>には毎月とある悩みがでてきます。</p>
<p><em>今月のビルド時間は残り○○分</em></p>
<p><img src="https://i.imgur.com/TSm24w0.png" alt="img" /></p>
<p>NetlifyはGitHubのレポジトリと連携して、フロントのビルドを実行した上で、デプロイするという超便利機能があるのですが、このビルドを回すのに時間の制約があり、</p>
<p>無料民だと月300分となっております。(それ以上はPro版月19ドル課金すれば問題なく使えます。課金も経験済み)</p>
<p>300分あれば大丈夫そう、とそう思う気もしなくなくもないですが、</p>
<p>複数レポジトリにわたってNetlifyを使っていたり、Gatsby.jsで画像をたくさん使っていて<strong>Sharp</strong>の画像リサイズに時間がかかったり、<strong>Dependabot</strong>で定期的にPRが出てPreview deployが発生したりすると<br />
案外ぎりぎりだったりします。</p>
<p><img src="https://i.imgur.com/y7ixbEG.png" alt="img" /></p>
<p>なので、私のような貧民は月末になると、Netlifyのビルド時間が気になって<strong>このブログの記事を書かなくなったり</strong>、<strong>サイトリファクターのペースが落ちて</strong>しまいます。</p>
<p>特にブログ更新は顕著で、例えば今書いている記事も通勤の電車の中でスマホから書いているわけなので、細かくコミットを打って保存したいのですが、コミットを打ってプッシュしてしまうと、ビルドが走ることになるので、WIPでのコミットが億劫になり、結果的に家のようなまとめてプッシュできるような作業スペースがある場所でないと、<br />
ブログを書かなくなってしまいました。</p>
<p>せっかく<a target="_blank" rel="nofollow noopener" href="https://blog.tubone-project24.xyz/2019-09-01-netlify-and-gatsby#cms%E3%81%AE%E7%AE%A1%E7%90%86%E7%94%BB%E9%9D%A2%E3%82%92%E8%A8%AD%E5%AE%9A%E3%81%99%E3%82%8B">Netlify CMS化</a>した意味がないですね。</p>
<h2 id="この悩みGitHub Actionsにお任せください"><a href="#%E3%81%93%E3%81%AE%E6%82%A9%E3%81%BFGitHub+Actions%E3%81%AB%E3%81%8A%E4%BB%BB%E3%81%9B%E3%81%8F%E3%81%A0%E3%81%95%E3%81%84">この悩みGitHub Actionsにお任せください</a></h2>
<p>ということでこの悩み、GitHub Actionsで解決してみたいと思います。</p>
<p>なんか工務店のCMみたいな表現になってしまいました。</p>
<p><img src="https://i.imgur.com/JlvUJ4zl.png" alt="ojisan" /></p>
<h2 id="Netlifyのビルド時やっていることを洗い出して自前でやってみる"><a href="#Netlify%E3%81%AE%E3%83%93%E3%83%AB%E3%83%89%E6%99%82%E3%82%84%E3%81%A3%E3%81%A6%E3%81%84%E3%82%8B%E3%81%93%E3%81%A8%E3%82%92%E6%B4%97%E3%81%84%E5%87%BA%E3%81%97%E3%81%A6%E8%87%AA%E5%89%8D%E3%81%A7%E3%82%84%E3%81%A3%E3%81%A6%E3%81%BF%E3%82%8B">Netlifyのビルド時やっていることを洗い出して自前でやってみる</a></h2>
<p>基本的にNetlifyがビルド時やってることは、例えばGatsby.jsであれば、gatsby buildコマンドを実行し、特定のディレクトリー(大概は./public)に配置されたビルド済みJSをデプロイする動きなので、<br />
それをそっくりGitHub Actionsに移行すればいいのですが、Netlifyがビルド済みJSに対して後処理(PostProcess)を実行してるパターンもあります。</p>
<p>私の場合、JSやイメージを最適化してくれる<strong>Asset optimization</strong>とFormタグに属性をつければ勝手にFormを作ってくれる<strong>Form detection</strong>の二つが設定されていましたのでそれぞれまず無効化します。</p>
<p>Form detectionの解説は<a target="_blank" rel="nofollow noopener" href="https://blog.tubone-project24.xyz/2019/09/30/netlify-form">こちら</a>を参照ください。</p>
<p><img src="https://i.imgur.com/ytjbJQA.png" alt="img" /></p>
<p><img src="https://i.imgur.com/LfL70Br.png" alt="img" /></p>
<p>こちら、Netlifyで実施してくれなくなりますので、こちらで実装し直す必要があります。</p>
<h2 id="gatsby-plugin-minify"><a href="#gatsby-plugin-minify">gatsby-plugin-minify</a></h2>
<p>Asset optimizationのうち、JSやCSSのminiferは<a target="_blank" rel="nofollow noopener" href="https://www.gatsbyjs.com/plugins/gatsby-plugin-minify/">gatsby-plugin-minify</a>を使うことでhtmlやJS、CSSをminifyできます。</p>
<p>インストールはいつも通りNPM(yarn)から</p>
<pre><code>npm install gatsby-plugin-minify
</code></pre>
<p>使い方はgatsby-config.jsのpluginsに次のように設定すればできます。</p>
<pre><code> {
resolve: 'gatsby-plugin-minify',
options: {
caseSensitive: false,
collapseBooleanAttributes: true,
useShortDoctype: false,
removeEmptyElements: false,
removeComments: true,
removeAttributeQuotes: false,
minifyCSS: true,
minifyJS: true,
},
},
</code></pre>
<p>minifyCSSとminifyJSをtrueにすることにより、CSSについては<a target="_blank" rel="nofollow noopener" href="https://github.com/jakubpawlowicz/clean-css">clean-css</a>、JSについては<a target="_blank" rel="nofollow noopener" href="https://github.com/mishoo/UglifyJS">UglifyJS</a>を使って一緒にminifyされます。また、gatsby-plugin-minifyの裏側は<a target="_blank" rel="nofollow noopener" href="https://github.com/kangax/html-minifier">html-minifier</a>をgatsby-node.jsでpostbuildで全掛けしているだけなので、細かいオプションは<a target="_blank" rel="nofollow noopener" href="https://github.com/kangax/html-minifier#options-quick-reference">html-minifier</a>で設定できる感じです。</p>
<p>ちなみに、気を付けないといけないのが<strong>removeAttributeQuotes</strong>のオプションをfalseにすること。</p>
<p>これをtrueにすると、HTMLタグ内のアトリビュートにダブルクオートが入らなくなりちょっとファイルが軽くなるのですが、<a target="_blank" rel="nofollow noopener" href="https://berss.com/feed/Find.aspx">berss.com</a>のようにサイトのRSSリンクを取得するようなシステムでうまく読み込めなくなってしまい、サイト更新が最悪通知できなくなってしまう現象が発生しました。</p>
<p>これで1日使ってしまった...。</p>
<p>RSSのリンクをページのLinkとして仕込んでいる人は要注意です。</p>
<h2 id="imgurを使うことで、画像ホスティングとリサイズを同時にやっちゃう"><a href="#imgur%E3%82%92%E4%BD%BF%E3%81%86%E3%81%93%E3%81%A8%E3%81%A7%E3%80%81%E7%94%BB%E5%83%8F%E3%83%9B%E3%82%B9%E3%83%86%E3%82%A3%E3%83%B3%E3%82%B0%E3%81%A8%E3%83%AA%E3%82%B5%E3%82%A4%E3%82%BA%E3%82%92%E5%90%8C%E6%99%82%E3%81%AB%E3%82%84%E3%81%A3%E3%81%A1%E3%82%83%E3%81%86">imgurを使うことで、画像ホスティングとリサイズを同時にやっちゃう</a></h2>
<p><a target="_blank" rel="nofollow noopener" href="https://imgur.com/">imgur</a>というサービスがあります。</p>
<p>主にRedditとかGifをあげるための画像ホスティングサービスとして有名なのですが、こちらを使うことで簡単に画像のリサイズとホスティングを実現できるため、このブログではimgurを使ってます。</p>
<p>画像URLの後ろに画像サイズに合わせたキーワードを入れることで実現できます。</p>
<p>例えばこちらのURLの画像を</p>
<pre><code>[https://i.imgur.com/Wfz9G0B.png](https://i.imgur.com/Wfz9G0B.png)
</code></pre>
<p>160x160にリサイズするには後ろに<strong>b</strong>をくっつけます。</p>
<pre><code>[https://i.imgur.com/Wfz9G0Bb.png](https://i.imgur.com/Wfz9G0Bb.png)
</code></pre>
<p>これで、画像最適化も完了です。</p>
<h2 id="getform.io"><a href="#getform.io">getform.io</a></h2>
<p><a target="_blank" rel="nofollow noopener" href="https://getform.io/">Getform.io</a>はフォームのバックエンドを提供するすばらしいサービスです。</p>
<p>便利なインテグレーションを使うには有料版が必要ですが、フォームに投稿されたら指定したメールアドレスに通知メール飛ばす、くらいのことであれば無料でできます。</p>
<p>これで、NetlifyのForm detectionを置き換えていきます。</p>
<p>まず、新しいフォームを作ると、FormのAction先URLが発行できます。</p>
<p>Formの作り方は下記のブログにわかりやすく纏めてあったので参照いただければと思います。</p>
<p><a target="_blank" rel="nofollow noopener" href="https://blog.nakamu.life/posts/getform-io">https://blog.nakamu.life/posts/getform-io</a></p>
<p>さて、Formができたらチュートリアルに沿ってそのまま、FormタグのactionにこちらのURLを設定してもいいのですが、GetFormは無料版だと、<strong>Form投稿後のThanksページが設定</strong>できません。</p>
<pre><code class="html"><!--
* Add your getform endpoint into "action" attribute
* Set a unique "name" field
* Start accepting submissions
-->
<form action="{getform-endpoint}" method="POST">
<input type="text" name="name">
<input type="email" name="email">
<button type="submit">Send</button>
</form>
</code></pre>
<p><img src="https://i.imgur.com/sT5vhFE.png" alt="img" /></p>
<p>まぁこれでも十分なのですが、せっかく<strong>React</strong>を使ってるので、裏側でgetform.ioのURLをPOST fetchしながら、actionsで定義した自分のThanks URLに飛ばすように指定しましょう。</p>
<p>まずは、Formに<strong>onSubmit</strong>を設定します。</p>
<p>```typescript{numberLines: 1}{5}<br />
<form
name="contact"
method="post"
action="/thanks/"
onSubmit={this.handleSubmit}
><br />
<label><br />
<span className="icon-user" /> Your name<br /><br />
<input
type="text"
name="name"
className="form-control"
maxLength="30"
minLength="2"
required
placeholder="Enter your name"
onChange={this.handleChange}
/><br />
</label><br />
</p></p>
<pre><code><br />そして、別途にonSubmitで発火する関数を定義します。
```typescript
handleSubmit(e) {
e.preventDefault();
const form = e.target;
fetch('https://getform.io/f/xxxxxxxxxxxxxxxxxxxxxxxxx', {
method: 'POST',
body: Contact.encode({
'form-name': form.getAttribute('name'),
...this.state,
}),
})
}
</code></pre>
<p>Formの送信なので、fetchでは<a target="_blank" rel="nofollow noopener" href="https://developer.mozilla.org/ja/docs/Web/API/FormData">FormData</a>に要素をappendしたものを送信しないといけません。</p>
<pre><code> static encode(data) {
const formData = new FormData();
// eslint-disable-next-line no-restricted-syntax
for (const key of Object.keys(data)) {
formData.append(key, data[key]);
}
return formData;
}
</code></pre>
<p>繰り返しになりますがReactではFormで、actionのほか、onSubmitを関数としてすることができます。</p>
<p>ただし、onSubmitが押されたタイミングで、Formの入力項目をPOST Fetchで渡さないといけないので、Formの入力で発生するchangeEventごとに、Formの値をstateとして保存しておくようにします。</p>
<p>```typescript{numberLines: 1}{1-7,21}<br />
handleChange(e) {<br />
this.setState({ [e.target.name]: e.target.value });<br />
}</p>
<p>handleAttachment(e) {<br />
this.setState({ [e.target.name]: e.target.files[0] });<br />
}</p>
<p>(中略)</p>
<pre><code> <label>
<span className="icon-user" /> Your name<br />
<input
type="text"
name="name"
className="form-control"
maxLength="30"
minLength="2"
required
placeholder="Enter your name"
onChange={this.handleChange}
/>
</label>
</p>
</code></pre>
<pre><code><br />また、onSubmitを使ってしまうと、Form規定のactionでは飛ばなくなるので自前でGatsbyのnavigateを使ってPost処理が終わったらThanksページに飛ぶようにします。
```typescript{numberLines: 1}{11-12}
handleSubmit(e) {
e.preventDefault();
const form = e.target;
fetch('https://getform.io/f/897f187e-876d-42a7-b300-7c235af72e6d', {
method: 'POST',
body: Contact.encode({
'form-name': form.getAttribute('name'),
...this.state,
}),
})
.then(() => navigateTo(form.getAttribute('action')))
.catch((error) => alert(error));
}
</code></pre>
<p>これでGetForm無料版でも自前のThanksページを作ることができます。</p>
<p><img src="https://i.imgur.com/gumRkbF.png" alt="img" /></p>
<h2 id="GitHub Actionsでビルドとデプロイ"><a href="#GitHub+Actions%E3%81%A7%E3%83%93%E3%83%AB%E3%83%89%E3%81%A8%E3%83%87%E3%83%97%E3%83%AD%E3%82%A4">GitHub Actionsでビルドとデプロイ</a></h2>
<p>ここまで来たらあとはGitHub Actionsでビルドとデプロイを行うだけです。</p>
<p>masterブランチへのPRでPreviewデプロイ、masterへのコミットで本番デプロイをするように2つactionsを作ります。</p>
<p>まずはPreviewデプロイ</p>
<pre><code class="yaml">name: DeployToNetlifyPreview
on:
pull_request:
branches:
- master
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout source code
uses: actions/checkout@v2
- name: Cache node_modules
uses: actions/cache@v1
with:
path: node_modules
key: $<span>{</span><span>{</span> runner.OS <span>}</span><span>}</span>-build-$<span>{</span><span>{</span> hashFiles('**/package-lock.json') <span>}</span><span>}</span>
restore-keys: |
$<span>{</span><span>{</span> runner.OS <span>}</span><span>}</span>-build-
$<span>{</span><span>{</span> runner.OS <span>}</span><span>}</span>
- name: Setup Node
uses: actions/setup-node@v1
with:
node-version: 12.x
- name: npm install and build
env:
GATSBY_GITHUB_CLIENT_SECRET: $<span>{</span><span>{</span>secrets.GATSBY_GITHUB_CLIENT_SECRET<span>}</span><span>}</span>
GATSBY_GITHUB_CLIENT_ID: $<span>{</span><span>{</span>secrets.GATSBY_GITHUB_CLIENT_ID<span>}</span><span>}</span>
GATSBY_ALGOLIA_SEARCH_API_KEY: $<span>{</span><span>{</span>secrets.GATSBY_ALGOLIA_SEARCH_API_KEY<span>}</span><span>}</span>
GATSBY_ALGOLIA_INDEX_NAME: $<span>{</span><span>{</span>secrets.GATSBY_ALGOLIA_INDEX_NAME<span>}</span><span>}</span>
GATSBY_ALGOLIA_APP_ID: $<span>{</span><span>{</span>secrets.GATSBY_ALGOLIA_APP_ID<span>}</span><span>}</span>
GATSBY_ALGOLIA_ADMIN_API_KEY: $<span>{</span><span>{</span>secrets.GATSBY_ALGOLIA_ADMIN_API_KEY<span>}</span><span>}</span>
FAUNADB_SERVER_SECRET: $<span>{</span><span>{</span>secrets.FAUNADB_SERVER_SECRET<span>}</span><span>}</span>
run: |
npm install
npm run build
- name: Deploy to netlify
run: npx netlify-cli deploy --dir=./public > cli.txt
env:
NETLIFY_AUTH_TOKEN: $<span>{</span><span>{</span> secrets.NETLIFY_AUTH_TOKEN <span>}</span><span>}</span>
NETLIFY_SITE_ID: $<span>{</span><span>{</span> secrets.NETLIFY_SITE_ID <span>}</span><span>}</span>
- name: Cat cli.txt
run: |
cat cli.txt
sed -i -z 's/\n/\\n/g' cli.txt
- name: Post Netlify CLI Comment
env:
GITHUB_TOKEN: $<span>{</span><span>{</span> secrets.GITHUB_TOKEN <span>}</span><span>}</span>
URL: $<span>{</span><span>{</span> github.event.pull_request.comments_url <span>}</span><span>}</span>
run: |
curl -X POST \
-H "Authorization: token ${GITHUB_TOKEN}" \
-d "{\"body\": \"$(cat cli.txt)\"}" \
${URL}
</code></pre>
<p>node setupやnpm install, buildはいつも通りです。</p>
<p>GitHub ActionsではSecretを指定することができますので、Algolia searchやFaunaDBのAPIキーはシークレットとしてビルド時の環境変数で渡してます。</p>
<p>ちなみに、環境変数で<strong>GATSBY_XXXX</strong>としておくと、ビルドされたJSにも環境変数が入る形になります。(JSから環境変数を使う場合はこれを忘れないこと。)これ結構詰まるポイント。</p>
<p>デプロイには<a target="_blank" rel="nofollow noopener" href="https://docs.netlify.com/cli/get-started/">netlify-cli</a>を使います。</p>
<p>必要な環境変数はサイトIDとAUTH TOKENです。</p>
<p>ちょっと特徴として、netlify-cliでデプロイが成功すると、<strong>デプロイURLが標準出力</strong>に出ますので、それをいったん適当なtextファイルに書き出し、</p>
<p>PRコメントにもURLを送るようにしています。</p>
<p>GitHub Actionsの素晴らしいところは、GITHUB TOKENについては、特に設定しなくてもsecrets.GITHUB_TOKENで取り出すことができますので簡単にPRコメントに送信できます。</p>
<pre><code class="yaml"> - name: Deploy to netlify
run: npx netlify-cli deploy --dir=./public > cli.txt
env:
NETLIFY_AUTH_TOKEN: $<span>{</span><span>{</span> secrets.NETLIFY_AUTH_TOKEN <span>}</span><span>}</span>
NETLIFY_SITE_ID: $<span>{</span><span>{</span> secrets.NETLIFY_SITE_ID <span>}</span><span>}</span>
- name: Cat cli.txt
run: |
cat cli.txt
sed -i -z 's/\n/\\n/g' cli.txt
- name: Post Netlify CLI Comment
env:
GITHUB_TOKEN: $<span>{</span><span>{</span> secrets.GITHUB_TOKEN <span>}</span><span>}</span>
URL: $<span>{</span><span>{</span> github.event.pull_request.comments_url <span>}</span><span>}</span>
run: |
curl -X POST \
-H "Authorization: token ${GITHUB_TOKEN}" \
-d "{\"body\": \"$(cat cli.txt)\"}" \
${URL}
</code></pre>
<p>次に本番へのデプロイです。</p>
<pre><code class="yaml">name: DeployToNetlifyPRD
on:
push:
branches:
- master
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout source code
uses: actions/checkout@v2
- name: Cache node_modules
uses: actions/cache@v1
with:
path: node_modules
key: $<span>{</span><span>{</span> runner.OS <span>}</span><span>}</span>-build-$<span>{</span><span>{</span> hashFiles('**/package-lock.json') <span>}</span><span>}</span>
restore-keys: |
$<span>{</span><span>{</span> runner.OS <span>}</span><span>}</span>-build-
$<span>{</span><span>{</span> runner.OS <span>}</span><span>}</span>
- name: Setup Node
uses: actions/setup-node@v1
with:
node-version: 12.x
- name: npm install and build
env:
GATSBY_GITHUB_CLIENT_SECRET: $<span>{</span><span>{</span>secrets.GATSBY_GITHUB_CLIENT_SECRET<span>}</span><span>}</span>
GATSBY_GITHUB_CLIENT_ID: $<span>{</span><span>{</span>secrets.GATSBY_GITHUB_CLIENT_ID<span>}</span><span>}</span>
GATSBY_ALGOLIA_SEARCH_API_KEY: $<span>{</span><span>{</span>secrets.GATSBY_ALGOLIA_SEARCH_API_KEY<span>}</span><span>}</span>
GATSBY_ALGOLIA_INDEX_NAME: $<span>{</span><span>{</span>secrets.GATSBY_ALGOLIA_INDEX_NAME<span>}</span><span>}</span>
GATSBY_ALGOLIA_APP_ID: $<span>{</span><span>{</span>secrets.GATSBY_ALGOLIA_APP_ID<span>}</span><span>}</span>
GATSBY_ALGOLIA_ADMIN_API_KEY: $<span>{</span><span>{</span>secrets.GATSBY_ALGOLIA_ADMIN_API_KEY<span>}</span><span>}</span>
FAUNADB_SERVER_SECRET: $<span>{</span><span>{</span>secrets.FAUNADB_SERVER_SECRET<span>}</span><span>}</span>
run: |
npm install
npm run build
- name: Deploy to netlify
run: npx netlify-cli deploy --prod --dir=./public
env:
NETLIFY_AUTH_TOKEN: $<span>{</span><span>{</span> secrets.NETLIFY_AUTH_TOKEN <span>}</span><span>}</span>
NETLIFY_SITE_ID: $<span>{</span><span>{</span> secrets.NETLIFY_SITE_ID <span>}</span><span>}</span>
</code></pre>
<p>ほとんど同じですが、netlify-cliでdeployコマンドに --prodオプションを入れることで、本番環境へデプロイされます。</p>
<pre><code class="yaml"> - name: Deploy to netlify
run: npx netlify-cli deploy --prod --dir=./public
env:
NETLIFY_AUTH_TOKEN: $<span>{</span><span>{</span> secrets.NETLIFY_AUTH_TOKEN <span>}</span><span>}</span>
NETLIFY_SITE_ID: $<span>{</span><span>{</span> secrets.NETLIFY_SITE_ID <span>}</span><span>}</span>
</code></pre>
<h2 id="結論"><a href="#%E7%B5%90%E8%AB%96">結論</a></h2>
<p>これで、Netlifyのビルド時間は0になり、精神的に安心できるようになりました。</p>
<p><img src="https://i.imgur.com/ugdUr9l.png" alt="img" /></p>
<p>リファクタや記事の執筆もはかどっていいですね!!</p>
tubone24
tag:crieit.net,2005:PublicArticle/14789
2019-02-09T11:28:59+09:00
2019-02-09T11:28:59+09:00
https://crieit.net/posts/GatsbyJs-Sitemap
GatsbyJsでSitemapを使う
<h2 id="GatsbyJSでgatsby-plugin-sitemapを使う"><a href="#GatsbyJS%E3%81%A7gatsby-plugin-sitemap%E3%82%92%E4%BD%BF%E3%81%86">GatsbyJSでgatsby-plugin-sitemapを使う</a></h2>
<p>GatsbyJSでGoogleにSiteMapを作成して登録したかったのでプラグインgatsby-plugin-sitemapを実装してみた。</p>
<h2 id="GatsbyJSでgatsby-plugin-sitemapの使い方"><a href="#GatsbyJS%E3%81%A7gatsby-plugin-sitemap%E3%81%AE%E4%BD%BF%E3%81%84%E6%96%B9">GatsbyJSでgatsby-plugin-sitemapの使い方</a></h2>
<ul>
<li>インストール</li>
<li>Gatsby-config.jsのセッティング</li>
<li>サンプルコード</li>
</ul>
<h2 id="Styled Componentsのインストール"><a href="#Styled+Components%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB">Styled Componentsのインストール</a></h2>
<p>npmコマンドでインストールします。</p>
<pre><code>npm install --save gatsby-plugin-sitemap
</code></pre>
<h2 id="Gatsby-config.jsのセッティング"><a href="#Gatsby-config.js%E3%81%AE%E3%82%BB%E3%83%83%E3%83%86%E3%82%A3%E3%83%B3%E3%82%B0">Gatsby-config.jsのセッティング</a></h2>
<p>Gatsby Config.jsを以下のようにします。</p>
<pre><code>module.exports = {
siteMetadata: {
siteUrl: `https://www.example.com`,
},
plugins: [`gatsby-plugin-sitemap`],
}
</code></pre>
<h2 id="動作確認"><a href="#%E5%8B%95%E4%BD%9C%E7%A2%BA%E8%AA%8D">動作確認</a></h2>
<pre><code>gatsby build
</code></pre>
<p>で確認すると</p>
<p>Publicフォルダを確認してみるとsitemap.xmlが出来ている。</p>
<p>サーチコンソールからサイトマップを追加してみるとエラーゼロで完成している。</p>
aocory
tag:crieit.net,2005:PublicArticle/14788
2019-02-08T18:05:29+09:00
2019-02-08T22:41:17+09:00
https://crieit.net/posts/GatsbyJS-Styled-Components
GatsbyJSでStyled Componentsを使う
<h2 id="GatsbyJSでStyled Componentsを使う"><a href="#GatsbyJS%E3%81%A7Styled+Components%E3%82%92%E4%BD%BF%E3%81%86">GatsbyJSでStyled Componentsを使う</a></h2>
<p>GatsbyJSでCSSモジュールを用いたスタイリングもいいが、CSSinJSで書いたほうが便利そうということでStyled Componentsを使ってみた。</p>
<h2 id="GatsbyJSでStyled Componentsの使い方"><a href="#GatsbyJS%E3%81%A7Styled+Components%E3%81%AE%E4%BD%BF%E3%81%84%E6%96%B9">GatsbyJSでStyled Componentsの使い方</a></h2>
<ul>
<li>インストール</li>
<li>Gatsby-config.jsのセッティング</li>
<li>サンプルコード</li>
</ul>
<h2 id="Styled Componentsのインストール"><a href="#Styled+Components%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB">Styled Componentsのインストール</a></h2>
<p>npmコマンドでインストールします。</p>
<pre><code>npm install --save gatsby-plugin-styled-components styled-components babel-plugin-styled-components
</code></pre>
<h2 id="Gatsby-config.jsのセッティング"><a href="#Gatsby-config.js%E3%81%AE%E3%82%BB%E3%83%83%E3%83%86%E3%82%A3%E3%83%B3%E3%82%B0">Gatsby-config.jsのセッティング</a></h2>
<p>Gatsby Config.jsを以下のようにします。</p>
<pre><code>module.exports = {
plugins: [`gatsby-plugin-styled-components`],
}
</code></pre>
<h2 id="書き直す"><a href="#%E6%9B%B8%E3%81%8D%E7%9B%B4%E3%81%99">書き直す</a></h2>
<p>index.jsはこのように書き直せます。</p>
<pre><code>import React from 'react'
import { Link } from 'gatsby'
import styled from 'styled-components'
import Layout from '../components/layout'
import Image from '../components/image'
const ImgWrapper = styled.div`
max-width: 300px;
margin-bottom: 1.45rem;
`
const IndexPage = () => (
<Layout>
<h1>Hi people</h1>
<p>Welcome to your new Gatsby site.</p>
<p>Now go build something great.</p>
<ImgWrapper>
<Image />
</ImgWrapper>
<Link to="/page-2/">Go to page 2</Link>
</Layout>
)
export default IndexPage
</code></pre>
<p>header.jsは、このように書き直すことができます。</p>
<pre><code>import React from 'react'
import { Link } from 'gatsby'
import styled from 'styled-components'
const HeaderWrapper = styled.div`
background: rebeccapurple;
margin-bottom: 1.45rem;
`
const Headline = styled.div`
margin: 0 auto;
max-width: 960;
padding: 1.45rem 1.0875rem;
h1 {
margin: 0;
}
`
const StyledLink = styled(Link)`
color: white;
textdecoration: none;
`
const Header = ({ siteTitle }) => (
<HeaderWrapper>
<Headline>
<h1>
<StyledLink to="/">{siteTitle}</StyledLink>
</h1>
</Headline>
</HeaderWrapper>
)
export default Header
</code></pre>
<h3 id="使ってみた感想"><a href="#%E4%BD%BF%E3%81%A3%E3%81%A6%E3%81%BF%E3%81%9F%E6%84%9F%E6%83%B3">使ってみた感想</a></h3>
<p>かなりStyled Components便利!一長一短ありますが、スコープ効いて名前が長くならないのはいいですね。</p>
aocory
tag:crieit.net,2005:PublicArticle/14781
2019-02-05T18:18:45+09:00
2019-02-05T18:18:45+09:00
https://crieit.net/posts/GatsbyJs-Font-Typeface
GatsbyJsでFontを変更するTypeface編
<h2 id="GatsbyJSでFontを変更したい"><a href="#GatsbyJS%E3%81%A7Font%E3%82%92%E5%A4%89%E6%9B%B4%E3%81%97%E3%81%9F%E3%81%84">GatsbyJSでFontを変更したい</a></h2>
<p>以前、gatsby-plugin-typographyで対応する方法を検討した。<br />
しかし、Noto Sans JPなどのフォントを使う時はGoogleフォントを読み込んでしまい、パフォーマンスが落ちるのが気になった。</p>
<h2 id="Typefaceを使う"><a href="#Typeface%E3%82%92%E4%BD%BF%E3%81%86">Typefaceを使う</a></h2>
<p>そこで、Gtasbyでは最近Typefaceを推奨している。<br />
npmでインストールしてimportで読み込む仕組みでこっちのほうが早いらしい。<br />
早速使ってみた。</p>
<ul>
<li>Typefaceのインストール</li>
<li>Layout.jsにインポート</li>
<li>css設定</li>
</ul>
<h3 id="Typefaceのインストール"><a href="#Typeface%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB">Typefaceのインストール</a></h3>
<p>今回はlatoというFontをインストールしてみる。</p>
<pre><code>npm install --save typeface-lato
</code></pre>
<h3 id="Layout.jsにインポート"><a href="#Layout.js%E3%81%AB%E3%82%A4%E3%83%B3%E3%83%9D%E3%83%BC%E3%83%88">Layout.jsにインポート</a></h3>
<p>インストール出来たらLayout.jsにインポートする</p>
<pre><code>import 'typeface-lato'
</code></pre>
<p>これだけではFontは動かないCSSの設定が必要になる。</p>
<h3 id="CSSに記載"><a href="#CSS%E3%81%AB%E8%A8%98%E8%BC%89">CSSに記載</a></h3>
<p>CSSに記載する。</p>
<pre><code> { font-family: Lato }
</code></pre>
<p>これで動く。</p>
aocory
tag:crieit.net,2005:PublicArticle/14778
2019-02-04T08:55:55+09:00
2019-02-04T08:55:55+09:00
https://crieit.net/posts/GatsbyJs-Webpack
GatsbyJsでWebpackバンドルサイズを確認する
<h2 id="GatsbyJsでWebpackバンドルサイズを確認する"><a href="#GatsbyJs%E3%81%A7Webpack%E3%83%90%E3%83%B3%E3%83%89%E3%83%AB%E3%82%B5%E3%82%A4%E3%82%BA%E3%82%92%E7%A2%BA%E8%AA%8D%E3%81%99%E3%82%8B">GatsbyJsでWebpackバンドルサイズを確認する</a></h2>
<p>当たり前だがAdSenseを入れるとサイト遅くなった。<br />
原因を探るため我々はGatsbyJsを良い感じにしてくれているWebPackの奥地に向かった。と言えば簡単なのだが<br />
WebPackは魔境だ。僕みたいな素人が触っても火傷するだけ。ということでパッケージを探した。</p>
<h2 id="gatsby-plugin-webpack-bundle-analyzerを使う"><a href="#gatsby-plugin-webpack-bundle-analyzer%E3%82%92%E4%BD%BF%E3%81%86">gatsby-plugin-webpack-bundle-analyzerを使う</a></h2>
<p>gatsby-plugin-webpack-bundle-analyzerというプラグインが便利そうだ。<br />
+ gatsby-plugin-webpack-bundle-analyzerのインストール<br />
+ gatsby-config.jsの設定<br />
+ 確認</p>
<h2 id="gatsby-plugin-webpack-bundle-analyzerのインストール"><a href="#gatsby-plugin-webpack-bundle-analyzer%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB">gatsby-plugin-webpack-bundle-analyzerのインストール</a></h2>
<pre><code>npm install --save gatsby-plugin-webpack-bundle-analyzer
</code></pre>
<h2 id="gatsby-config.jsの設定"><a href="#gatsby-config.js%E3%81%AE%E8%A8%AD%E5%AE%9A">gatsby-config.jsの設定</a></h2>
<p>gatsby-config.jsの設定を追加してやる</p>
<pre><code>plugins: [
'gatsby-plugin-webpack-bundle-analyzer',
]
</code></pre>
<h2 id="確認"><a href="#%E7%A2%BA%E8%AA%8D">確認</a></h2>
<pre><code>gatsby develop
</code></pre>
<p>で自動的にブラウザに表示される。<br />
ただ、毎回起動されるのはウザいので使わないときはコメントアウト推奨。</p>
aocory
tag:crieit.net,2005:PublicArticle/14774
2019-01-31T16:14:42+09:00
2019-01-31T16:14:42+09:00
https://crieit.net/posts/GatsbyJS-Static
GatsbyJSでStaticにファイルを置く
<h2 id="Staticファイルを置きたい"><a href="#Static%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%82%92%E7%BD%AE%E3%81%8D%E3%81%9F%E3%81%84">Staticファイルを置きたい</a></h2>
<p>Gatsbyはイメージファイルなどは自動で圧縮してくれるし、リサイズもしてくれるデキるやつです。<br />
しかし、PWAにサイトをしたり、ソーシャルアイコンのイメージ画像を扱う時は/img/logo.pngなどのようにファイルを扱いたいです。そこでやり方を調べました。</p>
<h2 id="GatsbyJSでStaticにファイルを置く方法"><a href="#GatsbyJS%E3%81%A7Static%E3%81%AB%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%82%92%E7%BD%AE%E3%81%8F%E6%96%B9%E6%B3%95">GatsbyJSでStaticにファイルを置く方法</a></h2>
<ul>
<li>rootディリクトリにstaticフォルダーを作成</li>
<li>staticにファイルを置く</li>
<li>withPrefixを読み込むコンポーネントに記載</li>
<li>gatsby-config.jsに変更</li>
</ul>
<h2 id="rootディリクトリにstaticフォルダーを作成"><a href="#root%E3%83%87%E3%82%A3%E3%83%AA%E3%82%AF%E3%83%88%E3%83%AA%E3%81%ABstatic%E3%83%95%E3%82%A9%E3%83%AB%E3%83%80%E3%83%BC%E3%82%92%E4%BD%9C%E6%88%90">rootディリクトリにstaticフォルダーを作成</a></h2>
<p>/blog/static/imgを作成します。</p>
<h2 id="staticにファイルを置く"><a href="#static%E3%81%AB%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%82%92%E7%BD%AE%E3%81%8F">staticにファイルを置く</a></h2>
<p>/static/img/logo.pngを今回は作成します。</p>
<h2 id="withPrefixを読み込むコンポーネントに記載"><a href="#withPrefix%E3%82%92%E8%AA%AD%E3%81%BF%E8%BE%BC%E3%82%80%E3%82%B3%E3%83%B3%E3%83%9D%E3%83%BC%E3%83%8D%E3%83%B3%E3%83%88%E3%81%AB%E8%A8%98%E8%BC%89">withPrefixを読み込むコンポーネントに記載</a></h2>
<p>staticファイルを読み込むにはwithPrefixの記載が必要です。</p>
<pre><code>import { withPrefix } from 'gatsby'
render() {
return <img src={withPrefix('/img/logo.png')} alt="Logo" />;
}
</code></pre>
<h2 id="gatsby-config.jsに変更"><a href="#gatsby-config.js%E3%81%AB%E5%A4%89%E6%9B%B4">gatsby-config.jsに変更</a></h2>
<pre><code>module.exports = {
pathPrefix: `/img`,
}
</code></pre>
<p>注意"/img/"と記載してはいけません。</p>
<h2 id="確認"><a href="#%E7%A2%BA%E8%AA%8D">確認</a></h2>
<p><img src="https://frosty-wozniak-d3bb12.netlify.com/img/logo.png" alt="logo.png" /><br />
できた!</p>
aocory
tag:crieit.net,2005:PublicArticle/14761
2019-01-30T11:24:33+09:00
2019-01-30T11:24:33+09:00
https://crieit.net/posts/GatsbyJS-Google-AdSense
GatsbyJSにGoogle AdSenseを導入する
<h2 id="GatsbyJSにAdSenseを導入する。"><a href="#GatsbyJS%E3%81%ABAdSense%E3%82%92%E5%B0%8E%E5%85%A5%E3%81%99%E3%82%8B%E3%80%82">GatsbyJSにAdSenseを導入する。</a></h2>
<p>ブログをやる以上ドメイン代金くらいは稼ぎたい。そこでGoogle AdSenseをGatsbyに導入する。</p>
<h2 id="やったこと"><a href="#%E3%82%84%E3%81%A3%E3%81%9F%E3%81%93%E3%81%A8">やったこと</a></h2>
<ul>
<li>react-adsenseの導入</li>
<li>html.jsの作成</li>
<li>コンポーネントを作成</li>
<li>アップロードして確認</li>
</ul>
<h2 id="react-adsenseの導入"><a href="#react-adsense%E3%81%AE%E5%B0%8E%E5%85%A5">react-adsenseの導入</a></h2>
<p>GatsbyでGoogleAdSenseを導入するときはreact-adsenseが便利です。</p>
<pre><code>npm install --save react-adsense
</code></pre>
<h2 id="html.jsの作成"><a href="#html.js%E3%81%AE%E4%BD%9C%E6%88%90">html.jsの作成</a></h2>
<p>GatsbyJSでは<code><script></code>タグをヘッダーに入れる場合はhtml.jsを作成し入れる必要がある。<br />
/.cache/default-html.jsを/src/html.jsにコピーする。</p>
<pre><code>cp .cache/default-html.js src/html.js
</code></pre>
<h2 id="コンポーネントを作成"><a href="#%E3%82%B3%E3%83%B3%E3%83%9D%E3%83%BC%E3%83%8D%E3%83%B3%E3%83%88%E3%82%92%E4%BD%9C%E6%88%90">コンポーネントを作成</a></h2>
<p>再利用することを見越してコンポーネントを作成する。<br />
/components/Ad/index.js</p>
<pre><code>import React from "react";
import AdSense from 'react-adsense'
const Ad = () => (
<div>
<AdSense.Google
client="ca-pub-数字"
slot="数字"
format="rectangle"
/>
</div>
)
export default Ad;
</code></pre>
<h2 id="確認"><a href="#%E7%A2%BA%E8%AA%8D">確認</a></h2>
<p><a href="https://crieit.now.sh/upload_images/b9ea838a8b4e1eaf357182ed160879ea5c510aaf03e03.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/b9ea838a8b4e1eaf357182ed160879ea5c510aaf03e03.jpg?mw=700" alt="024-1.jpg" /></a></p>
aocory
tag:crieit.net,2005:PublicArticle/14757
2019-01-28T23:45:36+09:00
2019-01-28T23:45:36+09:00
https://crieit.net/posts/GatsbyJS-Google-Analytics
GatsbyJSにGoogle Analyticsを導入する
<h2 id="GatsbyJSにGoogle Analyticsを導入する"><a href="#GatsbyJS%E3%81%ABGoogle+Analytics%E3%82%92%E5%B0%8E%E5%85%A5%E3%81%99%E3%82%8B">GatsbyJSにGoogle Analyticsを導入する</a></h2>
<p>Google Analyticsを導入するにはどうすればいいのか?<br />
Gatsbyならgatsby-plugin-google-analyticsで簡単に実装できます。</p>
<h2 id="やったこと"><a href="#%E3%82%84%E3%81%A3%E3%81%9F%E3%81%93%E3%81%A8">やったこと</a></h2>
<ul>
<li>gatsby-plugin-google-analyticsインストール</li>
<li>gatsby-config.jsを設定</li>
<li>siteConfig.jsを設定</li>
</ul>
<h2 id="gatsby-plugin-google-analytics"><a href="#gatsby-plugin-google-analytics">gatsby-plugin-google-analytics</a></h2>
<p>まずは、gatsby-plugin-google-analyticsをnpmでインストールします。</p>
<pre><code>npm install --save gatsby-plugin-google-analytics
</code></pre>
<h2 id="gatsby-config.js"><a href="#gatsby-config.js">gatsby-config.js</a></h2>
<p>次にgatsby-config.jsを設定します。<br />
/data/siteConfig.jsにデータはまとめて管理する仕様にしているのでsiteConfig.jsをちゃんと読み込むようにしましょう。</p>
<pre><code>const config = require("./data/siteConfig");
module.exports = {
plugins: [
{
resolve: "gatsby-plugin-google-analytics",
options: {
trackingId: config.googleAnalyticsID
}
},
],
}
</code></pre>
<h2 id="siteConfig.js"><a href="#siteConfig.js">siteConfig.js</a></h2>
<p>siteConfig.jsは以下のように設定します。</p>
<pre><code>googleAnalyticsID: "UA-XXXXXXX-X", // GA tracking ID.
</code></pre>
<h2 id="GoogleAnalyticsを確認する。"><a href="#GoogleAnalytics%E3%82%92%E7%A2%BA%E8%AA%8D%E3%81%99%E3%82%8B%E3%80%82">GoogleAnalyticsを確認する。</a></h2>
<p><a target="_blank" rel="nofollow noopener" href="https://analytics.google.com/">Google Analytics</a>で確認してみましょう。</p>
aocory
tag:crieit.net,2005:PublicArticle/14754
2019-01-28T15:53:21+09:00
2019-01-28T22:47:45+09:00
https://crieit.net/posts/GatsbyJS-5c4ea6e13be5d
GatsbyJSにソーシャルボタンを追加する
<h2 id="GatsbyJSにソーシャルボタンを追加する"><a href="#GatsbyJS%E3%81%AB%E3%82%BD%E3%83%BC%E3%82%B7%E3%83%A3%E3%83%AB%E3%83%9C%E3%82%BF%E3%83%B3%E3%82%92%E8%BF%BD%E5%8A%A0%E3%81%99%E3%82%8B">GatsbyJSにソーシャルボタンを追加する</a></h2>
<p>ソーシャルボタンを追加したい!と思ったのでGatsbyJSで追加しました。</p>
<h2 id="やったこと"><a href="#%E3%82%84%E3%81%A3%E3%81%9F%E3%81%93%E3%81%A8">やったこと</a></h2>
<ul>
<li>react-share導入</li>
<li>シェアボタンコンポーネントの作成</li>
<li>SiteConfigの追加</li>
<li>テンプレートの変更</li>
</ul>
<h1 id="react-shareの導入"><a href="#react-share%E3%81%AE%E5%B0%8E%E5%85%A5">react-shareの導入</a></h1>
<p>react-shareは、react向けの便利なライブラリです。<br />
対応しているSNSは、<br />
+ Facebook<br />
+ Twitter<br />
+ Telegram<br />
+ Google+<br />
+ Whatsapp<br />
+ LinkedIn<br />
+ Pinterest<br />
+ VK<br />
+ Odnoklassniki<br />
+ Reddit<br />
+ Tumblr<br />
+ Mail.Ru<br />
+ LiveJournal<br />
+ Viber<br />
+ Workplace<br />
+ Line<br />
+ Weibo<br />
+ email<br />
と非常に多いです。</p>
<pre><code>npm install react-share --save
</code></pre>
<h2 id="シェアボタンコンポーネントの作成"><a href="#%E3%82%B7%E3%82%A7%E3%82%A2%E3%83%9C%E3%82%BF%E3%83%B3%E3%82%B3%E3%83%B3%E3%83%9D%E3%83%BC%E3%83%8D%E3%83%B3%E3%83%88%E3%81%AE%E4%BD%9C%E6%88%90">シェアボタンコンポーネントの作成</a></h2>
<p>/component/Share/index.jsをつくります。</p>
<pre><code>import React, { Component } from "react";
import {
FacebookShareButton,
TwitterShareButton,
FacebookIcon,
TwitterIcon,
LineShareButton,
LineIcon
} from "react-share";
import urljoin from "url-join";
import config from "../../../data/SiteConfig";
import "./SocialLinks.css";
class Share extends Component {
render() {
const { postNode, postPath, mobile } = this.props;
const post = postNode.frontmatter;
const url = urljoin(config.siteUrl, postPath);
const iconSize = mobile ? 36 : 48;
return (
<div className="social-links">
<TwitterShareButton url={url} title={post.title}>
<TwitterIcon round size={iconSize} />
</TwitterShareButton>
<FacebookShareButton url={url} quote={postNode.excerpt}>
<FacebookIcon round size={iconSize} />
</FacebookShareButton>
<LineShareButton url={url} quote={postNode.excerpt}>
<LineIcon round size={iconSize} />
</LineShareButton>
</div>
);
}
}
export default Share;
</code></pre>
<h1 id="SiteConfigの追加"><a href="#SiteConfig%E3%81%AE%E8%BF%BD%E5%8A%A0">SiteConfigの追加</a></h1>
<p>続いてsiteConfig.jsの変更を行います。<br />
siteUrlを追記</p>
<pre><code>const siteConfig = {
siteUrl: "https://corylog.com",
}
module.exports = siteConfig;
</code></pre>
<h2 id="テンプレートの変更"><a href="#%E3%83%86%E3%83%B3%E3%83%97%E3%83%AC%E3%83%BC%E3%83%88%E3%81%AE%E5%A4%89%E6%9B%B4">テンプレートの変更</a></h2>
<pre><code>import React from 'react'
import { Link, graphql } from 'gatsby'
import Layout from '../components/Layout'
import SEO from '../components/seo'
import rehypeReact from "rehype-react"
import Sample from "../components/Sample"
import Share from '../components/Share';
const renderAst = new rehypeReact({
createElement: React.createElement,
components: { "sample": Sample }
}).Compiler
class BlogPostTemplate extends React.Component {
render() {
const { slug } = this.props.pageContext;
const post = this.props.data.markdownRemark
const siteTitle = this.props.data.site.siteMetadata.title
const { previous, next } = this.props.pageContext
return (
<Layout location={this.props.location} title={siteTitle}>
<SEO title={post.frontmatter.title} description={post.excerpt} />
<h1>{post.frontmatter.title}</h1>
<p>
{post.frontmatter.date}
</p>
<div>{renderAst(post.htmlAst)}</div>
<hr/>
<ul>
<li>
{previous && (
<Link to={previous.fields.slug} rel="prev">
← {previous.frontmatter.title}
</Link>
)}
</li>
<li>
{next && (
<Link to={next.fields.slug} rel="next">
{next.frontmatter.title} →
</Link>
)}
</li>
</ul>
<Share postPath={slug} postNode={post} />
</Layout>
)
}
}
export default BlogPostTemplate
export const pageQuery = graphql`
query BlogPostBySlug($slug: String!) {
site {
siteMetadata {
title
author
}
}
markdownRemark(fields: { slug: { eq: $slug } }) {
id
excerpt(pruneLength: 160)
htmlAst
frontmatter {
title
date(formatString: "MMMM DD, YYYY")
}
}
}
`
</code></pre>
<h2 id="動作確認"><a href="#%E5%8B%95%E4%BD%9C%E7%A2%BA%E8%AA%8D">動作確認</a></h2>
<p><a href="https://crieit.now.sh/upload_images/8f404993f6a55ca8c18a74d4b85dbe9d5c4f07f89632e.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/8f404993f6a55ca8c18a74d4b85dbe9d5c4f07f89632e.jpg?mw=700" alt="022-1.jpg" /></a></p>
aocory
tag:crieit.net,2005:PublicArticle/14753
2019-01-28T10:58:03+09:00
2019-01-28T10:58:03+09:00
https://crieit.net/posts/GatsbyJS-5c4e61ab0c09d
GatsbyJSに画像付きカードメニューを作成する
<h2 id="GatsbyJSに画像付きカードメニューを作成する"><a href="#GatsbyJS%E3%81%AB%E7%94%BB%E5%83%8F%E4%BB%98%E3%81%8D%E3%82%AB%E3%83%BC%E3%83%89%E3%83%A1%E3%83%8B%E3%83%A5%E3%83%BC%E3%82%92%E4%BD%9C%E6%88%90%E3%81%99%E3%82%8B">GatsbyJSに画像付きカードメニューを作成する</a></h2>
<p>時代は、画像付き投稿一覧だよね?(個人の感想です。)<br />
ということで実装してみた。</p>
<h2 id="やったこと"><a href="#%E3%82%84%E3%81%A3%E3%81%9F%E3%81%93%E3%81%A8">やったこと</a></h2>
<ul>
<li>postlistコンポーネントの変更</li>
<li>coverImageコンポーネントの実装</li>
<li>markdownにカバーイメージを追加</li>
</ul>
<h2 id="postlistを以下の様に変更した。"><a href="#postlist%E3%82%92%E4%BB%A5%E4%B8%8B%E3%81%AE%E6%A7%98%E3%81%AB%E5%A4%89%E6%9B%B4%E3%81%97%E3%81%9F%E3%80%82">postlistを以下の様に変更した。</a></h2>
<pre><code class="js">import React from "react";
import PropTypes from 'prop-types';
import CoverImage from '../../components/CoverImage'
import './postlist.css'
class Postlist extends React.Component {
getPostList() {
const postList = [];
this.props.postEdges.forEach(postEdge => {
postList.push({
title: postEdge.node.frontmatter.title,
date: postEdge.node.frontmatter.date,
cover: postEdge.node.frontmatter.coverImage,
excerpt: postEdge.node.excerpt,
});
});
return postList;
}
render() {
const postList = this.getPostList();
return (
<div className="grid">
{postList.map( post => (
<div key={post.id} className="griditem">
<div className="coverImage">
<CoverImage filename={post.cover}></CoverImage>
</div>
<span>
{post.title}<br/>
{post.date}
</span>
</div>
))}
</div>
);
}
}
export default Postlist;
</code></pre>
<p>そして、カードデザインを実装する</p>
<pre><code class="css">.grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(336px, 1fr));
grid-gap: 16px;
align-items: stretch;
}
.griditem {
max-width: 336px;
border: 1px solid #ccc;
box-shadow: 2px 2px 6px 0px rgba(0,0,0,0.3);
}
.griditem > img {
max-width: 100%;
}
.text {
padding: 0 20px 20px;
}
.text > button {
background: gray;
border: 0;
color: white;
padding: 10px;
width: 100%;
}
</code></pre>
<p>カードデザインの幅を336pxに設定しているのには実は理由があって、将来GoogleAdSenseを違和感なくフィットさせることに挑戦したいので、この幅で設定した。</p>
<h2 id="coverImageコンポーネントの実装"><a href="#coverImage%E3%82%B3%E3%83%B3%E3%83%9D%E3%83%BC%E3%83%8D%E3%83%B3%E3%83%88%E3%81%AE%E5%AE%9F%E8%A3%85">coverImageコンポーネントの実装</a></h2>
<pre><code class="js">import React from 'react'
import { StaticQuery, graphql } from 'gatsby'
import Img from 'gatsby-image'
import "./coverimage.css"
const Image = (props) => (
<StaticQuery
query={graphql`
query {
images: allFile {
edges {
node {
relativePath
name
childImageSharp {
fluid(maxWidth: 336, maxHeight: 280){
...GatsbyImageSharpFluid
}
}
}
}
}
}
`}
render={(data) => {
const image = data.images.edges.find(n => {
return n.node.relativePath.includes(props.filename);
});
if (!image) { return null; }
const imagefluid = image.node.childImageSharp.fluid;
return (
<Img
alt={props.alt}
sizes={imagefluid}
/>
);
<span>}</span><span>}</span>
/>
)
export default Image
</code></pre>
<p>こちらもAdSenseを見越して336×280の画像を生成出来るように実装しておく。</p>
<p>page/index.jsのGraphQLも変更しておく</p>
<pre><code class="js">export const query = graphql`
query {
allMarkdownRemark(filter: {frontmatter: {pagetype: {ne: "category"<span>}</span><span>}</span>}) {
totalCount
edges {
node {
id
frontmatter {
title
date(formatString: "DD MMMM, YYYY")
category
coverImage
}
excerpt
}
}
}
}
`
</code></pre>
<p>できた!<br />
<a href="https://crieit.now.sh/upload_images/51f79a78e7e68e3fdf65b2c5196325095c4e610720365.JPG" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/51f79a78e7e68e3fdf65b2c5196325095c4e610720365.JPG?mw=700" alt="021-2.JPG" /></a></p>
aocory
tag:crieit.net,2005:PublicArticle/14751
2019-01-27T15:40:08+09:00
2019-01-27T22:24:49+09:00
https://crieit.net/posts/GatsbyJS-5c4d52488575f
GatsbyJSにドロワーメニューを追加する
<h2 id="ドロワーメニューを追加したい。"><a href="#%E3%83%89%E3%83%AD%E3%83%AF%E3%83%BC%E3%83%A1%E3%83%8B%E3%83%A5%E3%83%BC%E3%82%92%E8%BF%BD%E5%8A%A0%E3%81%97%E3%81%9F%E3%81%84%E3%80%82">ドロワーメニューを追加したい。</a></h2>
<p>カテゴリーをドロワーメニューで表示したい欲が出てきたので実装する。<br />
しかし、ドロワーを1から書くにはJSの理解レベルが足りない。<br />
そこで今回はMaterialUIに泣きついた。</p>
<h2 id="やったこと"><a href="#%E3%82%84%E3%81%A3%E3%81%9F%E3%81%93%E3%81%A8">やったこと</a></h2>
<ul>
<li>Material-UIのインストール</li>
<li>Headerを実装</li>
<li>categorylistを作成</li>
</ul>
<h2 id="Material-UIのインストール"><a href="#Material-UI%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB">Material-UIのインストール</a></h2>
<pre><code>npm install --save @material-ui/core
npm install --save @material-ui/icons
</code></pre>
<h2 id="Headerを実装"><a href="#Header%E3%82%92%E5%AE%9F%E8%A3%85">Headerを実装</a></h2>
<pre><code class="js">import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { withStyles } from '@material-ui/core/styles';
import AppBar from '@material-ui/core/AppBar';
import Toolbar from '@material-ui/core/Toolbar';
import Button from '@material-ui/core/Button';
import IconButton from '@material-ui/core/IconButton';
import MenuIcon from '@material-ui/icons/Menu';
import List from '@material-ui/core/List';
import ListItem from '@material-ui/core/ListItem';
import ListItemIcon from '@material-ui/core/ListItemIcon';
import ListItemText from '@material-ui/core/ListItemText';
import Drawer from '@material-ui/core/Drawer';
import { Link } from 'gatsby';
const styles = {
list: {
width: 250,
},
root: {
flexGrow: 1,
},
menuButton: {
marginLeft: -12,
marginRight: 20,
},
};
class Header extends Component {
state = {
left: false,
};
toggleDrawer = (side, open) => () => {
this.setState({
[side]: open,
});
};
render () {
const { classes } = this.props;
const sideList = (
<div className={classes.list}>
<List>
<Link to="/">
<ListItem button>
<ListItemText primary="Home" />
</ListItem>
</Link>
<Link to="/about">
<ListItem button>
<ListItemText primary="About" />
</ListItem>
</Link>
</List>
</div>
);
return (
<div className={classes.root}>
<AppBar position="relative" color="inherit">
<Toolbar>
<IconButton className={classes.menuButton} color="inherit" aria-label="Menu" onClick={this.toggleDrawer('left', true)}>
<MenuIcon />
</IconButton>
<Drawer open={this.state.left} onClose={this.toggleDrawer('left', false)}>
<div
tabIndex={0}
role="button"
onClick={this.toggleDrawer('left', false)}
onKeyDown={this.toggleDrawer('left', false)}
>
{sideList}
</div>
</Drawer>
<strong>
<Link to="/" style=<span>{</span><span>{</span> boxShadow: 'none', textDecoration: 'none', color: 'inherit', fontFamily: 'Montserrat, sans-serif', <span>}</span><span>}</span>>Post Bank Extra</Link>
</strong>
</Toolbar>
</AppBar>
</div>
);
}
}
Header.propTypes = {
classes: PropTypes.object.isRequired,
};
export default withStyles(styles)(Header);
</code></pre>
<p>これにあとは自分のカテゴリーリストを載せる。</p>
<h2 id="カテゴリーリストの実装"><a href="#%E3%82%AB%E3%83%86%E3%82%B4%E3%83%AA%E3%83%BC%E3%83%AA%E3%82%B9%E3%83%88%E3%81%AE%E5%AE%9F%E8%A3%85">カテゴリーリストの実装</a></h2>
<pre><code class="js">import React from 'react'
import { StaticQuery, graphql } from 'gatsby'
import ListItem from '@material-ui/core/ListItem';
import Button from '@material-ui/core/Button';
import ListItemText from '@material-ui/core/ListItemText';
const CategoryLists = () => (
<StaticQuery
query={graphql`
query{
allMarkdownRemark(filter: {frontmatter: {pagetype: {eq: "category"<span>}</span><span>}</span>}) {
edges{
node{
frontmatter{
categoryslug
categoryname
}
}
}
}
}
`}
render={(data) => {
const posts = data.allMarkdownRemark.edges
return (
<div>
{posts.map(({ node }) => {
return (
<ListItem button key={node.frontmatter.categoryslug}>
<ListItemText primary={node.frontmatter.categoryname}></ListItemText>
</ListItem>
)
})}
</div>
);
<span>}</span><span>}</span>
/>
)
export default CategoryLists
</code></pre>
<p>そして組み込む</p>
<pre><code class="js">import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { withStyles } from '@material-ui/core/styles';
import AppBar from '@material-ui/core/AppBar';
import Toolbar from '@material-ui/core/Toolbar';
import Button from '@material-ui/core/Button';
import IconButton from '@material-ui/core/IconButton';
import MenuIcon from '@material-ui/icons/Menu';
import List from '@material-ui/core/List';
import ListItem from '@material-ui/core/ListItem';
import ListItemIcon from '@material-ui/core/ListItemIcon';
import ListItemText from '@material-ui/core/ListItemText';
import Drawer from '@material-ui/core/Drawer';
import { Link } from 'gatsby';
import CategoryLists from '../categorylists';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faHome,faUtensils,faQuestion} from '@fortawesome/free-solid-svg-icons'
const styles = {
list: {
width: 250,
},
root: {
flexGrow: 1,
},
menuButton: {
marginLeft: -12,
marginRight: 20,
},
};
class Header extends Component {
state = {
left: false,
};
toggleDrawer = (side, open) => () => {
this.setState({
[side]: open,
});
};
render () {
const { classes } = this.props;
const sideList = (
<div className={classes.list}>
<List>
<Link to="/">
<ListItem button>
<FontAwesomeIcon icon={faHome} />
<ListItemText primary="Home" />
</ListItem>
</Link>
<CategoryLists />
<Link to="/about">
<ListItem button>
<FontAwesomeIcon icon={faQuestion} />
<ListItemText primary="About" />
</ListItem>
</Link>
</List>
</div>
);
return (
<div className={classes.root}>
<AppBar position="relative" color="inherit">
<Toolbar>
<IconButton className={classes.menuButton} color="inherit" aria-label="Menu" onClick={this.toggleDrawer('left', true)}>
<MenuIcon />
</IconButton>
<Drawer open={this.state.left} onClose={this.toggleDrawer('left', false)}>
<div
tabIndex={0}
role="button"
onClick={this.toggleDrawer('left', false)}
onKeyDown={this.toggleDrawer('left', false)}
>
{sideList}
</div>
</Drawer>
<strong>
<Link to="/" style=<span>{</span><span>{</span> boxShadow: 'none', textDecoration: 'none', color: 'inherit', fontFamily: 'Montserrat, sans-serif', <span>}</span><span>}</span>>corydoras</Link>
</strong>
</Toolbar>
</AppBar>
</div>
);
}
}
Header.propTypes = {
classes: PropTypes.object.isRequired,
};
export default withStyles(styles)(Header);
</code></pre>
<p>StaticQueryで実装。便利。</p>
<h2 id="実働"><a href="#%E5%AE%9F%E5%83%8D">実働</a></h2>
<p><a href="https://crieit.now.sh/upload_images/843d1ca1b8d9ab40db45ba8903d134505c4d51ea79aa4.png" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/843d1ca1b8d9ab40db45ba8903d134505c4d51ea79aa4.png?mw=700" alt="020-1.png" /></a><br />
よし!動いた!</p>
<h2 id="出来なかったこと"><a href="#%E5%87%BA%E6%9D%A5%E3%81%AA%E3%81%8B%E3%81%A3%E3%81%9F%E3%81%93%E3%81%A8">出来なかったこと</a></h2>
<p>frontmatterにicon設定してリストレンダリングしようとしましたができませんでした。</p>
aocory
tag:crieit.net,2005:PublicArticle/14750
2019-01-26T23:33:55+09:00
2019-01-26T23:43:44+09:00
https://crieit.net/posts/GatsbyJS-5c4c6fd367e88
GatsbyJSでカテゴリー機能を実装する
<h2 id="カテゴリーページにもっと自由を"><a href="#%E3%82%AB%E3%83%86%E3%82%B4%E3%83%AA%E3%83%BC%E3%83%9A%E3%83%BC%E3%82%B8%E3%81%AB%E3%82%82%E3%81%A3%E3%81%A8%E8%87%AA%E7%94%B1%E3%82%92">カテゴリーページにもっと自由を</a></h2>
<p>カテゴリー一覧を作っていきたい。<br />
GatsbyのStarterではGraphQLのGroup機能を使ってやっている人が多い。<br />
今回はMarkdownを使ってある程度自由にカスタマイズできるように実装していきたい。<br />
それには理由があって、僕のサイトの作り方だとカテゴリーページが上がる傾向にある。そこでユーザーを離脱させない工夫としてカテゴリーをmarkdownで自由にカスタマイズできるようにしておきたい。</p>
<h2 id="作っていくもの"><a href="#%E4%BD%9C%E3%81%A3%E3%81%A6%E3%81%84%E3%81%8F%E3%82%82%E3%81%AE">作っていくもの</a></h2>
<ul>
<li>categoriesフォルダ</li>
<li>gatsby-node.js</li>
<li>/templete/categorypage.js</li>
<li>/components/categoryPostlist/</li>
</ul>
<p>こんだけで実装できそうだ。<br />
まず、/contents/categoies/food.mdと<br />
/contents/categories/drink.mdを作成。</p>
<pre><code>---
pagetype: "category"
categoryname: "食べ物"
categoryslug: "food"
---
</code></pre>
<p>と</p>
<pre><code>---
pagetype: "category"
categoryname: "飲み物"
categoryslug: "drink"
---
</code></pre>
<p>YAMLで上記のように記載する。<br />
カスタマイズしたければMarkdownで加工すればいいようにする。</p>
<h2 id="gatsby-node.js"><a href="#gatsby-node.js">gatsby-node.js</a></h2>
<p>続いてgatsby-node.jsを書いていく前にGraphQLでどこにフィルターをかけるかを見てみる。</p>
<pre><code>{
allMarkdownRemark(filter: {frontmatter: {pagetype: {eq: "category"<span>}</span><span>}</span>}) {
edges {
node {
id
}
}
}
}
</code></pre>
<p>こんな感じでフィルターかけるのが簡単そう。<br />
同じところから引っ張る場合エラーが出るのでそれぞれ名前を付ける</p>
<pre><code>{
blogposts: allMarkdownRemark(sort: {fields: [frontmatter___date], order: DESC}, limit: 1000) {
edges {
node {
fields {
slug
}
frontmatter {
title
}
}
}
}
categories: allMarkdownRemark(filter: {frontmatter: {pagetype: {eq: "category"<span>}</span><span>}</span>}) {
edges {
node {
frontmatter {
categoryslug
}
}
}
}
}
</code></pre>
<p>最終的には</p>
<pre><code>const path = require(`path`)
const { createFilePath } = require(`gatsby-source-filesystem`)
exports.createPages = ({ graphql, actions }) => {
const { createPage } = actions
return new Promise((resolve, reject) => {
const blogPost = path.resolve(`./src/templates/blog-post.js`)
const categoryPage = path.resolve(`./src/templates/categorypage.js`)
resolve(
graphql(
`
{
blogposts: allMarkdownRemark(sort: {fields: [frontmatter___date], order: DESC}, limit: 1000) {
edges {
node {
fields {
slug
}
frontmatter {
title
}
}
}
}
categories: allMarkdownRemark(filter: {frontmatter: {pagetype: {eq: "category"<span>}</span><span>}</span>}) {
edges {
node {
frontmatter {
categoryslug
}
}
}
}
}
`
).then(result => {
if (result.errors) {
console.log(result.errors)
reject(result.errors)
}
// Create blog posts pages.
const posts = result.data.blogposts.edges
const categories = result.data.categories.edges
posts.forEach((post, index) => {
const previous =
index === posts.length - 1 ? null : posts[index + 1].node
const next = index === 0 ? null : posts[index - 1].node
createPage({
path: post.node.fields.slug,
component: blogPost,
context: {
slug: post.node.fields.slug,
previous,
next,
},
})
})
categories.forEach((category) => {
createPage({
path: `/category/${(category.node.frontmatter.categoryslug)}`,
component: categoryPage,
context: {
slug: category.node.frontmatter.categoryslug,
<span>}</span><span>}</span>)
})
})
)
})
}
exports.onCreateNode = ({ node, actions, getNode }) => {
const { createNodeField } = actions
if (node.internal.type === `MarkdownRemark`) {
const value = createFilePath({ node, getNode })
createNodeField({
name: `slug`,
node,
value,
})
}
}
</code></pre>
<p>こうなった。<br />
次は、テンプレを作る</p>
<pre><code>import rehypeReact from "rehype-react"
import Sample from "../components/Sample"
import Categoryposts from "../components/categoryposts"
const renderAst = new rehypeReact({
createElement: React.createElement,
components: { "sample": Sample }
}).Compiler
class CategoryPageTemplate extends React.Component {
render() {
const post = this.props.data.markdownRemark
const siteTitle = this.props.data.site.siteMetadata.title
return (
<Layout location={this.props.location} title={siteTitle}>
<SEO title={post.frontmatter.categoryname} />
<h1>{post.frontmatter.categoryname}</h1>
<div>{renderAst(post.htmlAst)}</div>
<hr/>
<Categoryposts category={post.frontmatter.categoryslug} />
</Layout>
)
}
}
export default CategoryPageTemplate
export const pageQuery = graphql`
query CategoryPageBySlug ($slug: String!){
site {
siteMetadata {
title
author
}
}
markdownRemark (frontmatter:{categoryslug:{ eq: $slug<span>}</span><span>}</span>)
{
htmlAst
frontmatter {
categoryname
categoryslug
}
}
}
`
</code></pre>
<p>最終的にこうなった。<br />
そして、categorylistを作る。<br />
/src/components/categoryposts/index.js</p>
<pre><code>import React from 'react'
import { StaticQuery, graphql } from 'gatsby'
const CategoryPosts = (props) => (
<StaticQuery
query={graphql`
query{
allMarkdownRemark{
edges{
node{
frontmatter{
pagetype
category
title
date
}
excerpt
}
}
}
}
`}
render={(data) => {
const postlists = data.allMarkdownRemark.edges
const posts = postlists.filter((category)=>{
return (category.node.frontmatter.category === props.category)
})
return (
<div>
{posts.map(({ node }) => {
return (
<div key={node.frontmatter.title}>
<p>{node.frontmatter.date}</p>
<p dangerouslySetInnerHTML=<span>{</span><span>{</span> __html: node.excerpt <span>}</span><span>}</span> />
</div>
)
})}
</div>
);
<span>}</span><span>}</span>
/>
)
export default CategoryPosts
</code></pre>
<p>ポイントはStaticQueryを使って全部取得してからフィルタリングしているところ。<br />
コンポーネントでGraphQLを使用する場合、普通のクエリではと動かない仕様になっている。<br />
<a href="https://crieit.now.sh/upload_images/2371759b8c5aa1d5cae8dfe692bf6f1d5c4c6fc398ae5.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/2371759b8c5aa1d5cae8dfe692bf6f1d5c4c6fc398ae5.jpg?mw=700" alt="019-1.jpg" /></a><br />
上手く表示できた!</p>
aocory
tag:crieit.net,2005:PublicArticle/14747
2019-01-25T08:46:16+09:00
2019-01-25T08:46:16+09:00
https://crieit.net/posts/GatsbyJS-Mrakdown
GatsbyJSでMrakdown内でコンポーネントを使う
<h2 id="GatsbyJSでMrakdown内でコンポーネントを使う"><a href="#GatsbyJS%E3%81%A7Mrakdown%E5%86%85%E3%81%A7%E3%82%B3%E3%83%B3%E3%83%9D%E3%83%BC%E3%83%8D%E3%83%B3%E3%83%88%E3%82%92%E4%BD%BF%E3%81%86">GatsbyJSでMrakdown内でコンポーネントを使う</a></h2>
<p>Markdown内でReactコンポーネントを使いたい欲求が出てきたので実装してみる。</p>
<h2 id="Gatsby Remark Componentを使う"><a href="#Gatsby+Remark+Component%E3%82%92%E4%BD%BF%E3%81%86">Gatsby Remark Componentを使う</a></h2>
<p>こういうReactコンポーネントを使う場合は、Gatsby Remark Componentを使う。</p>
<h2 id="gatsby-remark-responsive-iframeをインストール"><a href="#gatsby-remark-responsive-iframe%E3%82%92%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB">gatsby-remark-responsive-iframeをインストール</a></h2>
<p><code>npm install --save gatsby-remark-component</code><br />
<code>npm install --save rehype-react</code></p>
<h2 id="gatsby-config.jsmの設定"><a href="#gatsby-config.jsm%E3%81%AE%E8%A8%AD%E5%AE%9A">gatsby-config.jsmの設定</a></h2>
<pre><code>plugins: [
{
resolve: "gatsby-transformer-remark",
options: {
plugins: ["gatsby-remark-component"]
}
}
]
</code></pre>
<h2 id="実際の動作確認"><a href="#%E5%AE%9F%E9%9A%9B%E3%81%AE%E5%8B%95%E4%BD%9C%E7%A2%BA%E8%AA%8D">実際の動作確認</a></h2>
<p>とりあえず簡単なコンポーネントを作ってみる。<br />
/components/Sample.js</p>
<pre><code>import React from 'react'
const Sample = () => (
<div>
<p>これはコンポーネントです。</p>
</div>
)
export default Sample
</code></pre>
<p>blog-post.jsを変更する。<br />
読み込みを追加</p>
<pre><code>import rehypeReact from "rehype-react"
import Sample from "../components/SampleSample"
</code></pre>
<p>そして、コンポーネントを使えるように設定する。注意点としては小文字にしなければいけない。</p>
<pre><code>const renderAst = new rehypeReact({
createElement: React.createElement,
components: { "sample": Sample },
}).Compiler
</code></pre>
<pre><code><div dangerouslySetInnerHTML=<span>{</span><span>{</span> __html: post.html <span>}</span><span>}</span> />
</code></pre>
<p>を</p>
<pre><code>{
renderAst(post.htmlAst)
}
</code></pre>
<p>に変更する。<br />
あとGraphQLクエリのHTMLをhtmlastに変更する。</p>
<pre><code># ...
markdownRemark(fields: { slug: { eq: $slug } }) {
htmlAst
}
# ...
</code></pre>
<p>そしてマークダウンファイル内に</p>
<pre><code><sample></sample>
</code></pre>
<p>と書く。</p>
<pre><code><sample />
</code></pre>
<p>書きたいがこれでは動かない。注意。<br />
<a href="https://crieit.now.sh/upload_images/ea33ef801970aef5e88a93cffd5577915c4a4ced27c6f.JPG" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/ea33ef801970aef5e88a93cffd5577915c4a4ced27c6f.JPG?mw=700" alt="018-1.JPG" /></a><br />
出来た!<br />
お疲れ様でした。</p>
<h2 id="ハマったところ"><a href="#%E3%83%8F%E3%83%9E%E3%81%A3%E3%81%9F%E3%81%A8%E3%81%93%E3%82%8D">ハマったところ</a></h2>
<p>公式がimport {Sample} form ../という書き方していたのでそこでハマった。</p>
aocory
tag:crieit.net,2005:PublicArticle/14746
2019-01-24T17:23:19+09:00
2019-01-24T17:23:19+09:00
https://crieit.net/posts/GatsbyJS-iframe
GatsbyJSでiframeタグを使う
<h2 id="GatsbyJSでiframeタグを使う"><a href="#GatsbyJS%E3%81%A7iframe%E3%82%BF%E3%82%B0%E3%82%92%E4%BD%BF%E3%81%86">GatsbyJSでiframeタグを使う</a></h2>
<p>ちょっと書評の仕事が来たのでこのブログを書いた。<br />
その時、Amazonリンクを書評だから貼ってしまおう!と言うことで実装した。</p>
<h2 id="gatsby-remark-responsive-iframeを使う"><a href="#gatsby-remark-responsive-iframe%E3%82%92%E4%BD%BF%E3%81%86">gatsby-remark-responsive-iframeを使う</a></h2>
<p>こういうiframeタグを使う場合は、gatsby-remark-responsive-iframeを使う。</p>
<h2 id="gatsby-remark-responsive-iframeをインストール"><a href="#gatsby-remark-responsive-iframe%E3%82%92%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB">gatsby-remark-responsive-iframeをインストール</a></h2>
<p><code>npm install --save gatsby-remark-responsive-iframe</code></p>
<h2 id="gatsby-config.jsmの設定"><a href="#gatsby-config.jsm%E3%81%AE%E8%A8%AD%E5%AE%9A">gatsby-config.jsmの設定</a></h2>
<pre><code>plugins: [
{
resolve: `gatsby-transformer-remark`,
options: {
plugins: [`gatsby-remark-responsive-iframe`],
},
},
]
</code></pre>
<h2 id="実際の動作確認"><a href="#%E5%AE%9F%E9%9A%9B%E3%81%AE%E5%8B%95%E4%BD%9C%E7%A2%BA%E8%AA%8D">実際の動作確認</a></h2>
<p>それではAmazonリンクをiframeで入れてみよう。<br />
widthとheightを入れないと動かないので注意が必要。<br />
<a href="https://crieit.now.sh/upload_images/d4d462fbb8100c0429371e86634903955c4975e57d642.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/d4d462fbb8100c0429371e86634903955c4975e57d642.jpg?mw=700" alt="017-1.jpg" /></a></p>
<p>出来た!</p>
aocory
tag:crieit.net,2005:PublicArticle/14744
2019-01-23T22:35:14+09:00
2019-01-23T22:35:14+09:00
https://crieit.net/posts/GatsbyJS-Markdown-5c486d9261f96
GatsbyJSでMarkdownで画像を表示する
<h2 id="GatsbyJSでMarkdownで画像を表示する"><a href="#GatsbyJS%E3%81%A7Markdown%E3%81%A7%E7%94%BB%E5%83%8F%E3%82%92%E8%A1%A8%E7%A4%BA%E3%81%99%E3%82%8B">GatsbyJSでMarkdownで画像を表示する</a></h2>
<p>Markdownファイルは、</p>
<pre><code>![画像の説明](イメージファイルのパス)
</code></pre>
<p>という形で画像を挿入することができますが、実はそのままだと今くいきません。そこでgatsby-remark-imagesを使用します。</p>
<h2 id="gatsby-remark-imagesのインストール"><a href="#gatsby-remark-images%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB">gatsby-remark-imagesのインストール</a></h2>
<p>npmコマンド一つで終わります。</p>
<pre><code>npm install --save gatsby-remark-images gatsby-plugin-sharp
</code></pre>
<h2 id="gatsby-remark-imagesの設定"><a href="#gatsby-remark-images%E3%81%AE%E8%A8%AD%E5%AE%9A">gatsby-remark-imagesの設定</a></h2>
<p>gatsby-remark-imagesは、gatsby-transformer-remarkのプラグインですので、gatsby-config.jsの中で書く部位が少し異なります。<br />
<code>gatsby-config.js
plugins: [
`gatsby-plugin-sharp`,
{
resolve: `gatsby-transformer-remark`,
options: {
plugins: [
{
resolve: `gatsby-remark-images`,
options: {
// It's important to specify the maxWidth (in pixels) of
// the content container as this plugin uses this as the
// base for generating different widths of each image.
maxWidth: 590,
},
},
],
},
},
]</code></p>
<h2 id="動作確認"><a href="#%E5%8B%95%E4%BD%9C%E7%A2%BA%E8%AA%8D">動作確認</a></h2>
<p>それでは、確認してみましょう。<br />
<a href="https://crieit.now.sh/upload_images/1c85302484d390ae45b121bce4445eb65c486d6a1b9b5.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/1c85302484d390ae45b121bce4445eb65c486d6a1b9b5.jpg?mw=700" alt="016-1.jpg" /></a><br />
ちゃんと表示されていますね。<br />
お疲れさまでした。</p>
aocory
tag:crieit.net,2005:PublicArticle/14743
2019-01-23T12:14:47+09:00
2019-01-23T12:14:47+09:00
https://crieit.net/posts/GatsbyJS-5c47dc27d18c5
GatsbyJSでフォントを変更する
<h2 id="GatsbyJSでフォントをあてる"><a href="#GatsbyJS%E3%81%A7%E3%83%95%E3%82%A9%E3%83%B3%E3%83%88%E3%82%92%E3%81%82%E3%81%A6%E3%82%8B">GatsbyJSでフォントをあてる</a></h2>
<p>ブログの見た目と読みやすさを追求するならやはりフォントにも多少はこだわりたい。<br />
GatsbyJSには、<a target="_blank" rel="nofollow noopener" href="https://kyleamathews.github.io/typography.js/">Typography.js</a>を用いたやり方が公式チュートリアルには記載されている。(本当はtypefaceでやるやり方が最近のGatsby流なのですが、上手く動かなかったのでこちらで実装。)</p>
<h2 id="GatsbyJSに Typography pluginを入れる"><a href="#GatsbyJS%E3%81%AB+Typography+plugin%E3%82%92%E5%85%A5%E3%82%8C%E3%82%8B">GatsbyJSに Typography pluginを入れる</a></h2>
<p><code>npm install gatsby-plugin-typography react-typography typography --save</code></p>
<h2 id="gatsby-config.jsをセッティング"><a href="#gatsby-config.js%E3%82%92%E3%82%BB%E3%83%83%E3%83%86%E3%82%A3%E3%83%B3%E3%82%B0">gatsby-config.jsをセッティング</a></h2>
<p>gatsby-config.jsを以下の様にセッティングする</p>
<pre><code>module.exports = {
siteMetadata: {
title: 'Gatsby Default Starter',
},
plugins: [
{
resolve: `gatsby-plugin-typography`,
options: {
pathToConfigModule: `src/utils/typography`,
}
}
],
}
</code></pre>
<h2 id="typography.jsを作成する"><a href="#typography.js%E3%82%92%E4%BD%9C%E6%88%90%E3%81%99%E3%82%8B">typography.jsを作成する</a></h2>
<p>src/utils/フォルダを作成し、typography.jsをそのフォルダに入れる。</p>
<pre><code>import Typography from "typography"
const typography = new Typography({
baseFontSize: "18px",
baseLineHeight: 1.666,
headerFontFamily: [
"Avenir Next",
"Helvetica Neue",
"Segoe UI",
"Helvetica",
"Arial",
"sans-serif",
],
bodyFontFamily: ["Georgia", "serif"],
})
export default typography
</code></pre>
<h2 id="layouts.cssを全部消す。"><a href="#layouts.css%E3%82%92%E5%85%A8%E9%83%A8%E6%B6%88%E3%81%99%E3%80%82">layouts.cssを全部消す。</a></h2>
<p>layouts.cssには色々なCSSがまだ入っているので全部消してみる。<br />
すると以下の様になる。<br />
<a href="https://crieit.now.sh/upload_images/6ea3d1de2e0a325b5f749ee7b9e829e85c47dbb1b5ff8.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/6ea3d1de2e0a325b5f749ee7b9e829e85c47dbb1b5ff8.jpg?mw=700" alt="015-1.jpg" /></a><br />
これがインストールとセッティングが終わるとこうなる。<br />
<a href="https://crieit.now.sh/upload_images/2bf4a9731c1868abf11db68869177e205c47dbc3ee86b.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/2bf4a9731c1868abf11db68869177e205c47dbc3ee86b.jpg?mw=700" alt="015-2.jpg" /></a><br />
これでフォント問題も解決しました。</p>
aocory
tag:crieit.net,2005:PublicArticle/14742
2019-01-23T09:17:18+09:00
2019-01-23T09:17:18+09:00
https://crieit.net/posts/GatsbyJS-fontawesome
GatsbyJSでfontawesomeを使う
<h2 id="ブログのUI開発に必要なやつ"><a href="#%E3%83%96%E3%83%AD%E3%82%B0%E3%81%AEUI%E9%96%8B%E7%99%BA%E3%81%AB%E5%BF%85%E8%A6%81%E3%81%AA%E3%82%84%E3%81%A4">ブログのUI開発に必要なやつ</a></h2>
<p>ブログのUI開発にアイコンは、ユーザーの学習コストを下げるという意味で無くてはならないモノだと思っていてその実装をGatsbyではどうするか?について調べた。</p>
<h2 id="結論fontawesomeを採用した。"><a href="#%E7%B5%90%E8%AB%96fontawesome%E3%82%92%E6%8E%A1%E7%94%A8%E3%81%97%E3%81%9F%E3%80%82">結論fontawesomeを採用した。</a></h2>
<ul>
<li><a target="_blank" rel="nofollow noopener" href="https://github.com/react-icons/react-icons">react-icons</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://github.com/FortAwesome/react-fontawesome">react-fontawesome</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://github.com/andreypopp/react-fa">react-fa</a><br />
実装アイコン数はreact-iconsが最も多くGithubのスター数も多い。しかし、個人で作る上で必要なアイコンはそこまで多くない。あとfontawesomeのバージョンが4系だった(最新は5系)ので5系に対応しているreact-fontawesomeを実装していくことにする。</li>
</ul>
<h2 id="GatsbyJSにインストール"><a href="#GatsbyJS%E3%81%AB%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB">GatsbyJSにインストール</a></h2>
<pre><code>$ npm i --save @fortawesome/fontawesome-svg-core
$ npm i --save @fortawesome/free-solid-svg-icons
$ npm i --save @fortawesome/react-fontawesome
</code></pre>
<p>これでOK。fortawesomeはスペルミスじゃないので安心して欲しい。<br />
gatsbyのプラグインじゃないのでgatsby-config.jsはの変更不要。</p>
<h2 id="fontawesomeを早速使ってみる"><a href="#fontawesome%E3%82%92%E6%97%A9%E9%80%9F%E4%BD%BF%E3%81%A3%E3%81%A6%E3%81%BF%E3%82%8B">fontawesomeを早速使ってみる</a></h2>
<p>index.jsを修正し動作確認をする。</p>
<pre><code>import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faCoffee } from '@fortawesome/free-solid-svg-icons'
</code></pre>
<p>ここの部分でフォントを読み込む。fontawesomeは、直接CDNで読み込んでやるとサイズが大きくGoogleの計測ツールで見るとPageSpeedが著しく下がる。このコンポーネントだと使うフォントだけを抜き出してサブセットを作って書き出してくれる。最高。Layoutに入れ込んでしまえば管理楽になりそう。<br />
あとは、適当な位置にタグを入れて確認しよう。</p>
<pre><code><FontAwesomeIcon icon={faCoffee} />
</code></pre>
<p><a href="https://crieit.now.sh/upload_images/7e487cd8811144020c4443b5fdc3424c5c47b251e9db6.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/7e487cd8811144020c4443b5fdc3424c5c47b251e9db6.jpg?mw=700" alt="0141.jpg" /></a><br />
GatsbyJSでfontawesomeを上手く表示できた!<br />
これでイケそうだ。</p>
aocory