Skip to content

Thêm ảnh vào Astro trên Cloudflare Pages

Thêm ảnh vào Astro trên Cloudflare Pages

Section titled “Thêm ảnh vào Astro trên Cloudflare Pages”

Cloudflare Pages là hosting miễn phí tuyệt vờI cho Astro sites. Bài viết này hướng dẫn cách quản lý và sử dụng hình ảnh trên Cloudflare Pages.

Phương ánGiáTốt choHạn chế
public/Free< 100 ảnh, < 20MBBuild chậm hơn
Cloudflare Images$5/100k imagesDynamic resizePaid
R2 Storage$0.015/GBBulk storageSetup phức tạp
External CDNFree/PaidExisting workflowDependency

Section titled “2. Phương án 1: public/ folder (Recommended cho beginners)”
my-astro-blog/
├── public/
│ └── images/
│ ├── posts/
│ │ ├── 2024/
│ │ │ └── bai-viet-1/
│ │ │ ├── hero.jpg
│ │ │ └── diagram.png
│ │ └── 2023/
│ ├── authors/
│ │ ├── avatar-john.jpg
│ │ └── avatar-jane.jpg
│ └── shared/
│ └── logo.png
└── src/
└── content/
└── blog/
![Alt text](/images/posts/2024/bai-viet-1/hero.jpg)
<!-- Hoặc với size cụ thể -->
<img
src="/images/posts/2024/bai-viet-1/hero.jpg"
alt="Description"
width="800"
height="450"
/>
src/pages/blog/[slug].astro
---
import { Image } from 'astro:assets';
---
<!-- Local image -->
<Image
src="/images/posts/2024/bai-viet-1/hero.jpg"
alt="Description"
width={800}
height={450}
format="webp"
/>
<!-- Hoặc dynamic -->
<img
src={`/images/posts/${post.slug}/hero.jpg`}
alt={post.data.title}
/>

Nếu repo lớn, dùng Git LFS:

Terminal window
# Install Git LFS
git lfs install
# Track images
git lfs track "*.jpg"
git lfs track "*.png"
git lfs track "*.webp"
# Commit
git add .gitattributes
git add public/images/
git commit -m "Add images with LFS"

3. Phương án 2: Cloudflare Images (Best cho dynamic resize)

Section titled “3. Phương án 2: Cloudflare Images (Best cho dynamic resize)”
  1. Trong Cloudflare Dashboard:

    • Vào Images → Configuration
    • Enable “Cloudflare Images”
    • Copy Delivery URL
  2. Upload images:

Terminal window
# Via API
curl -X POST \
https://api.cloudflare.com/client/v4/accounts/YOUR_ACCOUNT/images/v1 \
-H "Authorization: Bearer YOUR_TOKEN" \
-F file=@/path/to/image.jpg
  1. Sử dụng trong Astro:
---
const imageId = 'image-id-from-upload';
const accountHash = 'your-account-hash';
---
<!-- Direct URL -->
<img
src={`https://imagedelivery.net/${accountHash}/${imageId}/public`}
alt="Description"
loading="lazy"
/>
<!-- With transformations -->
<img
src={`https://imagedelivery.net/${accountHash}/${imageId}/w=800,quality=85`}
srcset={`
https://imagedelivery.net/${accountHash}/${imageId}/w=400 400w,
https://imagedelivery.net/${accountHash}/${imageId}/w=800 800w,
https://imagedelivery.net/${accountHash}/${imageId}/w=1200 1200w
`}
sizes="(max-width: 600px) 400px, 800px"
alt="Description"
/>
ParameterExampleDescription
ww=800Width
hh=600Height
qualityquality=85Quality (1-100)
formatformat=webpOutput format
fitfit=coverResize fit
src/utils/images.js
export function getCloudflareImageUrl(imageId, options = {}) {
const accountHash = import.meta.env.CLOUDFLARE_ACCOUNT_HASH;
const { width, quality = 85, format = 'webp' } = options;
let transform = '';
if (width) transform += `w=${width},`;
transform += `quality=${quality}`;
if (format) transform += `,format=${format}`;
return `https://imagedelivery.net/${accountHash}/${imageId}/${transform}`;
}
// Usage
import { getCloudflareImageUrl } from '../utils/images.js';
const imageUrl = getCloudflareImageUrl('image-id', {
width: 800,
quality: 85
});

  1. Tạo R2 bucket:

    • Cloudflare Dashboard → R2
    • Create bucket: my-blog-images
    • Set public access
  2. Upload images:

Terminal window
# Using Wrangler
wrangler r2 object put my-blog-images/posts/hero.jpg --file=./hero.jpg
# Hoặc via S3-compatible API
aws s3 cp ./images s3://my-blog-images/posts/ --recursive \
--endpoint-url https://ACCOUNT_ID.r2.cloudflarestorage.com
  1. Custom domain cho R2:
Cloudflare Dashboard → R2 → Manage Bucket → Settings → Public Custom Hostname
→ Add: images.yoursite.com
  1. Sử dụng trong Astro:
---
const R2_PUBLIC_URL = 'https://images.yoursite.com';
---
<img
src={`${R2_PUBLIC_URL}/posts/hero.jpg`}
alt="Description"
loading="lazy"
/>

src/content/config.ts
import { defineCollection, z } from 'astro:content';
const blogCollection = defineCollection({
type: 'content',
schema: z.object({
title: z.string(),
date: z.date(),
image: z.object({
src: z.string(),
alt: z.string(),
credit: z.string().optional(),
}).optional(),
ogImage: z.string().optional(),
}),
});
export const collections = {
'blog': blogCollection,
};
---
title: "Bài viết với ảnh"
date: 2024-01-15
image:
src: "/images/posts/2024/bai-viet/hero.jpg"
alt: "Mô tả ảnh hero"
credit: "Photo by John Doe"
ogImage: "/images/posts/2024/bai-viet/og-image.jpg"
---
Nội dung bài viết...
---
import { Image } from 'astro:assets';
import type { CollectionEntry } from 'astro:content';
interface Props {
post: CollectionEntry<'blog'>;
}
const { post } = Astro.props;
const { Content } = await post.render();
---
<article>
{post.data.image && (
<figure>
<Image
src={post.data.image.src}
alt={post.data.image.alt}
width={1200}
height={630}
format="webp"
/>
{post.data.image.credit && (
<figcaption>{post.data.image.credit}</figcaption>
)}
</figure>
)}
<Content />
</article>

.github/workflows/optimize-images.yml
name: Optimize Images
on:
push:
paths:
- 'public/images/**'
jobs:
optimize:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node
uses: actions/setup-node@v3
with:
node-version: 18
- name: Install dependencies
run: npm install sharp
- name: Optimize images
run: node scripts/optimize-images.js
- name: Commit changes
run: |
git config --local user.email "action@github.com"
git config --local user.name "GitHub Action"
git add public/images/
git diff --quiet && git diff --staged --quiet || git commit -m "Optimize images"
git push

<!-- Preload critical hero image -->
<link
rel="preload"
as="image"
href="/images/hero.webp"
type="image/webp"
/>
<!-- Responsive images -->
<Image
src={heroImage}
alt="Hero"
widths={[400, 800, 1200]}
sizes="100vw"
format="webp"
loading="eager"
fetchpriority="high"
/>

Vấn đềNguyên nhânFix
Images 404Wrong pathKiểm tra /images/ vs images/
Build chậmQuá nhiều ảnhDùng Cloudflare Images hoặc R2
CORS errorExternal imagesAdd CORS headers hoặc proxy
CLS caoThiếu dimensionsThêm width/height

Use CaseRecommendation
Personal blogpublic/images/
Photo galleryCloudflare Images
Large media siteR2 + Custom domain
Mixed approachpublic cho static, Images cho dynamic