快轉到主要內容
在 Cloudflare 上購買網域、架設 Cloudflare R2 圖床流程

在 Cloudflare 上購買網域、架設 Cloudflare R2 圖床流程

·
類別 
Hugo 網站
標籤 
Cloudflare Cloudflare R2 圖床
Eason Chiu
作者
Eason Chiu
一個不做筆記就容易忘記的工程師
目錄

前言
#

前一篇有提到我把部落格從github遷移到cloudflare,詳見「部落格從 GitHub Pages 遷移:為什麼我選擇 Hugo 搭配 Cloudflare Pages」,這篇就來記錄一下我如何購買個人網域、設定好,並把圖片自動上傳到cloudflare r2的流程。

購買 Cloudflare 網域
#

為什麼會選擇在 cloudflare 購買網域呢?主要有以下幾個原因:

  1. 價格實惠:幾乎是以成本價提供。
  2. 續約價格透明:不用擔心未來被養套殺,續約價格是固定的。
  3. 整合度高且安全:內建許多實用的免費功能,能看網域流量分析,還有一些基本的資安防護。
  4. 全球 CDN 加速:自帶強大的全球 CDN 節點,能大幅提升網站與圖片的載入效率。

實際的購買與註冊流程如下:

1. 搜尋並註冊網域
#

首先,前往 Cloudflare dashboard 頁面,在左側選單找到 網域 -> 購買網域

接著輸入你想要的網域名稱,下方會列出可用的後綴(如 .com.dev.io 等)與價格,我選了最常見的.com 結尾的網域,價格1年10美金,也算是很漂亮的價格。

然後就是選你要幾年的方案,我是直接先買了3年,也可以先買1年後面再自動續約,挑選好後,輸入個人資料,完成結帳付款即可。

2. 設定 DNS 與網域管理
#

購買完成後,該網域會自動加入到你 Cloudflare 的帳號中。你可以到左側的 網域 點擊查看剛剛購買的網域。

然後進入概觀頁面,首次進來會要你設定 DNS 與 憑證,到這裡你就可以透過剛剛購買的網域來存取你的網站了! 接下來只要按照這篇第六步-管理自訂網域設定就能把部署到cloudflare的網站指向購買的網域即可。

此外,你也可以把在其他地方部署的網站,照著網頁上的說明設定將 ip 指向自訂網域上。

設定完成後,之後再點進概觀頁面,就會看到cloudflare的流量分析了,也可以到分析與紀錄看更詳細的紀錄。

架設 Cloudflare R2 圖床
#

既然網域買好了,接下來就是設立圖床空間啦!而 Cloudflare R2 本身是一個與 AWS S3 兼容的物件儲存服務 ,使用者可以使用現有工具上傳檔案,而且免費額度對於一般的個人用部落格來說,已經非常夠用了(每月 10 GB 儲存與數百萬次讀寫)。

詳細額度說明可以參考:Cloudflare R2 收費標準

1. 新增 R2 貯體 (bucket)
#

在 Cloudflare 後台左側選單找到 R2-> 概觀,要開始使用需要先綁定一張信用卡。

接著點擊右上角的 建立貯體,輸入貯體名稱(例如 cdn),並選擇貯體的儲存位置(預設為 亞太地區)。

2. 開放公開存取與綁定自訂網域
#

預設情況下,R2 儲存區是私有的。為了讓網頁能讀取圖片,我們需要允許公開存取。 點擊進入你的儲存區,選擇 設定 -> 公用開發URL

會看到一組 S3 API : https://${R2_ACCOUNT_ID}.r2.cloudflarestorage.com/${R2_BUCKET_NAME},這個等等 API 上傳時會用到。

接著按下自訂網域(Custom Domains),輸入你想要用來做為圖床的子網域(例如 cdn.你的網域.com)。

按下儲存後,會進行初始化。 等到狀態變成作用中,就代表成功了。

然後用瀏覽器打開https://cdn.easonyc.com/,會看到 Error 404,是正常的,子網域已經成功接上Cloudflare R2 了。

3. 建立 Account API 權杖
#

接著就是建立這個 R2的 Account API 權杖,才能夠透過程式上傳檔案到 R2。

API Details 點擊 Manage 接著按下建立權杖。 將權限設定為系統管理員。 按下權限設定好後,建立權杖。 接著下方會有S3的儲存金鑰,先記起來,日後就不會再看到了。

圖片自動批量上傳至 R2
#

1. 自動批量處理未提交的圖片
#

要搬到 R2 上,當然可以使用 Cloudflare 網頁直接拖拉上傳,但如果圖片很多,還是得需要透過自動化腳本進行批量處理。 透過 Node.js 結合 AWS SDKsharp 套件,可以自動化整個流程:

  1. 透過 git status --porcelain 自動尋找 尚未 commit 的文章目錄,並自動尋找該文章目錄下的所有圖片。
  2. 自動將圖片壓縮為 .webp 格式,節省 R2 上的空間。
  3. 上傳至 Cloudflare R2,並維持原本在 content/posts/ 底下的文章目錄結構。
  4. 上傳成功後,會自動印出對應的 https://cdn.你的網域.com/... 完整網址,直接貼到文章上。

有了這個腳本,寫文章時只要把圖片丟進文章資料夾中,寫完後執行一次腳本,就能快速完成轉檔、上傳並拿到圖片網址。

在開始寫腳本前,我們需要在專案底下建立 .env 檔,並填入剛才在 S3的儲存金鑰 獲得的連線資訊:

env
R2_ACCOUNT_ID = 你的 Cloudflare 帳戶 ID(可以在 R2 概觀頁面或網址列找到)
R2_ACCESS_KEY_ID = 剛才建立 API 權杖時取得的 存取金鑰 ID
R2_SECRET_ACCESS_KEY = 剛才建立 API 權杖時取得的 機密存取金鑰
R2_BUCKET_NAME = 你的 R2 儲存區名稱(例如 `cdn`R2_DOMAIN = 綁定好的 R2 自訂網域(例如 `https://cdn.你的網域.com`

接著,以下為自動化上傳範例:

javascript
const fs = require('fs');
const { S3Client, PutObjectCommand } = require('@aws-sdk/client-s3');
require('dotenv').config();

const { R2_ACCOUNT_ID, R2_ACCESS_KEY_ID, R2_SECRET_ACCESS_KEY, R2_BUCKET_NAME } = process.env;

// 初始化 S3 Client (將 Endpoint 指向 Cloudflare R2)
const S3 = new S3Client({
    region: "auto",
    endpoint: `https://${R2_ACCOUNT_ID}.r2.cloudflarestorage.com`,
    credentials: {
        accessKeyId: R2_ACCESS_KEY_ID,
        secretAccessKey: R2_SECRET_ACCESS_KEY,
    },
});

// 核心上傳函數
async function uploadToR2(filePath, r2Key, contentType) {
    const fileStream = fs.createReadStream(filePath);
    const uploadParams = {
        Bucket: R2_BUCKET_NAME,
        Key: r2Key,       // R2 上的檔案路徑
        Body: fileStream, // 檔案內容
        ContentType: contentType,
    };

    try {
        await S3.send(new PutObjectCommand(uploadParams));
        return true;
    } catch (err) {
        console.error(`❌ 上傳失敗: ${r2Key}`, err);
        return false;
    }
}

async function processImages() {
    // 步驟 1:透過 git 狀態找出尚未 commit 的目錄,並尋找底下圖片
    const statusOutput = execSync('git status --porcelain', { encoding: 'utf-8' });
    const targetDirs = new Set();
    statusOutput.split('\n').forEach(line => {
        if (line.includes('content/')) {
            targetDirs.add(path.dirname(line.substring(3).trim()));
        }
    });

    const contentDir = path.join(__dirname, 'content');

    for (const dir of targetDirs) {
        // 尋找圖片 (此處以 glob 為例)
        const imageFiles = await glob('**/*.{png,jpg,jpeg}', { cwd: dir, absolute: true });
        
        for (const file of imageFiles) {
            // 步驟 2:利用 sharp 自動將圖片轉檔壓縮為 .webp 格式
            const tempWebpPath = file.replace(/\.[^/.]+$/, ".webp");
            await sharp(file).webp({ quality: 80 }).toFile(tempWebpPath);
            
            // 步驟 3:取得相對路徑以維持結構,並上傳至 R2
            const relativePath = path.relative(contentDir, file);
            const r2Key = path.join(path.dirname(relativePath), path.basename(tempWebpPath)).replace(/\\/g, '/');
            
            const success = await uploadToR2(tempWebpPath, r2Key, 'image/webp');
            
            // 步驟 4:上傳成功後,印出 CDN 完整網域讓你可以直接複製貼上
            if (success) {
                const url = `${R2_DOMAIN}/${r2Key.split('/').map(encodeURIComponent).join('/')}`;
                console.log(`✅ 上傳成功!`);
                console.log(`🔗 URL: ${url}`);
            }
        }
    }
}

// 執行腳本
processImages();

2. gitignore 排除圖片
#

透過腳本成功上傳後,確認所有圖片都能正常載入,就可以把文章 push 到 GitHub。透過在 .gitignore 裡,將 content/ 底下的圖片副檔名(如 *.png, *.jpg, *.webp 等)給排除,確保以後 Git 倉庫內只留有純文字,避免 GitHub 倉庫空間過大! gitignore 範例請見上一篇教學的#自動部署

結語
#

透過在 Cloudflare 上購買專屬網域並搭配 Cloudflare R2 建立圖床,不僅能擁有個人化的網址,還能有效減輕 Github Repository 的容量負擔,並借助 CDN 大幅提升圖片載入速度與後續的部署效率,而且擁有自己的網域相比使用 github.io 對於 SEO 也有幫助。

相關文章

部落格從 GitHub Pages 遷移:為什麼我選擇 Hugo 搭配 Cloudflare Pages
類別 
Hugo 網站
標籤 
Cloudflare Pages GitHub Pages 部落格部署
Hugo 網站的 SEO 優化與 Google 分析
類別 
Hugo 網站
標籤 
SEO Google Search Console Google Analytics
Hugo + Github Page 快速建立自己的部落格網站
類別 
Hugo 網站
標籤 
GitHub Pages 部落格架設