Đánh giá Astro 5 — thay đổi gì và có nên nâng cấp?
Nâng cấp Astro 4 ngay. Content Layer giúp build Markdown nhanh hơn 5×, ít bộ nhớ hơn 25–50%. Chỉ chờ nếu dùng @astrojs/lit hoặc cần Cloudflare adapter v13+.
Bởi Ethan
2.174 từ · 11 phút đọc
Hãy nâng cấp các site Astro 4 ngay bây giờ. Content Layer là tính năng nổi bật nhất và nó thực sự xứng đáng: build Markdown nhanh hơn tới 5 lần, MDX nhanh hơn 2 lần, bộ nhớ tiêu tốn ít hơn 25–50%. Server Islands và astro:env là những bổ sung gọn gàng, không kéo thêm độ phức tạp cho phần lớn dự án. Chỉ nên chờ nếu bạn dùng @astrojs/lit (đã bị xóa, chưa có thay thế), phụ thuộc vào dynamic prerender env var injection, hoặc cần các tính năng Cloudflare adapter chỉ có từ Astro 6. Một lưu ý về bối cảnh: Astro 6 đã là phiên bản hiện tại (v6.4.4), vì vậy Astro 5 là bước đệm được ghi chép đầy đủ — vẫn được hỗ trợ hoàn toàn, không phải legacy, nhưng cũng không phải mới nhất.
Bài viết này dành cho ai
Dành cho những ai đang dùng Astro 4 và đang phân vân có nên chuyển một content site đang hoạt động hay không. Nếu bạn đang ở Astro 2 hoặc 3, bài này không đủ để bao quát hết các khoảng cách — hãy bắt đầu từ migration guide đầy đủ. Nếu bạn đang bắt đầu dự án mới, hãy đi thẳng lên Astro 6.
Cách chúng tôi kiểm tra
Astro 5.11.0 trên M2 MacBook Pro, Node 22. Dự án thử nghiệm là một content blog Astro 4.16 có sẵn với 250 bài Markdown và 50 bài MDX. Số liệu thời gian build lấy từ các bài blog chính thức của Astro 5.0 và 5.3 (gắn với đúng phiên bản đó). Chúng tôi không chạy benchmark riêng cho SSR cold-start — không có số liệu bên thứ ba đáng tin cậy nào cho việc so sánh Astro 4 vs. 5 trên chiều đó, và chúng tôi không thay thế bằng suy đoán.
Content Layer
Thay đổi kiến trúc lớn nhất trong Astro 5. Content Layer thay thế API theo quy ước file-system bằng mô hình loader tường minh. Các collection được định nghĩa trong src/content/config.ts với trường loader:
import { defineCollection, z } from 'astro:content';
import { glob } from 'astro/loaders';
const posts = defineCollection({
loader: glob({ pattern: '**/*.md', base: './src/content/blog' }),
schema: z.object({
title: z.string(),
publishedAt: z.coerce.date(),
}),
});
export const collections = { posts };
Trường slug đã bị loại bỏ. Các collection giờ dùng id (đường dẫn file tương đối so với thư mục gốc). Nếu bạn dùng post.slug ở bất kỳ đâu trong template, hãy đổi thành post.id. Migration script xử lý được phần lớn việc này — nhưng hãy kiểm tra kỹ kết quả trước khi commit, vì script không phải lúc nào cũng bắt được slug trong các file MDX hoặc dynamic route params.
Số liệu hiệu năng từ bài blog release Astro 5.0: build Markdown nhanh hơn tới 5 lần, MDX nhanh hơn 2 lần, bộ nhớ tiêu tốn ít hơn 25–50%. Cải thiện đến từ việc xử lý các entry theo nhu cầu thay vì tải toàn bộ collection khi khởi động. Trên dự án thử nghiệm (250 Markdown + 50 MDX), chúng tôi thấy mức cải thiện tương đương, phù hợp với con số Astro công bố.
Thời gian migration: tính khoảng một tiếng cho site 200 bài với schema đơn giản, ba tiếng nếu bạn có kiểu schema tùy chỉnh và nhiều chỗ dùng slug rải rác trong template.
Server Islands
Server Islands trì hoãn việc render các component phía server cho đến sau khi static shell được tải xong. API chỉ có một directive duy nhất:
---
import Cart from '../components/Cart.astro';
---
<Cart server:defer />
Component được render trên server và được nhúng vào qua một fetch sau khi HTML ban đầu đã được gửi đi. Trường hợp điển hình: nội dung cá nhân hóa (tổng giỏ hàng, tên người dùng, số thông báo) trên các trang vốn là static, mà không cần hydrate cả một framework phía client chỉ để xử lý một khối nhỏ động.
Những hạn chế cần biết trước khi dùng:
- Props được serialize qua URL. Giới hạn là 2,048 bytes. Khi props đẩy URL vượt quá giới hạn này, Astro chuyển sang dùng POST request — trình duyệt không cache được, làm mất đi lợi ích của static-shell serving. Hãy thiết kế deferred component để tự fetch dữ liệu thay vì nhận qua props.
- Cần có adapter. Các deployment hoàn toàn static (không cấu hình adapter) không hỗ trợ Server Islands.
- Props phải có thể serialize được. Các hàm, class instance, và kiểu không phải JSON đều không dùng được.
Với các site nặng về nội dung và chỉ có vài widget cá nhân hóa, Server Islands là giải pháp gọn gàng. Với các deployment hoàn toàn static, tính năng này không áp dụng.
astro:env
Environment variable có type-safe. Bạn định nghĩa schema trong astro.config.ts và Astro kiểm tra tại thời điểm build:
import { envField } from 'astro/config';
export default defineConfig({
env: {
schema: {
API_KEY: envField.string({ context: 'server', access: 'secret' }),
PUBLIC_SITE_URL: envField.string({ context: 'client', access: 'public' }),
RESULTS_PER_PAGE: envField.number({ context: 'server', access: 'public', default: 10 }),
},
},
});
Truy cập biến secret từ code phía client sẽ gây lỗi compile. Biến bắt buộc bị thiếu sẽ báo lỗi ngay khi khởi động, không phải lúc runtime. Các kiểu dữ liệu: string, number, boolean, enum. Context: client hoặc server. Access: public hoặc secret.
Không ảnh hưởng hiệu năng. Đây hoàn toàn là cải thiện về trải nghiệm phát triển. Nếu bạn từng gặp cảnh một deploy lặng lẽ hỏng vì thiếu biến môi trường trong preview environment, đây chính là giải pháp.
Các thay đổi breaking
Các breaking change là có thật và cần một khoảng thời gian để xử lý. Những thứ sẽ làm bạn mất nhiều thời gian nhất:
@astrojs/lit đã bị xóa. Đây là rào cản cứng. Nếu bạn dùng Lit components qua integration này, bạn chưa thể nâng cấp cho đến khi có giải pháp thay thế tương thích. Không có giải pháp chính thức nào trong Astro 5. Kiểm tra catalog integrations của Astro xem có adapter từ cộng đồng không, hoặc tiếp tục dùng Astro 4.
Astro.glob() đã bị deprecated. Thay bằng import.meta.glob() hoặc Content Layer loaders. API cũ vẫn hoạt động trong Astro 5 nhưng sẽ bị xóa trong Astro 6. Sửa ngay để khỏi phải làm lại.
output: 'hybrid' đã bị xóa. Hành vi mặc định là static với SSR opt-in theo từng trang giờ nằm dưới output: 'static'. Nếu bạn đã khai báo output: 'hybrid' tường minh, hãy xóa nó đi. Hành vi vẫn như cũ; chỉ là key đó không còn nữa.
render() giờ là hàm import. Các entry không còn có method .render() — chúng là plain object. Import render từ astro:content và gọi await render(entry) thay vì await entry.render(). Tìm \.render\( để bắt hết các chỗ cần sửa.
compiledContent() giờ là async. Thêm await vào mọi chỗ gọi compiledContent().
Squoosh đã bị xóa. Chuyển sang Sharp. Cài sharp, gỡ squoosh. Một thay đổi cấu hình trong astro.config.ts nếu bạn đã cấu hình image service tường minh.
CSRF protection bật mặc định. Nếu bạn có form POST handler, bạn sẽ thấy lỗi 403 trong môi trường dev. Thêm header X-CSRF-Token vào form của bạn hoặc tắt CSRF protection tường minh nếu threat model của bạn không yêu cầu.
Route params không còn tự động decode. Nếu route của bạn khớp với ký tự đặc biệt và bạn đang phụ thuộc vào decodeURIComponent tự động, hãy tự thêm vào.
ViewTransitions → ClientRouter. Đổi tên import. Không thay đổi hành vi.
Content collections slug → id. Đơn giản về mặt kỹ thuật nhưng chạm vào nhiều template. Migration script bao phủ phần lớn; hãy kiểm tra kỹ kết quả với các file MDX và dynamic route có tham chiếu trực tiếp đến trường này.
Việc xóa @astrojs/lit là rào cản cứng duy nhất. Mọi thứ còn lại có thể xử lý trong một buổi chiều.
Hiệu năng
Số liệu build từ các bài blog release chính thức của Astro:
| Thay đổi | Tác động đo được |
|---|---|
| Content Layer (Astro 5.0) | Markdown nhanh hơn tới 5 lần, MDX nhanh hơn 2 lần, bộ nhớ ít hơn 25–50% |
| Sync rendering (Astro 5.3) | Static build nhanh hơn 10–15% |
| Sync rendering, component tree lớn (Astro 5.3) | SSR nhanh hơn 4 lần với 3,000+ component |
| SSR tổng quát (Astro 5.3) | Nhanh hơn 1.5–2 lần |
Nguồn: blog Astro 5.0, blog Astro 5.3.
Đây là benchmark của chính Astro trên test suite nội bộ, không phải đo lường độc lập. Cải thiện từ Content Layer phù hợp với những gì chúng tôi quan sát trên dự án thử nghiệm. Cải thiện sync rendering trong 5.3 là điểm thường bị bỏ qua — nếu bạn đang chạy các component tree lớn phía server, 5.3 nhanh hơn đáng kể so với 5.0.
Hệ sinh thái
| Integration | Trạng thái trong Astro 5 |
|---|---|
Tailwind 4 qua @tailwindcss/vite | ✅ Astro 5.2+; @astrojs/tailwind deprecated |
| Starlight | ✅ Astro ≥5.5.0 (Starlight mới nhất nhắm tới Astro 6) |
Markdoc (@astrojs/markdoc) | ✅ v0.15.x cho Astro 5 |
| Partytown | ✅ v2.1.7 |
| Cloudflare adapter | ⚠️ v12 = Astro 5; v13 = Astro 6 (Cloudflare Pages bị bỏ trong v13) |
@astrojs/lit | ❌ Đã bị xóa |
Migration sang Tailwind 4 là thay đổi ecosystem dễ làm bạn bất ngờ nhất. Nếu bạn đang dùng Tailwind 3 qua @astrojs/tailwind, integration đó đã bị deprecated và sẽ không nhận cập nhật cho Astro 5.2+. Chuyển sang @tailwindcss/vite là việc migration thực sự — Tailwind 4 dùng mô hình cấu hình khác (CSS-first config, không còn tailwind.config.js theo mặc định).
Với người dùng Cloudflare Pages: adapter v12 tương thích với Astro 5. Adapter v13 yêu cầu Astro 6 và bỏ hỗ trợ trực tiếp cho Cloudflare Pages, chuyển sang Workers runtime. Nếu bạn đang dùng v12 và ổn với nó, Astro 5 là tốt. Nếu bạn cần tính năng của v13, hãy chuyển thẳng lên Astro 6. Xem hướng dẫn deploy Astro lên Cloudflare Pages để biết cách cấu hình chi tiết.
Từ Astro 5 lên Astro 6
Astro 6 là phiên bản hiện tại (v6.4.4 tính đến tháng 6 năm 2026). Tài liệu Astro 4 đã bị đánh dấu là không còn được bảo trì. Astro 5 vẫn được hỗ trợ và nhận maintenance release, nhưng việc phát triển tính năng mới đang tập trung vào phiên bản 6.
Nhìn thực tế: Astro 5 là bước đệm được ghi chép đầy đủ để lên 6. Migration từ 5→6 nhẹ hơn so với 4→5. Nếu bạn đang duy trì một site Astro 4, nâng lên 5 ngay bây giờ giúp bạn có ngay lợi ích hiệu năng từ Content Layer và đặt bạn vào vị trí thuận lợi để nhảy lên 6 trong đợt bảo trì tiếp theo. Nếu bạn bắt đầu dự án mới, bỏ qua 5 và deploy thẳng trên 6.
Xem đánh giá Astro 6 để biết chi tiết những thay đổi trong phiên bản hiện tại.
Kết luận
Nâng cấp ngay nếu bạn đang dùng Astro 4 và dự án không sử dụng @astrojs/lit. Content Layer một mình đã đủ để biện minh cho công sức migration.
Chưa nên nâng cấp nếu:
- Bạn dùng
@astrojs/lit— đã bị xóa, chưa có thay thế - Bạn phụ thuộc vào dynamic
prerenderenv var injection — hành vi đã thay đổi - Bạn cần tính năng Cloudflare adapter v13+ — yêu cầu Astro 6
Bắt đầu trên Astro 6 cho mọi dự án mới.
Nếu bạn đang phân vân giữa Astro và các framework khác, xem so sánh Next.js vs Astro để biết khi nào nên chọn cái nào.
Lưu ý
Thử nghiệm của chúng tôi chỉ áp dụng cho một content blog tiêu chuẩn. Các site có nhiều client-side island, SSR phức tạp, hoặc nhiều integration bên thứ ba có thể gặp các vấn đề migration mà chúng tôi chưa gặp phải. Rào cản liên quan đến @astrojs/lit được xác nhận từ tài liệu chính thức — chúng tôi không test trực tiếp Lit components.
Bài viết này không có affiliate link. Cloudflare không có chương trình affiliate công khai; adapter được nhắc đến vì đây là nguồn phổ biến nhất gây khó khăn khi nâng cấp cho người dùng Cloudflare Pages.
Tham khảo
- Blog release Astro 5.0
- Migration guide lên Astro 5
- Tài liệu tham chiếu Content Loader API
- Tài liệu Server Islands
- Tài liệu tham chiếu astro:env API
- Blog Astro 5.2 — hỗ trợ Tailwind 4
- Blog Astro 5.3 — sync rendering
- Astro tổng kết năm 2025
- Tài liệu adapter @astrojs/cloudflare
- GitHub issue #14893 — OOM regression (đã xử lý)