Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
サーバーレスAPI(API Gateway+Lambda)とNext.jsで 個人ブログを作ろう!
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
shuntaka
July 18, 2024
Technology
2.2k
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
サーバーレスAPI(API Gateway+Lambda)とNext.jsで 個人ブログを作ろう!
shuntaka
July 18, 2024
More Decks by shuntaka
See All by shuntaka
GitHub Copilot CLI が マッスルに馴染むまで / Until GitHub Copilot CLI Becomes Second Nature
shuntaka
1
13k
Claude Code活用時のつらみと隙間を埋めるツール / Tools to bridge the gaps and pains of using Claude Code
shuntaka
0
15k
CloudFront OAC × Lambda Function URLs で作る認証付き簡易サイト / Simple Authenticated Website Built with CloudFront OAC and Lambda Function URLs
shuntaka
0
3.3k
顧客体験を加速させるチャットボットで始めるAIエージェント入門 / Introduction to AI Agents: Starting with Chatbots to Accelerate Customer Experience
shuntaka
1
3.7k
AI SDKで作るチャットボット開発 / Chatbot Development with AI SDK
shuntaka
0
1.7k
Claude Codeチーム活用の現在地 〜小さな実践と今後の展望〜 / Current State of Claude Code Team Adoption - Small Practices and Future Prospects
shuntaka
2
8.3k
Claude Codeをdotfiles管理しよう! / Let's Manage Claude Code with Dotfiles!
shuntaka
8
21k
個人プロジェクトをKiroベースに 乗り換えてみた / I Tried Migrating My Personal Project to Kiro-based
shuntaka
0
2.7k
AI駆動開発がもたらす革新と実践 / Innovation and Practice Brought by AI-Driven Development
shuntaka
2
2.2k
Other Decks in Technology
See All in Technology
不要なレビューをAIにまかせて AIコーディングの環境改善を加速した
shoota
1
230
iAEONの段階的リアーキテクト戦略 / iAEON's_Gradual_Re-architecture_Strategy
aeonpeople
0
230
Flow 不死:AI 時代 DevOps 的不變本質
cheng_wei_chen
2
340
新しいUbuntu/GNOMEが使いたいからXからWaylandへ移行頑張ってるの巻 2026-06-20
nobutomurata
0
150
GitHub Copilot app最速の発信の裏側
tomokusaba
1
200
Kubernetesにおける学習基盤とLLMOpsの概要
ry
1
320
AI時代のコスト管理を考えよう〜明日から使える実践AWSノウハウ~
yoshimi0227
0
320
PostgreSQL 19 新機能概要 OSC Hokkaido 2026
nori_shinoda
0
160
自分が詳しくない領域でAIを使う #プロヒス2026
konifar
16
5.5k
iOS アプリの「これって不具合ですか?」を AI に調べてもらう
miichan
0
100
2026TECHFRESH畢業分享會 - Lightning Talk - 打造精準高效的 MCP 設計模式與測試實務
line_developers_tw
PRO
0
1.3k
AI駆動開発を通して感じた、 AI時代のデザイナーの役割変化
whisaiyo
4
2.3k
Featured
See All Featured
A designer walks into a library…
pauljervisheath
211
24k
Abbi's Birthday
coloredviolet
2
8.1k
Crafting Experiences
bethany
1
180
The Impact of AI in SEO - AI Overviews June 2024 Edition
aleyda
5
1.1k
Leo the Paperboy
mayatellez
7
1.8k
Noah Learner - AI + Me: how we built a GSC Bulk Export data pipeline
techseoconnect
PRO
0
200
Build your cross-platform service in a week with App Engine
jlugia
234
18k
Lightning talk: Run Django tests with GitHub Actions
sabderemane
0
200
Optimising Largest Contentful Paint
csswizardry
37
3.7k
Java REST API Framework Comparison - PWX 2021
mraible
34
9.4k
Why Mistakes Are the Best Teachers: Turning Failure into a Pathway for Growth
auna
0
160
Embracing the Ebb and Flow
colly
88
5.1k
Transcript
サーバーレスAPI(API Gateway+Lambda)とNext.jsで 個⼈ブログを作ろう! 2024.7.20 製造ビジネステクノロジー部 髙橋俊⼀ a.k.a. shuntaka
⾃⼰紹介 2 shuntaka/髙橋俊⼀ 19年8⽉クラメソ⼊社 製造ビジネステクノロジー部 基本的にAWSでサーバーサイド開発 ‧IoTバックエンド/エッジソフトウェア開発 ‧サーバレス/コンテナ開発 ‧データ基盤開発 ツール開発:
ddbrew/gh-p2/oax/s3-concat/preview-asciidoc.vim … shuntaka.dev/who
3 「Speakerdeck shuntaka」で検索 or https://spekerdeck.com/shuntaka
ご理解頂きたいこと 4 ‧フロントエンド/デザインは、サーバサイドエンジニアが 頑張ってみた...くらいの温度感で、要素少なめです😿 ‧サーバーレスAPIと表記しているところは、Amazon API Gateway+AWS LambdaのREST APIを指します
⽬次 5 ‧過去の個⼈ブログ ‧現在の個⼈ブログ ‧経験から学んだこと ‧未来へ向けて ‧まとめ
⽬次 6 ‧過去の個⼈ブログ 👈 ‧現在の個⼈ブログ ‧経験から学んだこと ‧未来へ向けて ‧まとめ
作る経緯 7 2018年前職時代 Web企業のミートアップにポツポツ参加し始め、 参加ブログを書きたくなる🐥 当時Goが好きだったので、静的サイトジェネレータのHugoに興味 を持つ
構成 8 静的サイトジェネレーター(Hugo)を使って構築 (独⾃ドメイン、HTTPS) 2. ビルド‧デプロイ 1. push
外観 9 作った当初は書いていたが、しだいに全く書かなくなり、ドメ イン解約😱
ブログ運⽤が続かなかった理由 10 振り返ると感じた続かない理由 ‧サイト⾃体へ愛着がなかった ‧モチベーションに繋がる仕組みを⾃分が作らなかった
⽬次 11 ‧過去の個⼈ブログ ‧現在の個⼈ブログ 👈 ‧経験から学んだこと ‧未来へ向けて ‧まとめ
作る経緯 12 技術ブログといえばZenn!影響をかなり受けてま す。Zennを触り、個⼈ブログに以下の体験を検証 /実装したいと感じた。 ‧Gitプッシュ後のサイトへ反映速度 ‧記事プレビューの体験の良さ
作る経緯 13 プラスで漠然と思っていたこと ‧⾃分がほぼ毎⽇使うWebアプリを作り たかった(改善欲の刺激) ‧業務でサーバーレスAPIを書いているの で趣味で使いたい ‧技術検証できる庭が欲しい ‧業務でありそうな要件で実装したい
構成 14
構成 15 ・お財布に優しい(ほぼ無料枠運用) ・Vercel/Next.jsのISRとの相性(コールドスタート問題の緩和) ・個人でお手軽にクラサバ構成が取れる ・Fly.io, Deno deploy, Cloudflare workerなどの選択肢
→ 自分の業務シナジーを考慮
外観 16 shuntaka.dev
現在のブログで注⼒したこと 17 ‧Gitプッシュ後サイトへ即反映 ‧記事プレビューの体験の良さ ‧サイト⾃体への愛着 ‧ モチベーションに繋がる仕組み
現在のブログで注⼒したこと 18 ‧Gitプッシュ後サイトへ即反映 👈 ‧記事プレビューの体験の良さ ‧サイト⾃体への愛着 ‧ モチベーションに繋がる仕組み
Gitプッシュ後サイトへ即反映 19 GitHub Appsから直接DBにデータを投⼊することで実現 サイトや過去記事ビルドが必要なくなる
WebアプリからのApps連携 20 ※ GIFなのでPDFだ と再⽣できません
Webアプリからの連携シーケンス 21 https://shuntaka.dev/shuntaka/articles/01ezm5k2rt1jm6zbsewm33r0xw
Webhook検証 22 Webhookの検証もしておく と安全 ‧GitHubでwebhookシーク レットを指定 ‧ボディ部を上記を使い HMAC-SHA256でハッシュ ‧X-Hub-Signature-256と⼀ 致検証
Webhookのトラブルシューティング 23 GitHub Apps上からペイロードの確認可能
現在のブログで注⼒したこと 24 ‧Gitプッシュ後サイトへ即反映 ‧記事プレビューの体験の良さ 👈 ‧サイト⾃体への愛着 ‧ モチベーションに繋がる仕組み
記事プレビューの体験の良さ 25 静的サイトジェネレータのファイルシステム変更監視による プレビューは顧客が求めていたもの...⾃作するならどうする か... エディタにより依存させれば、汎⽤性はないが良い体験が⽣ まれそう...
マークダウンパーサー 26 ‧Rustで⾃作を試みるが断念。markdown-itを拡張 ‧困ったらzenn-dev/zenn-editorの実装を参考にさせて頂い ている... ‧独⾃で欲しい機能を拡張できる(PlantUML,SpeakerDeckの 指定スライドプレビューなど) ‧今後⾔語処理系の学習でリベンジしたい...
Vimとの連携 27 denops.vim Vim/NeovimプラグインをTypeScript(deno) で書けるというエコシステム denoはnpmのパッケージと互換性があるた め、前述パーサーを流⽤できる
リアルタイムプレビュー(Vim/Neovim) 28
リアルタイムプレビュー(Vim/Neovim) 29 ※ GIFなのでPDFだ と再生できません
現在のブログで注⼒したこと 30 ‧Gitプッシュ後サイトへ即反映 ‧記事プレビューの体験の良さ ‧サイト⾃体への愛着 👈 ‧ モチベーションに繋がる仕組み
作って気づく愛着 31 結論、⾃分でデザインして時間をかけることで愛着が醸成さ れた。 これは意識して訳ではなく、Next.jsでやると決めた瞬間デザ インは必要に迫られ、やらざるを得なかった。
デザイン 32 Figmaの学習。⾼評価のUdemyの動画を⼿を動かしながら慣 れていく。(※ 2020年時点なので注意)
デザイン 33 オブジェクトコネコネ...⽇曜⼤⼯感...
ダークモード 34 CSS Variablesを使って作成 配⾊はGitHubのダークモー ドを参考に
OGP 35 ‧サムネイル設定 → そのまま表⽰ ‧サムネイル未設定→タイトル⽂字列をCloudinaryのURL/画像 に埋込 → URLは署名を含められる 任意の⼈が⽂字列を埋め込むことはできない
現在のブログで注⼒したこと 36 ‧Gitプッシュ後サイトへ即反映 ‧記事プレビューの体験の良さ ‧サイト⾃体への愛着 ‧ モチベーションに繋がる仕組み 👈
アクセス解析導⼊ 37 ‧Google Analytics ‧Search Console連携
必要なこと 38 静的サイトジェネレータならデフォルトである。流⽯。 ‧sitemap⽣成(->Search Consoleへ登録) ‧RSS⽣成
現在のブログで注⼒したこと 39 ‧Gitプッシュ後サイトへ即反映 ‧記事プレビューの体験の良さ ‧サイト⾃体への愛着 ‧ モチベーションに繋がる仕組み
⽬次 40 ‧過去の個⼈ブログ ‧現在の個⼈ブログ ‧経験から学んだこと 👈 ‧未来へ向けて ‧まとめ
サービス運⽤する楽しさ 41 ‧⾃⼰表現と振り返りの楽しみ ‧特定の⼈にしか⾒られない⼼理的安全性 ‧ちゃんと書いた記事はオーガニック検索流⼊ ‧検索パフォーマンスから読者の興味を分析 ‧意外な⼈気記事の発⾒(例:Zig⾔語、platformio記事)
技術を試す遊び場 42 ‧利害関係者がいないため、新しいライブラリや開発⼿法を 試しやすい ‧既存システムで試すことで、使うだけとは異なった視点(開 発や運⽤に適⽤した場合)の体験が得られる ‧いろんなサイトを参考にするようになる。プラックティス の塊。(今回だとGitHub/Zenn/Qiitaなど...) ‧ある程度⼈にみられることを考慮された動くサンプルが⼿ 元にあるメリット
必要は発明の⺟ 43 ‧無から必要を⽣み出すのは難しい ‧ブログ開発/運⽤することで必要が⽣まれやすい ‧可処分時間やお財布を考えて⼯夫の余地を探す等 通して、様々ブログ記事やCLI開発をした... 詳細は過去記事で
実際作りっぱなし... 44 ‧最初は熱中、その後はライブラリ、ランタイム更新対応 ‧業務や登壇の機会を利⽤してブースト ‧⾃分が興味あること/ないことのメタ認知
SaaS周りの注意は必須... 45 ‧スマホ未圧縮画像配信で、ネットワーク帯域を使いすぎて料 ⾦発⽣経験 ‧クレカ登録不要でもお試し系は、解約忘れ注意。⾃動停⽌ しない場合あり、プロジェクトが消せず、放置期間含めて請求 が発⽣したり、、 → 契約とGoogleカレンダー登録は同時に ‧新興の海外系SaaSだとサポートもあまり期待は出来ない
セッション概要 46 ‧過去の個⼈ブログ ‧現在の個⼈ブログ ‧経験から学んだこと ‧未来へ向けて 👈 ‧まとめ
登場するコードはこちらに 47 https://github.com/shuntaka9576/devio2024-sample-code
試したいこと 48 技術選定をしたのは4年前なのでリプレースするために、技術検 証してみる ‧同じ解決策でも新しいやり⽅へ ‧今⾃分がワクワクする構成へ
試したいこと 49 ‧サーバサイドJSマルチランチタイム ‧エコシステムの成⻑への追従 ‧認証 ‧認知負荷へ対応
試したいこと 50 ‧サーバサイドJSマルチランチタイム 👈 ‧エコシステムの成⻑への追従 ‧認証 ‧認知負荷へ対応
JSランタイムの選択肢 51 WinterCGによる⾮Webブラウ ザJSランタイム標準化の流れ Deno/Bun/Node.jsの三つ巴 開発者体験はまだNode.jsの印 象。今後は分からない。 Node.jsを使いつつ、乗り換え 可能な選択肢を持つ。
HTTPサーバー/ルーティング 52 Honoを利⽤(Lambda⽬線だとHTTPサーバー部分は含まない) ‧作ったアプリがコンテナや別JSランタイム上で検証可 ‧活発なコミュニティ ‧Web標準API/マルチランタイム → ミドルウェア含めランタイム互換性が⾼い → 利⽤者‧開発者⼈⼝が多くなりそう(?)
→ エコシステムが充実しそう!
試したいこと 53 ‧サーバサイドJSマルチランチタイム ‧エコシステムの成⻑への追従 👈 ‧認証 ‧認知負荷へ対応 ‧その他
Nodeエコシステム 54 ⾼速なツールチェインの採⽤ ‧pnpm → 並列実⾏ヘルパー不要なので使っているが、拘りなし(多様 性がありそう) ‧Biome(Rust製で⾼速) → 異次元な速さ+LSPで最⾼。BE的には⼗分。
ESMを使う 55 ESMしかサポートしないライブラリも少なくない CDKもtsx経由で実⾏すればESMで実⾏可能 // cdk.json { "app": "pnpm tsx
bin/cdk.ts" … }
56 const getConfig = async (): Promise<Config> => { const
secretsAndVariables = await getVariablesAndSecrets(); const parseResult = configSchema.safeParse({ auth: { rpID: secretsAndVariables.variables.rpId, rpName: secretsAndVariables.variables.cookieDomain, }, ... }); ... return parseResult.data; }; export const config = await getConfig(); ESMを使う to level awaitの活⽤ ‧起動時環境変数 /SSM取得&バリデー ション(設定し忘れ防 ⽌) ‧以後config変数を Lambdaでグローバル 変数キャッシュ
モノレポ構成 57 CIの⼀部共通化やリポジ トリ間のCDが少なくな り良い。 GHAは数年で共通化の余 地が増えた。横展可能な 秘伝タレを作ると良い。 ‧Reusing workflows
‧Composite action name: Setup node description: Setup Node and restore cache runs: using: 'composite' steps: - uses: actions/setup-node@v4 with: node-version-file: './.node-version' - uses: pnpm/action-setup@v4 - name: Restore node modules uses: actions/cache@v4 id: cache_dependency env: cache-name: cache-dependency with: path: '**/node_modules' key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('pnpm-lock.yaml') }} - name: Install node modules
試したいこと 58 ‧サーバサイドJSマルチランチタイム ‧エコシステムの成⻑への追従 ‧認証 👈 ‧認知負荷へ対応 ‧その他
認証 59 ‧Firebase Authenticationを採⽤ ‧⾃分⽤にダッシュボードが欲しくて実装
認証 60 パスワード⼊れるの⾯倒問題
パスキーの検証 61 技術検証でWebAuthnの仕様を使ったパスキー認証を試す ライブラリは以下を利⽤ ‧hono_session(Honoミドルウェア) ‧SimpleWebAuthn SimpleWebAuthnのexampleを動かしつつ流れを把握... ただ、永続化していないので、DynamoDBで永続化
パスキーの検証 62 ‧challengeをユーザーのデバイ ス(認証器)に 保存された秘密鍵で 署名を作成 ‧サービス側で保存された公開鍵 を⽤いて認証
パスキーの検証 63 ※ GIF iCloudキーチェーンを使って、 ⽣体認証でサインアップ/ログイン デモ iCloudキーチェーンで同期される ため、Mac/iPhoneでログイン可
試したいこと 64 ‧サーバサイドJSマルチランチタイム ‧エコシステムの成⻑への追従 ‧認証 ‧認知負荷へ対応 👈 ‧その他
⾃作ブログは開発頻度にムラあり 65 実際に⾃作ブログの開発頻度はときどきになるので、できれ ば認知負荷を下げたい... try! catch! error! unknown! 😱
関数型スタイルTypeScript 66
関数型スタイルTypeScript 67 ‧neverthrow ‧fp-ts(Effectと統合) ‧Effect → Effectを試す
Effectとは 68 関数型プログラミングの影響を受けて以下をサポート ‧最⼤限の型安全性(エラー処理を含む) ‧テストユーテリティ ‧o11y機能 エコシステムが重厚⻑⼤
69 Effectを試す interface Effect<Success, Failure = never, Requirements = never>
成功時の型 依存するデータ型 (本セッションでは割 愛) 失敗時の型 Effect型について。近いのがRustのResult型。
70 Effectを試す 関数の合成 1 つの関数の出力を受け取り、それをパイプライン内の次の関 数の入力として渡します。これにより、複数の関数を連結して複 雑な変換を構築
71 Effectを試す const effects = pipe( { isLoggedIn: session.get('isLoggedIn'), userID:
session.get('userID'), }, Schema.decodeUnknownEither(toValidSchema), Effect.flatMap(workflow) ); const result = await Effect.runPromise(effects); pipeを使って関数を合成する
72 const effects: Effect.Effect<{ isLoggedIn: boolean; user: { userName: string;
}; }, DataBaseUnknownError | ParseError | NotFoundUserError, never> 先ほどのeffects変数の型推論。赤枠がハンドリングされていない ことが自明。副作用の存在が分かる。 Effectを試す
73 関数の振る舞いを予測可能に 関数ができることはすべて、その シグネチャに書かれている。関数 は引数を受け取り、値を返す。そ れ以外は特にないもしない。/ (2.12. 信頼される純粋関数より) → 関数の振る舞いを予測可能に
し、副作用を避ける
74 const effects = pipe( ... Effect.match({ onSuccess: (result) =>
({ status: 200, body: { isLoggedIn: result.isLoggedIn, user: result.user }, }), onFailure: (error) => { switch (error._tag) { case 'ParseError': return { status: 200, body: { isLoggedIn: false } }; case 'NotFoundUserError': return { status: 400, body: { isLoggedIn: false } }; case 'DataBaseUnknownError': return { status: 500, body: { code: 'InternalServerError' } }; } }, }) ); エラーハンドリング漏れを防ぐことができる。日曜大工も安心。 ハンドリングをすれば、 第⼆引数はnever型に Effectを試す
試したいこと 75 ‧サーバサイドJSマルチランチタイム ‧エコシステムの成⻑への追従 ‧認証 ‧認知負荷へ対応 ‧その他 👈
76 その他やってみたいこと ‧画像の最適化をしてネットワーク帯域を減らしたい ‧スライド機能 ‧全⽂検索(meilisearch, algoria)
77 その他やってみたいこと ベアメタルk8sに載せたい →
⽬次 78 ‧過去の個⼈ブログ ‧現在の個⼈ブログ ‧経験から学んだこと ‧未来へ向けて ‧まとめ 👈
まとめ 79 過去 現在 未来?
まとめ 80 ‧ブログの運⽤(アクセス解析/SEO/デザイン) ‧技術試す遊び場(調査/検証/改善/業務/メタ認知) ‧発明(ブログ執筆/登壇ネタ/ツール開発)
ご清聴ありがとうございました& お付き合い頂きありがとうござ いました🥹 81
レビュー協⼒/参考⽂献 82 レビュー協⼒ ‧Kyo さん (とっ散らかっていたところをまとめて下さり圧倒的感謝!) 参考⽂献 ‧Zennを⽀える技術とサービス構成 ‧TSKaigi関連 ‧TypeScript
関数型スタイルでバックエンド開発のリアル ‧Step by Stepで学ぶ、ADT(代数的データ型)、モナドからEffect-TSまで゙ ‧複雑なビジネスルールに挑む:正確性と効率性を両⽴するfp-tsのチーム活⽤術 ‧Effectで作る堅牢でスケーラブルなAPIゲートウェイ ‧Deno Deploy で WebAuthn を使ったサイトを作ってみた ‧パスキーのすすめ
83