りゅーそう
元高校地歴科教員。現在microCMSでエンジニアをしています。
Saitama.jsというLT会を運営中です。
発言はすべて個人の意見です。
gatsby
microcms
typescript
2020/05/12
2022/01/23
今回はGatsbyについての話題です。
特に新しい情報ではなく、「巨人の肩に乗る」的なやつでしょうか。Gatsbyでなかなか良いブログの開発体験が得られたので共有しようと思います。
以下の記事をmicroCMSを用いてやってみましたという記事です。
[Gatsby.jsを完全TypeScript化する]
上記のリンクを読んでください。
GatsbyのメリットとしてgraphQLを用いてデータ取得ができるということが挙げられます(独特な書き方でもあるため、毛嫌いされる一要因にもなっていますが)。Gatsbyを使用するのであれば、このgraphQLのメリットを生かして型安全なコードをできるだけ楽に書きたいというモチベーションがありました。
そういった意味でも上記の記事はとても良かったです。
gatsbyを知らない方のために以前記事を書きました。こちらで概要を掴んでみてください。
JamstackなWebサイト制作
上記のような画面をgatsby developコマンドで表示させることができます。
お使いのheadlessCMSやAPIの情報と紐づけることでブラウザ上でgraphQLのクエリを定義したり、試すことができます。図はmicroCMSで作成したAPIを叩いた様子です。
①で試したクエリを実際にコードで定義していきます。
const query = `
{
allMicrocmsPosts {
edges {
node {
postsId
title
tags {
id
name
}
day
image {
url
}
content
}
}
}
}
`;
このように定義したスキーマからgatsby-plugin-graphql-codegenを用いて型を自動生成することができます。
参考:gatsby-plugin-graphql-codegen
gatsby-plugin-graphql-codegenの使用方法などは冒頭の参照記事に詳しいのでそちらをご参照ください。
当記事では、microCMSでのユースケースを紹介したいと思います。
microCMSをGatsbyで使用するにはgatsby-source-microcmsというプラグインを使用します。
使用方法は公式をご参照ください。
gatsby-source-microcms
gatsby-plugin-graphql-codegenを使用し、元記事のように設定を行うと、ビルド時にgraphql-types.tsファイルが自動生成されます。
これを使用して、型定義を行うことができます。
例えば、このようなクエリをエクスポートします(例は私が作成したmicroCMSで作成したブログのデータ一覧を取得するクエリです)。
export const pageQuery = graphql`
query PagePosts {
allMicrocmsPosts {
edges {
node {
id
postsId
title
day
tags {
id
name
}
image {
url
}
}
}
}
}
`;
すると、
//graphql-types.ts
export type PagePostsQuery = { allMicrocmsPosts: { edges: Array<{ node: (
Pick<MicrocmsPosts, 'id' | 'postsId' | 'title' | 'day'>
& { tags?: Maybe<Array<Maybe<Pick<MicrocmsPostsTags, 'id' | 'name'>>>>, image?: Maybe<Pick<MicrocmsPostsImage, 'url'>> }
) }> } };
このようなクエリがビルド時に自動生成されます。これを用いて以下のようなコードを書いてみます。
//src/pages/posts.tsx
import * as React from 'react';
import { graphql, Link } from 'gatsby';
import { PagePostsQuery } from '../../graphql-types';
type Props = {
data: PagePostsQuery;
};
const Posts: React.FC<Props> = ({ data }) => (
<div>
<h1>Post Page</h1>
{data.allMicrocmsPosts?.edges?.map((edge) => {
const posts = edge.node;
return (
<React.Fragment key={posts.id}>
<div>
<Link to={`/posts/${posts.postsId}`}>
<h2>{posts.title}</h2>
</Link>
<div>
{posts?.tags?.map(
(tag) =>
tag?.id && (
<React.Fragment key={tag.id}>
<span>{tag.name}</span>
</React.Fragment>
),
)}
</div>
<p>{posts.day}</p>
{posts?.image?.url && (
<img src={posts.image.url} />
)}
</div>
</React.Fragment>
);
})}
</div>
);
export const pageQuery = graphql`
query PagePosts {
allMicrocmsPosts {
edges {
node {
id
postsId
title
day
tags {
id
name
}
image {
url
}
}
}
}
}
`;
export default Posts;
コードをホバーすると以下の画像のように型が適用され、型安全なコードが実現されているのがわかります。
graphqlを使用する際にはoptional Chainingは必須です。画像のようにnull checkを行う場合には使用して簡潔なコードを書けるようにしましょう(もっと良い書き方あれば指摘お願いします)。
optional Chainingについては以下の記事がおすすめです。
そろそろJavaScriptに採用されそうなOptional Chainingを今さら徹底解説
元記事をご参照ください。
microCMSでブログデータの型を参照するには
MicrocmsPostsConnection, MicrocmsPosts という型を使用しました。
//graphql-types.ts
export type MicrocmsPosts = Node & {
id: Scalars['ID'];
parent?: Maybe<Node>;
children: Array<Node>;
internal: Internal;
createdAt?: Maybe<Scalars['Date']>;
updatedAt?: Maybe<Scalars['Date']>;
title?: Maybe<Scalars['String']>;
tags?: Maybe<Array<Maybe<MicrocmsPostsTags>>>;
day?: Maybe<Scalars['Date']>;
image?: Maybe<MicrocmsPostsImage>;
content?: Maybe<Scalars['String']>;
postsId?: Maybe<Scalars['String']>;
};
export type MicrocmsPostsConnection = {
totalCount: Scalars['Int'];
edges: Array<MicrocmsPostsEdge>;
nodes: Array<MicrocmsPosts>;
pageInfo: PageInfo;
distinct: Array<Scalars['String']>;
group: Array<MicrocmsPostsGroupConnection>;
};
良さげですね。graphql-codegenで生成される型定義はnull checkが厳格です(一長一短ですが)。
厳格にTypeScriptを導入してみたい方はお試しください。
あと単純に生成されるコードを読むと勉強になるかなあと思います。
元記事がとても素晴らしいので、そちらも読んでください。良い記事をありがとうございます。
TypeScript導入の際にとても参考になりました。
ただ、null checkが厳格なので単純なブログサイトを作成するには少し工夫が必要かも知れません。
個人的には初期設定をすればあとはvsCodeでの自動補完、TypeScriptでの補完も聞くので開発体験は最高でした。
データの型も保障されますし。
サンプルコードは以下をご参照ください。
GitHub