[{"data":1,"prerenderedAt":365},["ShallowReactive",2],{"blog-ja-2025-12-14-nuxt-blog-architecture":3},{"id":4,"title":5,"body":6,"category":346,"date":347,"description":348,"draft":349,"extension":350,"lang":351,"meta":352,"navigation":358,"path":359,"seo":360,"sitemap":361,"slug":362,"stem":363,"updated":347,"__hash__":364},"blog/blog/ja/2025-12-14-nuxt-blog-architecture.md","Nuxt 4 + @nuxt/content + Vercel：個人ブログにおける技術選定とアーキテクチャ設計",{"type":7,"value":8,"toc":334},"minimark",[9,13,16,19,22,25,38,43,66,70,73,76,87,91,94,97,108,111,115,123,126,130,133,136,147,151,154,157,165,168,172,175,186,190,193,196,207,210,221,224,232,311,315,323,327,330],[10,11,12],"p",{},"本記事はチュートリアルではなく、\nプロジェクト開始時に行った技術選定の記録です。",[10,14,15],{},"このブログの目的は UI の実験やフレームワーク学習ではなく、\n長期的に文章と技術知見を蓄積するためのプラットフォームを構築することです。",[10,17,18],{},"アーキテクチャの観点から見ると、本ブログは典型的な\ncontent-driven site（コンテンツ駆動型サイト）です。",[10,20,21],{},"目的は、コンテンツ制作・パフォーマンス・運用コストの\n長期的なバランスを維持することにあります。",[10,23,24],{},"そのため技術選定では以下を重視しました：",[26,27,28,32,35],"ul",{},[29,30,31],"li",{},"長期的な保守性",[29,33,34],{},"Content-first な設計",[29,36,37],{},"低い運用コスト",[39,40,42],"h2",{"id":41},"技術スタック概要","🧭 技術スタック概要",[26,44,45,48,51,54,57,60,63],{},[29,46,47],{},"Framework: Nuxt 4",[29,49,50],{},"Content: @nuxt/content",[29,52,53],{},"UI: @nuxt/ui + Tailwind",[29,55,56],{},"i18n: @nuxtjs/i18n",[29,58,59],{},"Image: @nuxt/image + build metadata",[29,61,62],{},"Deploy: Vercel",[29,64,65],{},"Analytics：Google Analytics (GA4)",[39,67,69],{"id":68},"なぜ-nuxt-4-なのか","🚀 なぜ Nuxt 4 なのか",[10,71,72],{},"SSG と比較すると、\n継続的に更新される developer blog において\nSSR はより安定した初期表示性能と SEO を提供します。",[10,74,75],{},"主な理由：",[26,77,78,81,84],{},[29,79,80],{},"SSR が標準で統合されている",[29,82,83],{},"ルーティングとレイアウトが規約ベース",[29,85,86],{},"コンテンツ・画像・i18n との高い統合性",[39,88,90],{"id":89},"nuxtcontent-を採用した理由","📝 @nuxt/content を採用した理由",[10,92,93],{},"ブログは本質的にコンテンツプロダクトです。",[10,95,96],{},"重視した点：",[26,98,99,102,105],{},[29,100,101],{},"Markdown 執筆体験",[29,103,104],{},"Git 管理",[29,106,107],{},"多言語コンテンツ管理",[10,109,110],{},"この構成は static-first architecture に近く、\nStrapi や Contentful のような Headless CMS の\n運用コストを回避できます。",[39,112,114],{"id":113},"ui-レイヤー","🎨 UI レイヤー",[26,116,117,120],{},[29,118,119],{},"一貫性を優先",[29,121,122],{},"必要に応じてカスタマイズ",[10,124,125],{},"@nuxt/ui が基盤コンポーネントを提供し、\nTailwind がデザイン調整を担います。",[39,127,129],{"id":128},"i18n-をアーキテクチャの中核へ","🌍 i18n をアーキテクチャの中核へ",[10,131,132],{},"初期段階から多言語対応（zh / ja / en）を前提に設計。",[10,134,135],{},"利点：",[26,137,138,141,144],{},[29,139,140],{},"ルーティングと言語構造の一致",[29,142,143],{},"locale ベースのコンテンツ管理",[29,145,146],{},"UI と記事の独立進化",[39,148,150],{"id":149},"画像最適化戦略","🖼 画像最適化戦略",[10,152,153],{},"画像はパフォーマンス上の主要リスクです。",[10,155,156],{},"二層構成：",[26,158,159,162],{},[29,160,161],{},"@nuxt/image による表示最適化",[29,163,164],{},"ビルド時のメタデータ生成",[10,166,167],{},"事前にサイズを定義することで\nCumulative Layout Shift（CLS）を効果的に削減できます。",[39,169,171],{"id":170},"️-vercel-でのデプロイ","☁️ Vercel でのデプロイ",[10,173,174],{},"理由：",[26,176,177,180,183],{},[29,178,179],{},"Nuxt との高い親和性",[29,181,182],{},"Preview 環境",[29,184,185],{},"低運用コスト",[39,187,189],{"id":188},"analyticsgoogle-analytics-ga4","📊 Analytics：Google Analytics (GA4)",[10,191,192],{},"コンテンツサイトを継続的に改善していくためには、\nフィードバックループの存在が欠かせません。\nアクセス解析ツールとしては、\nデプロイプラットフォームに付属する分析機能ではなく、\nGoogle Analytics (GA4) を採用しています。",[10,194,195],{},"主な理由は次の3つです。",[26,197,198,201,204],{},[29,199,200],{},"コンテンツサイトの分析において GA4 はより成熟しており、取得できるデータの粒度も豊富である",[29,202,203],{},"アクセスデータを長期間保存でき、コンテンツの傾向を継続的に観察できる",[29,205,206],{},"プラットフォームと疎結合であり、特定のホスティングサービスに依存しない",[10,208,209],{},"個人ブログにおいて、実際に必要な分析内容はそれほど複雑ではありません。",[26,211,212,215,218],{},[29,213,214],{},"どの記事が継続的に読まれているのか",[29,216,217],{},"ユーザーは主にどの国・地域からアクセスしているのか",[29,219,220],{},"どのテーマのコンテンツに関心が集まっているのか",[10,222,223],{},"GA4 はイベントベースのデータモデルを採用しており、\n従来のアクセス解析よりも構造は複雑ですが、\nブログのようなサイトでは基本的なページビュー計測だけでも十分な分析が可能です。",[10,225,226,227,231],{},"Nuxt プロジェクトへの GA4 の導入も比較的簡単で、\n",[228,229,230],"code",{},"nuxt-gtag"," モジュールを利用すればアプリケーションレベルで統一的に組み込むことができます。",[233,234,239],"pre",{"className":235,"code":236,"language":237,"meta":238,"style":238},"language-ts shiki shiki-themes github-light github-light github-dark","// nuxt.config.ts\nexport default defineNuxtConfig({\n  modules: [\"nuxt-gtag\"],\n  gtag: {\n    id: \"G-XXXXXXXXXX\",\n  },\n});\n","ts","",[228,240,241,250,268,281,287,299,305],{"__ignoreMap":238},[242,243,246],"span",{"class":244,"line":245},"line",1,[242,247,249],{"class":248},"sCsY4","// nuxt.config.ts\n",[242,251,253,257,260,264],{"class":244,"line":252},2,[242,254,256],{"class":255},"s8jYJ","export",[242,258,259],{"class":255}," default",[242,261,263],{"class":262},"snPdu"," defineNuxtConfig",[242,265,267],{"class":266},"sxrX7","({\n",[242,269,271,274,278],{"class":244,"line":270},3,[242,272,273],{"class":266},"  modules: [",[242,275,277],{"class":276},"sIIMD","\"nuxt-gtag\"",[242,279,280],{"class":266},"],\n",[242,282,284],{"class":244,"line":283},4,[242,285,286],{"class":266},"  gtag: {\n",[242,288,290,293,296],{"class":244,"line":289},5,[242,291,292],{"class":266},"    id: ",[242,294,295],{"class":276},"\"G-XXXXXXXXXX\"",[242,297,298],{"class":266},",\n",[242,300,302],{"class":244,"line":301},6,[242,303,304],{"class":266},"  },\n",[242,306,308],{"class":244,"line":307},7,[242,309,310],{"class":266},"});\n",[39,312,314],{"id":313},"️-トレードオフ","⚖️ トレードオフ",[26,316,317,320],{},[29,318,319],{},"依存関係の更新管理",[29,321,322],{},"多言語運用コスト",[39,324,326],{"id":325},"結論","✅ 結論",[10,328,329],{},"本構成は developer blog architecture の実践例であり、\n技術的な複雑さではなく、\n長期的なコンテンツ生成を支えることを目的としています。",[331,332,333],"style",{},"html pre.shiki code .sCsY4, html code.shiki .sCsY4{--shiki-light:#6A737D;--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .s8jYJ, html code.shiki .s8jYJ{--shiki-light:#D73A49;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .snPdu, html code.shiki .snPdu{--shiki-light:#6F42C1;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sxrX7, html code.shiki .sxrX7{--shiki-light:#24292E;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sIIMD, html code.shiki .sIIMD{--shiki-light:#032F62;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":238,"searchDepth":252,"depth":252,"links":335},[336,337,338,339,340,341,342,343,344,345],{"id":41,"depth":252,"text":42},{"id":68,"depth":252,"text":69},{"id":89,"depth":252,"text":90},{"id":113,"depth":252,"text":114},{"id":128,"depth":252,"text":129},{"id":149,"depth":252,"text":150},{"id":170,"depth":252,"text":171},{"id":188,"depth":252,"text":189},{"id":313,"depth":252,"text":314},{"id":325,"depth":252,"text":326},"architecture","2025-12-14T00:00:00.000Z","本ブログの技術選定をアーキテクチャ視点から整理。\nNuxt 4 を SSR ブログに採用した理由、\n@nuxt/content をコンテンツレイヤーとして選んだ背景、\n多言語対応・画像最適化・デプロイ・分析における設計判断について。",false,"md","ja",{"tags":353},[354,355,356,357],"nuxt","nuxt-content","i18n","frontend-architecture",true,"/blog/ja/2025-12-14-nuxt-blog-architecture",{"title":5,"description":348},{"loc":359},null,"blog/ja/2025-12-14-nuxt-blog-architecture","qEd31pV4yxUNDThUtsNzmR1MifQ-Vn7FYA9HN0KjSR0",1784966029638]