وب مدرن، رابط کاربری و تجربهی وب · فصل ۶ — Static-first، SEO و Performance · 53
Astro, Static-first Content and Islands
Design one Astro content route with an explicit prerender/on-demand decision, keep most markup server/static by default, add only evidence-justified client/server islands, and verify the emitted/runtime boundary. میتواند «Astro, Static-first Content و Islands» را در یک feature محدود طراحی/پیادهسازی کند و correctness، accessibility یا failure behavior مرتبط را اثبات کند.
Lesson summary
Design one Astro content route with an explicit prerender/on-demand decision, keep most markup server/static by default, add only evidence-justified client/server islands, and verify the emitted/runtime boundary.
میتواند «Astro, Static-first Content و Islands» را در یک feature محدود طراحی/پیادهسازی کند و correctness، accessibility یا failure behavior مرتبط را اثبات کند.
This lesson produces
میتواند «Astro, Static-first Content و Islands» را در یک feature محدود طراحی/پیادهسازی کند و correctness، accessibility یا failure behavior مرتبط را اثبات کند.
Who it is for
Foundation
Worked baseline, explicit evidence table, safe local fixture and one guided failure probe.
Repair
Reduce to one failing contract, observe evidence, repair, then restore full case.
Experienced
Skip syntax walkthrough; require independent implementation, mutation evidence and residual-risk statement.
Prerequisites
1. First screen: the boundary is the product decision
A documentation product has three visibly different needs on one route. The article body changes only when editors publish. A code-filter control must respond in the browser. A small account badge is personalized and should not force the entire article to become request-time HTML. The weak solution is to label the whole page “Astro” and assume the framework has already made the performance decision. The stronger solution is to write down the rendering contract before adding directives.
For this lesson, the contract is narrow. Keep stable content in the static/server-rendered shell. Hydrate only a region that truly needs browser interaction. Use a server-rendered dynamic boundary only when freshness or personalization requires server work, and only when the deployment runtime can support it. Then inspect generated or runtime evidence instead of treating words such as “islands” or “static-first” as proof.
Your evidence artifact is Astro Rendering & Island Boundary Record v1. It must separate what you observed from what you inferred. A passing architecture diagram is not enough. The record needs the route decision, island decisions, an emitted-output observation, at least one mutation, a repair, a changed-context transfer, and one residual limitation.
2. Route orientation: choose the shortest route, keep the same evidence bar
Foundation route: begin with the supplied route plan and classify each region as stable content, browser-interactive content, or volatile/personalized content. Use the worked evidence matrix before changing directives.
Repair route: if you already know Astro but your build ships unnecessary JavaScript or your route boundary is unclear, isolate one failed contract. Ask which region caused the failure, which directive or rendering mode created it, and what observable artifact would prove the repair.
Experienced route: skip the syntax tour. Produce the boundary record directly, run the mutation suite, and defend why each hydrated or deferred region exists. The fast path removes explanation, not evidence.
All routes must preserve five dimensions: rendering_mode, zero_js_default, client_island, server_island, and emitted_evidence. None of them may be replaced by “Astro is fast by default.”
3. Mental model: one page, three execution locations
Think of an Astro page as a composition of regions whose work can happen at different times and places.
Build-time/static shell. Stable article markup can be produced ahead of visits. In the default static mode, Astro prerenders routes unless you opt a route into on-demand rendering. This is a route-level decision, not a claim that the site can never execute server code.
Browser client island. A UI-framework component can contribute HTML without becoming a browser application. A client:* directive is the explicit request to hydrate that component. Choosing client:load, client:idle, or client:visible changes when the browser work starts, so the directive is part of the performance and UX contract.
Server island or on-demand region. Volatile or personalized content may need server execution. An on-demand route uses a server runtime and adapter. A server island uses server:defer to isolate dynamic server-rendered content from the rest of the page and also requires a compatible adapter/runtime.
This model prevents a common category error: a client island and a server island solve different execution problems. One brings browser-side behavior to a component. The other delays or isolates server-rendered dynamic content.
4. Foundation layer: prerendering and zero-JavaScript default
Start from freshness. If a route’s content is valid until the next deployment or content build, prerendering is a strong default. If the response must depend on per-request cookies, current server data, or another request-time condition, on-demand rendering may be justified. Do not switch an entire site to request-time rendering merely because one region is dynamic.
Astro’s static-first behavior also applies at component boundaries. A framework component rendered without a client:* directive contributes rendered HTML but does not automatically require its client runtime. This means “React component exists” and “React JavaScript ships to the browser” are different statements.
The lab encodes this distinction. A presentational summary component has no client directive. The filter has client:visible because it becomes interactive in the browser. The account badge uses a server-island boundary in the reference plan. The model records only the filter as a client bundle candidate.
A crucial limitation: the deterministic lab model is evidence about the lesson contract, not a substitute for an actual Astro build. In a publisher runtime with Astro installed, repeat the checks against the real dist/ output and preview behavior before making production performance claims.
5. Deep explanation: client islands, server islands, and route mode
A client island should have a reason that can be stated without naming the framework: “this region needs browser interaction after initial HTML.” If there is no browser-side state, event handling, or API available only in the client, hydration may be unnecessary.
Loading priority matters. client:load requests eager hydration and is suitable only when interaction is immediately important. client:idle defers until the browser is less busy. client:visible waits until the component enters the viewport. These are scheduling choices, not quality grades. The right directive follows from when the interaction is needed.
On-demand rendering is different. A route can opt out of prerendering and execute on each request when a server adapter is present. That is useful when the entire response depends on request-time state. If only a small region is volatile, a server island can preserve a mostly static shell while the dynamic region renders separately. This lets you reason about cacheability and latency region by region.
Server islands have their own constraints. They require an adapter/runtime. Their props must cross a serialization boundary. Fallback content should remain meaningful and should not create an accessibility dead end while the dynamic region loads. None of those facts imply that a server island is always the right solution for personalization.
Finally, performance language must remain bounded. Fewer client bundles is observable. Smaller emitted JavaScript is observable. A specific hydration boundary is inspectable. “Good Core Web Vitals” is not proven until you measure the relevant metrics in an appropriate environment.
6. Worked example: documentation route
The reference design keeps the article shell prerendered. StaticSummary is rendered without a client directive. CodeFilter uses client:visible because filtering is only needed when the widget is reached. AccountBadge is treated as personalized server content and isolated with server:defer; the deployment plan therefore records that an adapter is required.
A compact source sketch looks like this:
<StaticSummary items={summary} />
<CodeFilter client:visible items={snippets} />
<AccountBadge server:defer>
<span slot="fallback">Account</span>
</AccountBadge>
The evidence record should not merely copy this code. It should include a row such as: “CodeFilter — interaction required in browser — client:visible — expected client bundle: yes — observed in deterministic emitted model: yes — production Astro build: not observed in this acceptance run.” That final qualifier matters.
For the route itself, record: “article freshness is deployment-bound — route remains prerendered — personalized badge isolated — adapter required because of server island.” If the business requirement changes so that the article itself must reflect request-time entitlement, the route decision must be revisited rather than defended by habit.
7. Failure modes: regressions must change the evidence
Mutation A: hydrate a presentational component. Add client:load to a region that has no browser behavior. The emitted model must now report an additional client bundle candidate. If your conclusion does not change, your evidence process is too weak.
Mutation B: remove hydration from the interactive filter. The initial markup may still appear, but the browser interaction contract is no longer satisfied. A screenshot of the initial page would miss the defect; an interaction-oriented check or boundary model catches it.
Mutation C: force volatile personalized content into a fully prerendered assumption. The content freshness contract breaks. This is not a JavaScript-size failure; it is a rendering-mode failure.
Mutation D: hydrate the whole page. The design may still “work,” but it violates the bounded-island decision and expands the client runtime surface. Compare what ships and which regions now depend on browser JavaScript.
Mutation E: keep a server island but remove adapter support. The source-level intention exists, but the deployment contract is incomplete. Architecture must include runtime compatibility.
8. Experienced bridge: optimize decisions, not slogans
Experienced teams often know how to type the directives but still benefit from an explicit decision record. The useful question is not “Can Astro do this?” It is “Which region needs which execution location, and what evidence will prove that choice?”
A good review can be performed as a diff. When a new island appears, require a stated interaction or freshness need. When a route moves to on-demand rendering, identify the request-time dependency. When a directive changes from client:visible to client:load, identify the UX requirement that justifies earlier hydration.
Treat emitted assets as a budget with provenance. A JavaScript file should be attributable to a specific interactive region. If the team cannot explain which user interaction needs a bundle, the boundary deserves review. This does not mean “zero JavaScript at all costs”; it means browser JavaScript must earn its place.
9. Alternatives and tradeoffs
A fully prerendered page is simple to cache and deploy, but it cannot represent arbitrary per-request state without an additional dynamic mechanism. A fully on-demand route can use request-time data naturally, but it moves the whole route behind a server runtime. A server island can split the difference for a small dynamic region, at the cost of an additional request/runtime boundary and fallback behavior.
Client hydration has similar tradeoffs. client:load improves readiness for an immediately interactive control but competes for early browser resources. client:visible can avoid loading a below-the-fold widget for users who never reach it, but interaction cannot begin before visibility-triggered hydration completes. The choice must be tied to UX, not a universal hierarchy.
Whole-page SPA embedding is also a valid tool for a genuinely app-like region. It is simply a different contract from a mostly static content page. This lesson does not forbid SPAs; it prevents accidental SPA-like hydration from being mistaken for an islands decision.
10. Guided and independent practice
Run node --test test/public-contract.test.mjs in the learner fixture. Then run node src/inspect-boundary.mjs to regenerate the deterministic evidence snapshot. The checks are deliberately local and dependency-free so the core reasoning can be graded offline.
Complete these steps in order:
- State why the documentation shell is prerendered.
- Explain why
StaticSummaryhas no client directive. - Defend the filter’s client directive and loading priority.
- Explain why the account badge is a server-side concern and why adapter compatibility is part of the contract.
- Run each mutation and record the changed evidence.
- Repair the plan and rerun the checks.
- Complete the product-catalog transfer without copying component names from the documentation example.
The independent transfer uses stable product description, a comparison widget, and volatile inventory. Your solution may choose an on-demand route or a server island for inventory, but the decision must follow the stated freshness and runtime constraints.
11. Verification and evidence record
The record has six required evidence dimensions: implementation artifact, observable generated/runtime behavior, failure mutation result, repair result, changed-context transfer, and residual limitation.
Use three labels in your notes: Observed, Inferred, and Not observed. For example: “Observed: deterministic model reports one client bundle candidate for CodeFilter. Inferred: a real Astro build should create a client asset for the hydrated framework component. Not observed: browser network trace and production adapter behavior.” This prevents synthetic acceptance evidence from silently turning into a production claim.
When a real Astro runtime is available, extend—not replace—the record with the actual build command, Astro version, adapter version, dist/ inspection, preview behavior, and browser network evidence where relevant. Keep the local deterministic checks because they remain useful for regression isolation.
Residual limitations are mandatory. A correct boundary in this fixture does not prove Core Web Vitals, search ranking, CDN behavior, production personalization latency, or accessibility under every assistive technology.
12. Assessment and transfer
Retrieval: explain the difference between prerendered route output, client hydration, and a server island without using “fast” as the explanation.
Application: implement the bounded documentation route and complete the evidence record.
Diagnosis: choose one mutation and predict the first observable failure before running it.
Decision: defend one boundary against a plausible alternative. For example, explain why a small account badge does not require making the entire article route on-demand.
Transfer: for a product catalog, keep stable descriptive content static where possible, hydrate the comparison widget only if browser interaction requires it, and choose a freshness mechanism for inventory. The correct answer is not a fixed directive. The correct answer is a traceable decision plus evidence.
13. References and freshness boundary
This lesson’s technology facts are bounded to current official Astro documentation reviewed on 2026-09-13. The official Islands Architecture guidance describes static HTML by default for framework components and explicit client:* hydration. The on-demand rendering guide documents prerendered-by-default route behavior with adapter-backed request-time rendering. The server-islands guide documents server:defer and adapter-backed delayed server rendering.
The source review does not expand the frozen Bible. It only confirms that the existing claims remain within the official guidance. Recheck the sources by the frozen review date, 2026-10-17, or earlier if Astro changes rendering or directive semantics.
Do not convert architecture vocabulary into guarantees. This lesson proves a bounded rendering/island decision method and a local evidence process. Real production claims still require the corresponding production observations.
Assessment
There is no answer key in this lesson pack; answer it yourself and mark honestly. "Needs review" sends the lesson to your review queue.
WEB-015-S1 retrieval
State the WEB-015 route/island contract: when the bounded route is prerendered versus on-demand, which content stays zero-JavaScript by default, and one explicit non-goal.
WEB-015-S2 application
Implement the bounded docs route with a static article/summary region, a browser-interactive CodeFilter client island, and a deferred AccountBadge server island; record the route decision, region boundaries, emitted-model evidence, and residual limitation.
WEB-015-S3 diagnosis
Predict, run, diagnose, and repair one deliberate rendering/island mutation affecting route mode, hydration, server-island/runtime support, or evidence consistency.
WEB-015-S4 decision
Defend the chosen static/client/server boundary against a plausible alternative using freshness, interactivity, and adapter/runtime constraints; state one residual uncertainty and do not claim Core Web Vitals without measurement.
WEB-015-S5 transfer
Independently design the changed-context product-catalog route: choose prerender/on-demand behavior, identify static, client-interactive, and server-dynamic regions, define an evidence method, and state one residual limitation without reusing original fixture identifiers.
Assessment rubric
Critical dimensions:
- RENDERING_MODE — Choose prerender versus on-demand from freshness/runtime requirements rather than from the Astro label.
- ZERO_JS_AND_CLIENT_ISLAND — Keep unhydrated framework content zero-JavaScript by default and add a client directive only where browser interaction requires it.
- SERVER_ISLAND_RUNTIME_BOUNDARY — Use a server island only for justified dynamic server content and keep adapter/runtime support explicit.
- EMITTED_EVIDENCE_AND_CLAIM_BOUNDARY — Separate emitted/output evidence from inference; internal synthetic evidence is never relabeled as a real Astro build, browser observation, field performance, or SEO proof.
- CHANGED_CONTEXT_TRANSFER — Apply the contract independently to the product-catalog case, including route decision, static/client/server regions, evidence method, and a residual limitation.
Blocking assessments: S2, S3 and S5. S1 and S4 are non-blocking but still require scope discipline.
Forbidden overclaims remain explicit: Astro does not require every route to be static; adding a React component does not automatically ship React JavaScript; more islands do not automatically improve performance; server and client islands are not interchangeable; static-first architecture does not prove Core Web Vitals without measurement.
Publisher-runtime execution remains deferred to the pinned runtime. The internal synthetic oracle is not publisher-runtime observation. Browser/assistive-technology evidence is not claimed.
References & freshness
Case studies
Lab files
This learner fixture tests the reasoning contract offline. It includes Astro-shaped source files plus a dependency-free deterministic emitted-output model. The public acceptance run does not claim that Astro itself was installed, built, previewed, or observed in a browser.
Run:
node --test test/public-contract.test.mjs
node src/inspect-boundary.mjs
Then complete evidence/Astro_Rendering_Island_Boundary_Record_v1.json, run the mutations described in the lesson, repair the plan, and complete the product-catalog transfer.
When a publisher runtime with pinned Astro and adapter packages is available, extend the evidence with a real build and preview. Do not rewrite deterministic model output as real Astro observation.
Lesson media & slides
Teaching files (download)