226 lines
4.7 KiB
Markdown
226 lines
4.7 KiB
Markdown
|
|
---
|
|||
|
|
title: "Astro.js"
|
|||
|
|
contributor: "@tuanductran"
|
|||
|
|
tags: #system, #tuanductran
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
# Astro v6 Architecture Rules (Strict Mode)
|
|||
|
|
|
|||
|
|
## 1. Core Philosophy
|
|||
|
|
|
|||
|
|
- Follow Astro’s “HTML-first / zero JavaScript by default” principle:
|
|||
|
|
- Everything is static HTML unless interactivity is explicitly required.
|
|||
|
|
- JavaScript is a cost → only add when it creates real user value.
|
|||
|
|
|
|||
|
|
- Always think in “Islands Architecture”:
|
|||
|
|
- The page is static HTML
|
|||
|
|
- Interactive parts are isolated islands
|
|||
|
|
- Never treat the whole page as an app
|
|||
|
|
|
|||
|
|
- Before writing any JavaScript, always ask:
|
|||
|
|
"Can this be solved with HTML + CSS or server-side logic?"
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 2. Component Model
|
|||
|
|
|
|||
|
|
- Use `.astro` components for:
|
|||
|
|
- Layout
|
|||
|
|
- Composition
|
|||
|
|
- Static UI
|
|||
|
|
- Data fetching
|
|||
|
|
- Server-side logic (frontmatter)
|
|||
|
|
|
|||
|
|
- `.astro` components:
|
|||
|
|
- Run at build-time or server-side
|
|||
|
|
- Do NOT ship JavaScript by default
|
|||
|
|
- Must remain framework-agnostic
|
|||
|
|
|
|||
|
|
- NEVER use React/Vue/Svelte hooks inside `.astro`
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 3. Islands (Interactive Components)
|
|||
|
|
|
|||
|
|
- Only use framework components (React, Vue, Svelte, etc.) for interactivity.
|
|||
|
|
|
|||
|
|
- Treat every interactive component as an isolated island:
|
|||
|
|
- Independent
|
|||
|
|
- Self-contained
|
|||
|
|
- Minimal scope
|
|||
|
|
|
|||
|
|
- NEVER:
|
|||
|
|
- Hydrate entire pages or layouts
|
|||
|
|
- Wrap large trees in a single island
|
|||
|
|
- Create many small islands in loops unnecessarily
|
|||
|
|
|
|||
|
|
- Prefer:
|
|||
|
|
- Static list rendering
|
|||
|
|
- Hydrate only the minimal interactive unit
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 4. Hydration Strategy (Critical)
|
|||
|
|
|
|||
|
|
- Always explicitly define hydration using `client:*` directives.
|
|||
|
|
|
|||
|
|
- Choose the LOWEST possible priority:
|
|||
|
|
|
|||
|
|
- `client:load`
|
|||
|
|
→ Only for critical, above-the-fold interactivity
|
|||
|
|
|
|||
|
|
- `client:idle`
|
|||
|
|
→ For secondary UI after page load
|
|||
|
|
|
|||
|
|
- `client:visible`
|
|||
|
|
→ For below-the-fold or heavy components
|
|||
|
|
|
|||
|
|
- `client:media`
|
|||
|
|
→ For responsive / conditional UI
|
|||
|
|
|
|||
|
|
- `client:only`
|
|||
|
|
→ ONLY when SSR breaks (window, localStorage, etc.)
|
|||
|
|
|
|||
|
|
- Default rule:
|
|||
|
|
❌ Never default to `client:load`
|
|||
|
|
✅ Prefer `client:visible` or `client:idle`
|
|||
|
|
|
|||
|
|
- Hydration is a performance budget:
|
|||
|
|
- Every island adds JS
|
|||
|
|
- Keep total JS minimal
|
|||
|
|
|
|||
|
|
📌 Astro does NOT hydrate components unless explicitly told via `client:*` :contentReference[oaicite:0]{index=0}
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 5. Server vs Client Logic
|
|||
|
|
|
|||
|
|
- Prefer server-side logic (inside `.astro` frontmatter) for:
|
|||
|
|
- Data fetching
|
|||
|
|
- Transformations
|
|||
|
|
- Filtering / sorting
|
|||
|
|
- Derived values
|
|||
|
|
|
|||
|
|
- Only use client-side state when:
|
|||
|
|
- User interaction requires it
|
|||
|
|
- Real-time updates are needed
|
|||
|
|
|
|||
|
|
- Avoid:
|
|||
|
|
- Duplicating logic on client
|
|||
|
|
- Moving server logic into islands
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 6. State Management
|
|||
|
|
|
|||
|
|
- Avoid client state unless strictly necessary.
|
|||
|
|
|
|||
|
|
- If needed:
|
|||
|
|
- Scope state inside the island only
|
|||
|
|
- Do NOT create global app state unless required
|
|||
|
|
|
|||
|
|
- For cross-island state:
|
|||
|
|
- Use lightweight shared stores (e.g., nano stores)
|
|||
|
|
- Avoid heavy global state systems by default
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 7. Performance Constraints (Hard Rules)
|
|||
|
|
|
|||
|
|
- Minimize JavaScript shipped to client:
|
|||
|
|
- Astro only loads JS for hydrated components :contentReference[oaicite:1]{index=1}
|
|||
|
|
|
|||
|
|
- Prefer:
|
|||
|
|
- Static rendering
|
|||
|
|
- Partial hydration
|
|||
|
|
- Lazy hydration
|
|||
|
|
|
|||
|
|
- Avoid:
|
|||
|
|
- Hydrating large lists
|
|||
|
|
- Repeated islands in loops
|
|||
|
|
- Overusing `client:load`
|
|||
|
|
|
|||
|
|
- Each island:
|
|||
|
|
- Has its own bundle
|
|||
|
|
- Loads independently
|
|||
|
|
- Should remain small and focused :contentReference[oaicite:2]{index=2}
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 8. File & Project Structure
|
|||
|
|
|
|||
|
|
- `/pages`
|
|||
|
|
- Entry points (SSG/SSR)
|
|||
|
|
- No client logic
|
|||
|
|
|
|||
|
|
- `/components`
|
|||
|
|
- Shared UI
|
|||
|
|
- Islands live here
|
|||
|
|
|
|||
|
|
- `/layouts`
|
|||
|
|
- Static wrappers only
|
|||
|
|
|
|||
|
|
- `/content`
|
|||
|
|
- Markdown / CMS data
|
|||
|
|
|
|||
|
|
- Keep `.astro` files focused on composition, not behavior
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 9. Anti-Patterns (Strictly Forbidden)
|
|||
|
|
|
|||
|
|
- ❌ Using hooks in `.astro`
|
|||
|
|
- ❌ Turning Astro into SPA architecture
|
|||
|
|
- ❌ Hydrating entire layout/page
|
|||
|
|
- ❌ Using `client:load` everywhere
|
|||
|
|
- ❌ Mapping lists into hydrated components
|
|||
|
|
- ❌ Using client JS for static problems
|
|||
|
|
- ❌ Replacing server logic with client logic
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 10. Preferred Patterns
|
|||
|
|
|
|||
|
|
- ✅ Static-first rendering
|
|||
|
|
- ✅ Minimal, isolated islands
|
|||
|
|
- ✅ Lazy hydration (`visible`, `idle`)
|
|||
|
|
- ✅ Server-side computation
|
|||
|
|
- ✅ HTML + CSS before JS
|
|||
|
|
- ✅ Progressive enhancement
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 11. Decision Framework (VERY IMPORTANT)
|
|||
|
|
|
|||
|
|
For every feature:
|
|||
|
|
|
|||
|
|
1. Can this be static HTML?
|
|||
|
|
→ YES → Use `.astro`
|
|||
|
|
|
|||
|
|
2. Does it require interaction?
|
|||
|
|
→ NO → Stay static
|
|||
|
|
|
|||
|
|
3. Does it require JS?
|
|||
|
|
→ YES → Create an island
|
|||
|
|
|
|||
|
|
4. When should it load?
|
|||
|
|
→ Choose LOWEST priority `client:*`
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 12. Mental Model (Non-Negotiable)
|
|||
|
|
|
|||
|
|
- Astro is NOT:
|
|||
|
|
- Next.js
|
|||
|
|
- SPA framework
|
|||
|
|
- React-first system
|
|||
|
|
|
|||
|
|
- Astro IS:
|
|||
|
|
- Static-first renderer
|
|||
|
|
- Partial hydration system
|
|||
|
|
- Performance-first architecture
|
|||
|
|
|
|||
|
|
- Think:
|
|||
|
|
❌ “Build an app”
|
|||
|
|
✅ “Ship HTML + sprinkle JS”
|