はじめに
最初は単にGraphQL、gRPC、ECS、New Relic etc
自分が興味のある技術トピックでHello World Enterprise Editionをやるだけのつもりだったものの
GraphQL -> ヘッドレスCMS -> ブログ
という連想ゲームの結果、ブログを作るに至りました
仕事でGoを触り始めた頃に着手して
中断を挟みながらゆっくり進めていたこともあって
初期に書いたコードは今見ると...ですが
まず何より完走できて良かったです
また
バックエンドを開発する中で欲しくなったライブラリを
自作してOSSとして公開できたことも
副次的にですがいい経験になりました
技術スタック
バックエンド
- gqlgen
- gRPC
フロントエンド
- Gatsby.js
- yamada-ui
DB
CockroachDB Serverless
AWS
- API Gateway
- ECS(on Fargate)
- S3
- Cloud Front
- DynamoDB
- Lambda
- Cognito
IaC
- CloudFormation
- Terraform
O11y
- New Relic
こだわり
CQRS/Event Sourcing
コマンドをDynamoDB、クエリをCockroachDB Serverlessとしました
ブログの更新はGraphQLのミューテーションで行い
コマンドの受付が完了(DynamoDBへのPut)した段階で即座にレスポンスを返します
コマンドを受け付けると
DynamoDB StreamによってLambdaへ連携され
記事のスナップショットをCockroachDB Serverlessに流します
実際にブログ記事やタグとして参照されているデータはこのスナップショットです
Lambdaはデータの同期が終わったタイミングで
repository dispatch API経由でGitHub Actioesを実行して
そのワークフロー内でGatsby.jsのビルド・デプロイが行われます
Grid Layout
自社のデザイン/フロントエンドの方が激推ししているのでチャレンジしてみました
本質的に理解できるまでには至らず
要所要所で雰囲気ゴリ押し実装してしまった節はあるのですが
grid-template-areasは直感的にレイアウトが組めて使っていて楽しかったです
コメント・リアクション機能
Hugoが公式にフィーチャーしていることもあってか
エンジニアのブログを見ているとDisqusが採用されている例を多く見かけました
個人的に
- お金がかからないこと
- モデレートしやすい
- コメントだけでなくリアクションもできる
をMUSTとしていたため
上記に合致していたgiscusを採用しました
Gatsby.jsで困ったこと
これは何より自前のGraphQLサーバーをデータソースにする事例が殆ど見当たらなかったことです
正直この時点で手詰まりかなとも思ったのですが
外部から取得した画像をGatsbyImageで利用するTipsを参考に
マークダウン文字列からFileNodeを生成することができました
const content = `
---
id: "${articleNode.id}"
title: "${articleNode.title}"
createdAt: "${format(new Date(articleNode.createdAt), "YYYY/MM/DD")}"
updatedAt: "${format(new Date(articleNode.updatedAt), "YYYY/MM/DD")}"
tags: [${articleNode.tags.edges
.map((edge) => {
return `{"id": "${edge.cursor}", "name": "${edge.node.name}"}`;
})
.join(", ")}]
---
${rawContent}`;
const contentNode = await createFileNodeFromBuffer({
buffer: Buffer.from(content),
cache,
createNode,
createNodeId: (): string => {
return `ArticleContent:${articleNode.id}`;
},
hash: createContentDigest(content),
ext: ".md",
});
ただこれだけではMarkdownスキーマが生成されず
Gatsbyエコシステムでremarkができないため
今回は事前に下記のようなスケルトンファイルを用意することで解決しました
---
id: "Noop"
title: "Noop"
createdAt: 1970/01/01
updatedAt: 1970/01/01
tags:
- {
id: "Noop",
name: "Noop"
}
---
Noop
frontmatterフィールドを利用する場合は
スケルトンのfront matter部分も取得するデータと同様のフォーマットで定義する必要があります
今後やりたいこと
gatsby-source-miyamotoday
前述のskelton.md対応はさすがにお粗末なので
Contentful etc ヘッドレスCMSのように
専用のプラグインを作ってみたいです
投稿用のUI
この記事はGraphQLクライアントを使って投稿してます
困っていないといえば困ってないのですが
断筆する原因になりうるので何とかしたいです
通知
非同期レスポンスパターンのため
ブログ自体の更新の成功/失敗はリクエストを送った段階では分かりません
現状、成功・失敗の判断する手段はブログを見る以外にないので
RMUがGitHub Actionsをキックした段階でメール通知してくれるようにしたいです