<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>GitHub on Keyuki Blog</title>
    <link>https://blog.keyuki.net/tags/github/</link>
    <description>Recent content in GitHub on Keyuki Blog</description>
    <generator>Hugo</generator>
    <language>en</language>
    <lastBuildDate>Sat, 09 May 2026 10:46:38 +0900</lastBuildDate>
    <atom:link href="https://blog.keyuki.net/tags/github/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Hugoブログの画像をGitHubに置かず、Cloudflare R2で管理することにした</title>
      <link>https://blog.keyuki.net/posts/hugo-blog-image-management-cloudflare-r2/</link>
      <pubDate>Sat, 09 May 2026 10:46:38 +0900</pubDate>
      <guid>https://blog.keyuki.net/posts/hugo-blog-image-management-cloudflare-r2/</guid>
      <description>&lt;h2 id=&#34;最初は画像もリポジトリに入れればいいと思っていた&#34;&gt;最初は画像もリポジトリに入れればいいと思っていた&lt;/h2&gt;&#xA;&lt;p&gt;HugoはMarkdownと画像をまとめてGitHubで管理できるのが強みのひとつです。記事ごとにフォルダを作り、その中に &lt;code&gt;index.md&lt;/code&gt; と画像をまとめて置く「Page Bundle」という構成が使えるので、記事と素材の対応が分かりやすくなっています。&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;content/posts/&#xA;  2026-05-01-my-article/&#xA;    index.md&#xA;    cover.webp&#xA;    diagram.png&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;この構成は直感的で、最初はこれで十分だと思っていました。&lt;/p&gt;&#xA;&lt;p&gt;ところが記事が増えていくにつれて、アイキャッチ画像・サムネイル・OGP画像を毎回用意するようになります。1記事あたり3〜5枚の画像が増えていくと、リポジトリのサイズがじわじわ膨らんでいくのではないかという、不安に駆られました。まだ、ほとんど記事書いてないですけど。Markdownファイル本体は数KBなのに、画像だけで数MBという状況はよくないのでは？と思うようになりました。&lt;/p&gt;&#xA;&lt;h2 id=&#34;githubリポジトリが重くなるのが気になった&#34;&gt;GitHubリポジトリが重くなるのが気になった&lt;/h2&gt;&#xA;&lt;p&gt;Gitはテキストファイルの差分管理が得意なツールです。しかしバイナリファイル（画像・動画など）は差分を持たず、変更のたびにファイル全体が履歴として積み上がります。&lt;/p&gt;&#xA;&lt;p&gt;たとえばアイキャッチ画像を差し替えると、古い画像も新しい画像もGitの履歴に残ります。&lt;code&gt;git clone&lt;/code&gt; するたびにその全履歴を取得することになるので、リポジトリが年単位で成長すると無視できないサイズになります。&lt;/p&gt;&#xA;&lt;p&gt;CI/CDやCloudflare Pagesのビルドも同様で、ビルドのたびにリポジトリ全体をチェックアウトします。画像が増えれば増えるほど、ビルド時間に影響する可能性があります。&lt;/p&gt;&#xA;&lt;p&gt;「ブログ本文の変更履歴」と「画像アセットの保管場所」は、そもそも性質が違います。そう気づいてから、分けて管理したほうがすっきりすると思いました。&lt;/p&gt;&#xA;&lt;h2 id=&#34;cloudflare-r2を画像置き場にした&#34;&gt;Cloudflare R2を画像置き場にした&lt;/h2&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://www.cloudflare.com/developer-platform/r2/&#34;&gt;Cloudflare R2&lt;/a&gt;はCloudflareが提供するオブジェクトストレージです。Amazon S3と互換性のあるAPIを持ちつつ、&lt;strong&gt;エグレス料金（データ転送料）がかからない&lt;/strong&gt;のが特徴で、個人ブログの画像配信には手頃な選択肢です。&lt;/p&gt;&#xA;&lt;p&gt;無料枠は、ストレージ10GB・Class Aオペレーション（書き込み）100万回/月・Class Bオペレーション（読み込み）1000万回/月となっています。個人ブログで画像を置く用途であれば、まずストレージが上限に達することはありません。読み込み回数についても、1000万回というのは1日あたり約33万リクエストに相当します。そもそも個人ブログにそれだけのPVがあれば、もうブログで飯が食えています。このブログには当然そんなPVはないので、無料枠で一生やっていける気がしています。&lt;/p&gt;&#xA;&lt;p&gt;このブログはCloudflare Pagesで配信しているので、Cloudflare側に画像も寄せると運用がまとまりやすくなります。R2バケットにカスタムドメインを設定することで、画像URLを &lt;code&gt;https://images.keyuki.net/...&lt;/code&gt; という形で統一できます。&lt;/p&gt;&#xA;&lt;p&gt;記事のフロントマターには画像URLだけを書きます。画像本体はリポジトリに存在しません。&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;featured_image&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;https://images.keyuki.net/uploads/2026/05/sample-eyecatch.webp&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;thumbnail_image&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;https://images.keyuki.net/uploads/2026/05/sample-thumb.webp&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;images&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  - &lt;span style=&#34;color:#ae81ff&#34;&gt;https://images.keyuki.net/uploads/2026/05/sample-og.jpg&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;hugo側ではurlを参照するだけにした&#34;&gt;Hugo側ではURLを参照するだけにした&lt;/h2&gt;&#xA;&lt;p&gt;移行後のリポジトリには、記事本文・テンプレート・CSS・設定ファイルだけが残ります。画像本体はR2に置き、Hugoはそこへのパスを参照するだけになりました。&lt;/p&gt;&#xA;&lt;p&gt;フロントマターで使っているフィールドの役割も整理しています。&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;featured_image&lt;/code&gt;: 記事ページのメインビジュアル&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;thumbnail_image&lt;/code&gt;: 記事一覧のカードに表示するサムネイル&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;images&lt;/code&gt;: SNSシェア時のOGP画像（TwitterカードやOGタグで使用）&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;この分担は&lt;a href=&#34;https://blog.keyuki.net/posts/pagespeed-blog-image-optimization/&#34;&gt;前の記事で書いたPageSpeed改善の取り組み&lt;/a&gt;とも関連しています。&lt;/p&gt;&#xA;&lt;p&gt;少し管理は面倒になりましたが、快適にサイトが見れるようにやっていくには、これがいいと今のところ思ってます。&lt;/p&gt;&#xA;&lt;h2 id=&#34;よかったこと&#34;&gt;よかったこと&lt;/h2&gt;&#xA;&lt;p&gt;リポジトリを軽く保てるのが一番の効果でした。&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;画像を差し替えてもGit履歴に古いファイルが積み上がりません。R2上で上書きすれば終わりです。&lt;/li&gt;&#xA;&lt;li&gt;アイキャッチ・サムネイル・OGPと用途別の画像を整理して置きやすくなりました。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;気をつけること&#34;&gt;気をつけること&lt;/h2&gt;&#xA;&lt;p&gt;移行してよかった一方で、いくつか注意点もあります。&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;R2側のURL設計が後から変えにくい。&lt;/strong&gt; 記事から参照しているURLを変えると、過去記事の画像が壊れます。最初からディレクトリ構造とファイル命名規則を決めておく必要があります。&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;画像を消すと記事の表示が壊れる。&lt;/strong&gt; GitHubのように「削除もバージョン管理する」という感覚はR2にはありません。不要になった画像でも、参照している記事がないか確認してから消す必要があります。&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;GitHubだけ見ても画像の実体がわからない。&lt;/strong&gt; リポジトリを見ても画像は見えません。バックアップや棚卸しは別途R2側で行う必要があります。&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;キャッシュと公開設定に注意する。&lt;/strong&gt; R2バケットのパブリックアクセス設定やCloudflareのキャッシュ設定を間違えると、画像が表示されなかったりキャッシュが意図せず残ったりします。&lt;/p&gt;&#xA;&lt;p&gt;「R2に置けば解決」ではなく、運用ルールをセットで決めることが大事だと感じました。&lt;/p&gt;&#xA;&lt;h2 id=&#34;今の運用ルール&#34;&gt;今の運用ルール&lt;/h2&gt;&#xA;&lt;p&gt;実際にやっていることをまとめると、こんな感じです。&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;ディレクトリ構成&lt;/strong&gt;: 年月で分けています。&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;uploads/&#xA;  2026/&#xA;    05/&#xA;      article-slug-eyecatch.webp&#xA;      article-slug-thumb.webp&#xA;      article-slug-og.jpg&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;ファイル命名規則&lt;/strong&gt;: 記事のslugをベースに、用途をsuffixで区別します。&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
