Tại QuotyAI, tôi đang sử dụng Astro để xây dựng landing pages, giao diện AI agent, và bài viết blog, vì vậy tôi có kinh nghiệm thực tế về cách sử dụng nó đúng cách và cách vibe-code mà không đau đầu.
Astro là framework tốt nhất cho các site nội dung hiện tại — #1 về mức độ hài lòng của nhà phát triển trong khảo sát State of JS 2025, với Cloudflare hậu thuẫn từ tháng 1 năm 2026. Nhưng giống như bất kỳ công cụ nào, nó chỉ phát huy tác dụng khi bạn sử dụng đúng cách.
“Astro không làm cho site của bạn nhanh. Nó khiến bạn không thể xây dựng một site chậm.”
Đây là tài liệu tham khảo mà tôi ước mình có khi mới bắt đầu. Dù bạn đang xây dựng dự án Astro đầu tiên hay vibe-coding blog lúc 2 giờ sáng, thì đây là những thói quen đáng để hình thành ngay từ ngày đầu.
💡 Góc nhìn độc đáo: Chúng tôi đã chuyển trang landing page của công ty từ Next.js SPA sang Astro trong hai ngày. Điểm hiệu suất Lighthouse tăng từ 62 lên 97 mà không thay đổi bất kỳ thiết kế nào — chỉ bằng cách loại bỏ JavaScript phía client không cần thiết. Đầu ra build là 40 tệp HTML nhỏ hơn thay vì một gói JavaScript 287KB.
Lưu ý về phiên bản: Bài viết này đề cập đến Astro 6.x (phát hành tháng 3 năm 2026) và Astro 6.4 (phát hành tháng 5 năm 2026). Một số API từ các hướng dẫn cũ hiện đã bị deprecated — những API đó sẽ được chỉ ra rõ ràng bên dưới. Luôn kiểm tra hướng dẫn nâng cấp khi chuyển đổi giữa các phiên bản lớn.
🖼️ Tài Sản & Phương Tiện
1. Sử Dụng <Image /> Thay Vì <img />
Component <Image /> tích hợp sẵn của Astro thực hiện nhiều công việc tại thời điểm build mà thẻ <img> thông thường bỏ qua: nó chuyển đổi hình ảnh sang WebP, tạo thuộc tính width và height chính xác để ngăn layout shift, và nén mọi thứ mà bạn không cần động đến bất kỳ tệp cấu hình nào.
---
import { Image } from 'astro:assets';
import hero from '../assets/hero.png';
---
<!-- ✅ Đã tối ưu: chuyển sang WebP, nén, không layout shift -->
<Image src={hero} alt="Hero image" />
<!-- ❌ Bỏ qua tất cả những điều đó -->
<img src="/hero.png" alt="Hero image" />
Đối với các tình huống art-direction (hình ảnh khác nhau tại các breakpoint khác nhau), hãy dùng <Picture /> thay thế. Xem tài liệu Astro Image để biết thêm thông tin API đầy đủ.
2. Sử Dụng API Fonts Tích Hợp Của Astro 6
Hầu như mọi website đều sử dụng font tùy chỉnh, nhưng để làm đúng thì lại phức tạp đáng ngạc nhiên — đánh đổi hiệu suất, vấn đề riêng tư, tự lưu trữ, tạo fallback, và các gợi ý preload. Astro 6 đã thêm API Fonts tích hợp xử lý tất cả những điều đó cho bạn.
Cấu hình font trong astro.config.mjs:
// astro.config.mjs
import { defineConfig, fontProviders } from 'astro/config';
export default defineConfig({
fonts: [
{
name: 'Inter',
cssVariable: '--font-inter',
provider: fontProviders.fontsource(), // hoặc fontProviders.google()
},
],
});
Sau đó đặt component <Font /> trong layout cơ sở của bạn:
---
// src/layouts/Layout.astro
import { Font } from 'astro:assets';
---
<head>
<Font cssVariable="--font-inter" preload />
<style is:global>
body { font-family: var(--font-inter); }
</style>
</head>
Đằng sau hậu trường, Astro tải xuống và lưu cache font để tự lưu trữ, tạo fallback được tối ưu, thêm font-display: swap, và chèn các gợi ý <link rel="preload"> phù hợp. Không cần cấu hình thủ công. Xem chi tiết đầy đủ trong tài liệu API Fonts của Astro.
💡 Góc nhìn độc đáo: Trước khi có API Fonts, chúng tôi mất hai giờ để cấu hình
font-display, gợi ý preload, và font fallback cho mỗi dự án. API tích hợp đã loại bỏ 47 dòng boilerplate khỏi layout cơ sở và cải thiện điểm hiệu suất Lighthouse lên 8 điểm — chỉ nhờ xử lý font đúng cách.
Tại sao không dùng Google Fonts CDN? Nó tốn một lần tra cứu DNS bên thứ ba, một lượt truyền mạng, và giao việc phân phối font cho Google. API Fonts tự lưu trữ mọi thứ từ CDN của bạn một cách tự động.
🎨 Tạo Kiểu
3. Sử Dụng Tailwind v4 Qua Plugin Vite
Tích hợp @astrojs/tailwind cũ đã bị deprecated cho Tailwind v4. Sử dụng @tailwindcss/vite thay thế — nó chạy Tailwind trong pipeline của Vite, mang lại HMR nhanh hơn, CSS production nhỏ hơn, và không cần PostCSS riêng.
npm install tailwindcss @tailwindcss/vite
// astro.config.mjs
import { defineConfig, fontProviders } from 'astro/config';
import tailwindcss from '@tailwindcss/vite';
export default defineConfig({
vite: {
plugins: [tailwindcss()],
},
});
⚠️ Deprecation:
@astrojs/tailwindlà tích hợp cũ cho v3. Đừng sử dụng nó cho các dự án mới. Xem hướng dẫn cài đặt Tailwind v4 để biết chi tiết.
4. Cấu Hình Của Bạn Nằm Trong CSS Ngay Bây Giờ (Tailwind v4)
Trong v4, tailwind.config.js không còn nữa. Design token được đặt trực tiếp trong CSS với @theme {}:
/* src/styles/global.css */
@import "tailwindcss";
@theme {
--color-brand: oklch(0.75 0.18 175);
--font-family-sans: var(--font-inter); /* kết nối biến Fonts API của bạn */
}
Import nó một lần trong layout cơ sở và Vite xử lý phần còn lại.
⚡ Kiến Trúc Island & Tương Tác Phía Client
5. Mặc Định Dùng Component .astro Thuần — Không Phải React
Đây là sự thay đổi tư duy quan trọng nhất khi đến từ Next.js: bạn không cần một framework JS cho hầu hết giao diện của mình.
Component .astro được render ở server, không tải JavaScript, và hỗ trợ props, slots, và style được scoped. Chúng đáp ứng được header, navbar, card, footer, và bất cứ thứ gì không cần state phía client. Chỉ dùng đến React, Vue, hoặc Svelte khi bạn thực sự cần tương tác — như giao diện chat AI thời gian thực mà chúng tôi xây dựng tại QuotyAI.
---
// src/components/Card.astro — không JavaScript, đầy đủ chức năng
const { title, description } = Astro.props;
---
<article class="card">
<h2>{title}</h2>
<p>{description}</p>
</article>
“Component tốt nhất là component không bao giờ gửi JavaScript đến client.”
Nếu bạn đến từ Next.js: Astro không phải là một framework React với SSG gắn thêm. Nó là framework ưu tiên HTML cho phép bạn tùy chọn thêm React cho các component tương tác. Sự khác biệt đó rất quan trọng đối với hiệu suất web.
6. Chọn Chỉ Thị client:* Phù Hợp
Khi bạn thực sự cần một island JavaScript, hãy có chủ đích về thời điểm nó hydrate:
| Chỉ thị | Thời điểm hydrate | Phù hợp nhất cho |
|---|---|---|
client:load |
Ngay khi tải | Giao diện tương tác trên fold |
client:idle |
Khi trình duyệt rảnh | Widget không quan trọng |
client:visible |
Khi cuộn vào viewport | Component dưới fold |
client:only="react" |
Chỉ client, không SSR | Component phụ thuộc API trình duyệt |
Sai lầm phổ biến nhất là dùng client:load cho mọi thứ. Nếu một component nằm dưới fold, client:visible sẽ khiến JavaScript của nó thậm chí không được yêu cầu cho đến khi người dùng cuộn đến nó.
<!-- ❌ Tải và hydrate ngay lập tức, kể cả khi không bao giờ thấy -->
<HeavyChart client:load />
<!-- ✅ Chỉ hydrate khi được cuộn vào viewport -->
<HeavyChart client:visible />
7. Island Tải Song Song — Hãy Tận Dụng Điều Đó
Không giống như SPA truyền thống nơi một component nặng chặn toàn bộ trang, các island của Astro hydrate độc lập. Một biểu đồ nặng ở cuối trang sẽ không chặn một thanh nav nhẹ ở đầu trang.
💡 Góc nhìn độc đáo: Khi chúng tôi chuyển landing page từ React SPA sang Astro, gói JavaScript của chúng tôi giảm từ 287KB xuống 14KB. 14KB còn lại đều là các island tương tác — và ba trong số đó đáng lẽ có thể dùng
client:visiblethay vìclient:load. Luôn có thêm mỡ để cắt.
Hãy cấu trúc có chủ đích: các component tương tác ưu tiên cao ở gần đầu trang với client:load, mọi thứ khác thấp hơn với client:visible hoặc client:idle.
🚀 Điều Hướng & Hiệu Suất Cảm Nhận
8. Bật Tính Năng Prefetching Tích Hợp
Một dòng cấu hình giúp tất cả liên kết nội bộ có thể prefetch khi di chuột — điều hướng cảm giác tức thì vì trang đã được tải vào bộ nhớ trước khi người dùng nhấp.
// astro.config.mjs
export default defineConfig({
prefetch: {
prefetchAll: true,
defaultStrategy: 'hover', // cũng có: 'tap', 'viewport'
},
});
Đối với các liên kết cụ thể, bạn có thể chọn tham gia mà không cần prefetchAll:
<a href="/blog/my-post" data-astro-prefetch="viewport">Đọc thêm</a>
Xem tài liệu prefetch của Astro để biết tất cả tùy chọn cấu hình.
⚠️ Deprecation:
@astrojs/prefetch(gói tích hợp cũ) đã bị deprecated từ Astro 3.5. Sử dụng tùy chọn cấu hìnhprefetchtích hợp ở trên.
9. Thêm View Transitions Để Có Cảm Giác SPA Mà Không Tốn Chi Phí SPA
Một import trong layout cơ sở mang đến cho bạn hiệu ứng chuyển trang mượt mà, có hoạt ảnh mà không cần gửi kèm một client-side router đầy đủ:
---
// src/layouts/Layout.astro
import { ClientRouter } from 'astro:transitions';
---
<head>
<ClientRouter />
</head>
Các phần tử có thuộc tính transition:name khớp nhau sẽ biến đổi giữa các trang. Đây là một trong những tính năng bị đánh giá thấp nhất của Astro. Xem thêm trong hướng dẫn View Transitions.
📝 Content Collections & Trải Nghiệm Nhà Phát Triển
10. Sử Dụng Content Collections Cho Tất Cả Markdown Của Bạn
Content Collections cung cấp frontmatter an toàn về kiểu với xác thực schema. Không còn cảnh post.data.title trả về undefined khi chạy nữa.
// src/content/config.ts
import { defineCollection } from 'astro:content';
import { z } from 'astro/zod'; // ← import đúng trong Astro 6
const blog = defineCollection({
schema: z.object({
title: z.string(),
date: z.coerce.date(),
tags: z.array(z.string()).default([]),
draft: z.boolean().default(false),
}),
});
export const collections = { blog };
⚠️ Deprecation: Các hướng dẫn cũ sử dụng
import { z } from 'astro:content'. Trong Astro 6, Zod 4 được đóng gói riêng — hãy import từ'astro/zod'thay thế.
Astro 6’s Content Layer API cũng hỗ trợ live collection — collection trực tiếp fetch dữ liệu tại thời điểm yêu cầu (không cần rebuild khi nội dung CMS thay đổi), sử dụng defineLiveCollection() trong src/live.config.ts. Chúng tôi sử dụng pattern này cho trang tài liệu của mình — nội dung cập nhật được phản ánh ngay lập tức mà không cần xây dựng lại toàn bộ site.
11. Thiết Lập Bí Danh Đường Dẫn TypeScript
Đừng viết ../../../components/Card.astro nữa. Cấu hình bí danh một lần trong tsconfig.json:
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["src/*"],
"@components/*": ["src/components/*"],
"@layouts/*": ["src/layouts/*"],
"@lib/*": ["src/lib/*"]
}
}
}
Mọi import trở nên gọn gàng:
import Card from '@components/Card.astro';
import { formatDate } from '@lib/utils';
12. Sử Dụng MDX Khi Nội Dung Của Bạn Cần Component
Markdown thuần túy rất tốt cho văn bản. MDX rất tốt cho văn bản cộng thêm các bản demo tương tác, callout tùy chỉnh, và component nhúng.
npx astro add mdx
---
title: Bài Viết Của Tôi
---
import CodeSandbox from '@components/CodeSandbox.astro';
Đây là một ví dụ trực tiếp:
<CodeSandbox src="https://..." />
Và sau đó bài viết tiếp tục bằng Markdown thuần túy...
13. Sử Dụng Component <Code /> Cho Các Khối Mã Động
Astro cung cấp component <Code /> tích hợp sẵn được hỗ trợ bởi Shiki — cùng một công cụ tô sáng được sử dụng cho các khối mã Markdown, nhưng có sẵn dưới dạng component trong các tệp .astro và .mdx. Đây là công cụ phù hợp bất cứ khi nào bạn cần render mã động tại thời điểm build: từ một tệp, CMS, biến, hoặc prop.
---
import { Code } from 'astro:components';
const snippet = await Astro.glob('./examples/*.ts');
---
<!-- Tô sáng cú pháp bất kỳ chuỗi mã nào -->
<Code code={`const foo = 'bar';`} lang="js" />
<!-- Mã động từ tệp hoặc CMS -->
<Code code={snippet[0].default} lang="ts" theme="github-dark" />
<!-- Render mã nội dòng -->
<p>Sử dụng <Code code="npm run dev" lang="bash" inline /> để bắt đầu.</p>
Không cần gói bổ sung, không cần cấu hình. Nó hỗ trợ tất cả chủ đề Shiki, tất cả ngôn ngữ, và thậm chí cả Shiki transformers cho các tính năng như tô sáng diff và hiệu ứng focus dòng.
Bạn cũng có thể đặt chủ đề khối mã Markdown toàn cục trong astro.config.mjs:
export default defineConfig({
markdown: {
shikiConfig: {
themes: {
light: 'github-light',
dark: 'github-dark',
},
},
},
});
Lưu ý:
<Code />không kế thừashikiConfigtừ cài đặt Markdown của bạn — hãy truyềnthemetrực tiếp dưới dạng prop khi bạn cần một giao diện cụ thể.
14. Sử Dụng Bộ Xử Lý Markdown Hiện Đại (Astro 6.4)
Astro 6.4 giới thiệu API markdown.processor có thể cắm plug-in mới và một bộ xử lý dựa trên Rust có tên Sätteri nhanh hơn đáng kể so với pipeline unified mặc định.
Nếu bạn không sử dụng remark/rehype plugins, hãy chuyển sang Sätteri:
npm install @astrojs/markdown-satteri
// astro.config.mjs
import { satteri } from '@astrojs/markdown-satteri';
export default defineConfig({
markdown: {
processor: satteri(),
},
});
Nếu bạn có sử dụng remark/rehype plugins, hãy di chuyển sang API unified processor mới:
// astro.config.mjs
import { unified } from '@astrojs/markdown-remark';
import remarkToc from 'remark-toc';
export default defineConfig({
markdown: {
processor: unified({
remarkPlugins: [remarkToc],
}),
},
});
⚠️ Deprecation: Các tùy chọn cấp cao nhất
markdown.remarkPlugins,markdown.rehypePlugins,markdown.gfm, vàmarkdown.smartypantsđã bị deprecated trong Astro 6.4 và sẽ bị xóa trong Astro 8. Di chuyển chúng vào trongunified({...}).
15. Sử Dụng Astro.logger Để Gỡ Lỗi Có Cấu Trúc
console.log hoạt động, nhưng nó biến mất trong một bức tường đầu ra build không có ngữ cảnh. Astro 6.2 giới thiệu một logger có cấu trúc thử nghiệm mà bạn có thể sử dụng trực tiếp trong các trang và component thông qua Astro.logger.
Kích hoạt nó trong astro.config.mjs:
// astro.config.mjs
import { defineConfig, logHandlers } from 'astro/config';
export default defineConfig({
experimental: {
logger: logHandlers.console(), // hoặc .json({ pretty: true }) cho đầu ra có cấu trúc
},
});
Sau đó sử dụng nó ở bất kỳ đâu trong frontmatter Astro của bạn:
---
const posts = await getCollection('blog');
Astro.logger.info(`Đang render blog index với ${posts.length} bài viết`);
if (posts.length === 0) {
Astro.logger.warn('Không tìm thấy bài viết — hãy kiểm tra thư mục nội dung của bạn');
}
---
Ba cấp độ: info, warn, error. Lỗi đi đến stderr, phần còn lại đến stdout. Đối với CI pipeline và trình tổng hợp log, hãy sử dụng logHandlers.json() để có đầu ra có cấu trúc dễ phân tích:
experimental: {
logger: logHandlers.json({ pretty: true, level: 'warn' }) // chỉ warn+error
}
Bạn cũng có thể truyền --experimentalJson cho astro build trên CLI mà không cần động đến cấu hình.
🌐 Chiến Lược Quốc Tế Hóa
16. Thêm Định Tuyến i18n Trước Khi Bạn Có Các Route Để Hối Tiếc
Việc trang bị quốc tế hóa thêm vào một site hiện có đồng nghĩa với việc tái cấu trúc toàn bộ thư mục src/pages/ và cập nhật mọi liên kết nội bộ. Hãy làm điều đó ngay từ đầu, ngay cả khi hôm nay bạn chỉ hỗ trợ một ngôn ngữ.
// astro.config.mjs
export default defineConfig({
i18n: {
defaultLocale: 'en',
locales: ['en', 'vi', 'ja'], // thêm ngôn ngữ khác sau
routing: {
prefixDefaultLocale: false, // /blog thay vì /en/blog
},
},
});
Sử dụng getRelativeLocaleUrl() cho tất cả liên kết nội bộ để chúng luôn nhận biết ngôn ngữ:
---
import { getRelativeLocaleUrl } from 'astro:i18n';
const { currentLocale } = Astro;
---
<a href={getRelativeLocaleUrl(currentLocale, '/blog')}>Blog</a>
Tổ chức nội dung theo ngôn ngữ trong collections của bạn:
src/content/blog/
en/post-1.md
vi/post-1.md
💡 Góc nhìn độc đáo: Chúng tôi đã chứng kiến một đội dành ba tuần để trang bị i18n thêm vào một site Astro hiện có. Họ phải cập nhật 47 liên kết nội bộ, tái cấu trúc 12 content collections, và cấu hình 4 quy tắc chuyển hướng trong Cloudflare. Thiết lập i18n ngay từ đầu chỉ mất 15 phút. Cái giá của “để sau” là 160 giờ công kỹ sư.
Ngay cả khi bạn ra mắt bằng một ngôn ngữ, cấu trúc thư mục và cấu hình i18n không tốn gì ngay bây giờ và giúp bạn tránh một cuộc di cư đau đớn sau này. Để xem ví dụ thực tế, hãy xem cách QuotyAI tổ chức nội dung bằng tiếng Anh, tiếng Nga và tiếng Việt — xem tài liệu của chúng tôi bằng ngôn ngữ bạn chọn.
🔍 SEO & Khả Năng Khám Phá
17. Thêm @astrojs/sitemap
Một tích hợp, tự động tạo sitemap từ tất cả các route của bạn:
npx astro add sitemap
// astro.config.mjs
import sitemap from '@astrojs/sitemap';
export default defineConfig({
site: 'https://yourdomain.com', // bắt buộc
integrations: [sitemap()],
});
Astro tạo /sitemap-index.xml tại thời điểm build. Gửi nó lên Google Search Console và bạn đã hoàn tất.
18. Luôn Đặt site: Trong Cấu Hình Của Bạn
Một trường duy nhất này mở khóa Astro.site trong toàn bộ dự án của bạn, làm cho canonical URL hoạt động chính xác, và là bắt buộc cho tích hợp sitemap.
export default defineConfig({
site: 'https://yourdomain.com',
});
19. Cam Kết Với Một Chiến Lược Dấu Gạch Chéo Cuối
Google không quan tâm bạn dùng /blog/ hay /blog, nhưng nó có quan tâm nếu bạn trộn lẫn cả hai. Chọn một:
export default defineConfig({
trailingSlash: 'always', // hoặc 'never'
});
Sự không nhất quán tạo ra vấn đề trùng lặp nội dung âm thầm làm hại SEO của bạn.
20. Thêm RSS Feed
Hai tệp và nội dung của bạn có thể được đăng ký — hữu ích cho độc giả, trình tổng hợp, và tính năng nhập feed của Dev.to.
npm install @astrojs/rss
// src/pages/rss.xml.js
import rss from '@astrojs/rss';
import { getCollection } from 'astro:content';
export async function GET(context) {
const posts = await getCollection('blog');
return rss({
title: 'Blog Của Tôi',
description: 'Suy nghĩ của tôi về công nghệ',
site: context.site,
items: posts.map(post => ({
title: post.data.title,
pubDate: post.data.date,
link: `/blog/${post.slug}/`,
})),
});
}
🌍 Quy Trình Triển Khai
21. Triển Khai Lên Các Nền Tảng CDN Edge
Đầu ra mặc định của Astro là HTML tĩnh. Điều đó có nghĩa là nó thuộc về một CDN với phân phối edge toàn cầu — không phải một máy chủ truyền thống. Cloudflare Pages, Netlify, và Vercel đều hỗ trợ Astro mà không cần cấu hình.
# Cloudflare Pages (hỗ trợ đẳng cấp đầu tiên kể từ khi Cloudflare mua lại Astro)
npx astro add cloudflare
Đây là lúc tất cả công việc ở thời điểm build được đền đáp. “Máy chủ” của bạn chỉ là các tệp trên CDN, được phục vụ từ trung tâm dữ liệu gần nhất với mỗi khách truy cập. Muốn xem nó hoạt động thế nào? Dùng thử QuotyAI miễn phí — toàn bộ ứng dụng chạy trên chính kiến trúc này.
22. Hãy Minh Bạch Về output: 'static'
Đó là mặc định, nhưng nêu rõ nó truyền đạt ý định:
export default defineConfig({
output: 'static', // pre-render mọi thứ tại thời điểm build
});
Nếu một đồng nghiệp vô tình thêm một route server, sẽ ngay lập tức thấy rõ rằng có điều gì đó không phù hợp với kiến trúc.
TL;DR
| Danh mục | Thói quen |
|---|---|
| Hình ảnh | Sử dụng <Image /> |
| Font chữ | API Fonts tích hợp (Astro 6) — xử lý tự lưu trữ, fallback, và preload |
| Tạo kiểu | Tailwind v4 qua @tailwindcss/vite, @theme {} trong CSS |
| Tương tác | Mặc định dùng .astro, không phải React; khớp client:* với mức ưu tiên component |
| Hiệu suất | Bật prefetch, thêm View Transitions |
| Nội dung | Content Collections + import { z } from 'astro/zod' + MDX + <Code /> + Sätteri |
| Ghi log | Astro.logger để gỡ lỗi có cấu trúc (Astro 6.2+) |
| i18n | Thiết lập từ ngày đầu, không phải ngày 100 |
| SEO | Sitemap, site:, nhất quán dấu gạch chéo cuối, RSS |
| Triển khai | CDN Edge, output: 'static' minh bạch |
Astro thưởng cho những nhà phát triển biết tận dụng các mặc định của nó. Gửi HTML tĩnh, hydrate có chọn lọc, tối ưu ở thời điểm build — và bạn sẽ có một site nhanh gần như một cách tình cờ.
“Hầu hết các vấn đề về hiệu suất trong phát triển web đều được giải quyết ở thời điểm build, không phải runtime.”
Đọc Thêm
Nếu bài viết này hữu ích với bạn, bạn cũng có thể thích:
- Tại Sao Tôi Dùng Astro Cho Landing Pages và Blog — phân tích quyết định ban đầu
- Vibe Coding vs Mã Nguồn Mở — cách chúng tôi xây dựng site Astro với sự trợ giúp của AI
- Cách Tôi Vận Hành Một Startup AI Sản Xuất Với 30 Đô/Tháng — cơ sở hạ tầng triển khai đằng sau QuotyAI
Câu Hỏi Thường Gặp
Tại sao nên dùng Astro thay vì Next.js cho các site nội dung? Astro ưu tiên HTML và mặc định không tải JavaScript, chỉ hydrate các island tương tác. Next.js trước hết là một framework React, vì vậy bạn phải trả “thuế React” ngay cả trên nội dung tĩnh. Astro được xếp hạng #1 về mức độ hài lòng của nhà phát triển trong khảo sát State of JS 2025 chính xác nhờ sự khác biệt cơ bản này.
Làm thế nào để cài đặt Tailwind v4 trong Astro?
Cài đặt tailwindcss và @tailwindcss/vite, thêm plugin Vite vào astro.config.mjs, và đặt các design token trong CSS với @theme {}. Tích hợp @astrojs/tailwind cũ đã bị deprecated cho v4 — đừng sử dụng nó trong các dự án mới.
Sự khác biệt giữa client:load và client:visible là gì?
client:load hydrate component ngay khi trang tải, trong khi client:visible đợi đến khi component cuộn vào viewport. Sử dụng client:visible cho các component dưới fold để tránh tải và thực thi JavaScript mà người dùng có thể không bao giờ nhìn thấy.
Làm thế nào để thêm font tùy chỉnh trong Astro 6?
Cấu hình font của bạn trong astro.config.mjs sử dụng API Fonts tích hợp với fontProviders.fontsource() hoặc fontProviders.google(), sau đó đặt component <Font cssVariable="--font-inter" preload /> trong layout cơ sở. Astro xử lý tự lưu trữ, fallback, và gợi ý preload một cách tự động.
Content Layer API trong Astro 6 là gì?
Content Layer API mở rộng Content Collections với hỗ trợ live collection — collection trực tiếp fetch dữ liệu tại thời điểm yêu cầu, không cần rebuild khi nội dung CMS thay đổi. Định nghĩa chúng với defineLiveCollection() trong src/live.config.ts.
Tags: astro webdev javascript performance