Frontend Development 17 min read

Understanding Islands Architecture: From MPA vs SPA to Implementation in Astro, Fresh, and Island.js

The article explains the origins and advantages of the Islands architecture, compares MPA and SPA approaches, details how frameworks like Astro and Fresh implement Islands, and shares practical insights and performance data from the author’s own Island.js project.

ByteDance Web Infra
ByteDance Web Infra
ByteDance Web Infra
Understanding Islands Architecture: From MPA vs SPA to Implementation in Astro, Fresh, and Island.js

Islands architecture has become a hot topic this year, with well‑known new frameworks such as Fresh and Astro serving as typical examples. This article introduces the background of Islands architecture, analyzes its advantages over traditional solutions like Next.js and Gatsby, and examines the implementation principles of related community frameworks.

MPA and SPA Trade‑offs

MPA (Multi‑page Application) loads multiple full HTML pages from the server, each with its own URL, while SPA (Single‑page Application) loads a single HTML shell and then fetches JavaScript bundles to build and hydrate the DOM. MPA offers better first‑paint performance and SEO friendliness, whereas SPA provides smoother subsequent navigation at the cost of higher engineering complexity.

Performance

MPA delivers the complete HTML immediately, giving faster first‑screen load; SPA must download and execute the JS bundle first. However, SPA excels in later page transitions because only the needed components are fetched.

SEO

Because MPA returns full HTML for each page, it is more SEO‑friendly; SPA content appears only after JavaScript execution, which can hinder crawlers.

Routing and State Management

MPA relies on server‑side URLs, requiring no client router, while SPA needs client‑side routing (hashchange or History API) and often complex state‑management solutions such as Redux, Valtio, Zustand, or Reduck.

Overall, MPA provides better initial performance, while SPA offers better subsequent navigation but introduces higher complexity, SEO challenges, and slower first‑screen load.

What Is Islands Architecture?

Proposed in 2019 and popularized by Preact author Json Miller in 2021, Islands architecture targets SSR/SSG applications. Only interactive components (the “islands”) undergo hydration, while static components remain as pure server‑rendered HTML.

Implementation Principles

Astro

In Astro, all components are static by default. To activate an interactive component, the client:load directive is added.

// index.astro
import MyReactComponent from '../components/MyReactComponent.jsx';
---

With hydration:

// index.astro
import MyReactComponent from '../components/MyReactComponent.jsx';
---

Astro bundles only the Islands components and injects the appropriate framework‑specific render functions during hydration.

Fresh

Fresh, a full‑stack framework based on Preact and Deno, stores Island components in an islands directory. Its rendering pipeline scans this directory, intercepts vnode creation to wrap Island components with a comment tag containing an ID and props index, then uses renderToString to produce HTML.

// island-jsx-runtime.js
import * as jsxRuntime from 'react/jsx-runtime';
export const data = { islandProps: [], islandToPathMap: {} };
const originJsx = jsxRuntime.jsx;
const originJsxs = jsxRuntime.jsxs;
const internalJsx = (jsx, type, props, ...args) => {
  if (props && props.__island) {
    data.islandProps.push(props || {});
    const id = type.name;
    data.islandToPathMap[id] = props.__island;
    delete props.__island;
    return jsx('div', {
      __island: `${id}:${data.islandProps.length - 1}`,
      children: jsx(type, props, ...args)
    });
  }
  return jsx(type, props, ...args);
};
export const jsx = (...args) => internalJsx(originJsx, ...args);
export const jsxs = (...args) => internalJsx(originJsxs, ...args);
export const Fragment = jsxRuntime.Fragment;

During build time, the __island prop is transformed to include the component’s file path, enabling the runtime to locate and hydrate each Island separately.

Island.js (Author’s Practice)

The author built island.js , a VitePress‑like solution supporting MDX and combining Islands with MPA. Interactive components are marked with a __island prop:

import { Aside } from '../components/Aside';
export function Layout() {
  return
;
}

The custom JSX runtime collects Island props and IDs, injects them as a island-props script tag, and generates a virtual module that registers all Islands on the client.

// virtual module example
import { Aside } from './Aside.tsx!!island!!Users/project/src/Layout.tsx';
window.islands = { Aside };
window.ISLAND_PROPS = JSON.parse(document.getElementById('island-props').textContent);

Client‑side hydration loops through elements with the __island attribute, retrieves the corresponding component and props, and calls hydrateRoot (or createRoot ) from React‑DOM.

import { hydrateRoot, createRoot } from 'react-dom/client';
const islands = document.querySelectorAll('[__island]');
for (let i = 0; i < islands.length; i++) {
  const island = islands[i];
  const [id, index] = island.getAttribute('__island').split(':');
  const Element = window.ISLANDS[id];
  hydrateRoot(island,
);
}

Performance measurements show Islands mode reduces HTTP payload by ~60% and improves DCL by ~40% compared to pure SPA.

Applicability

Islands can be framework‑agnostic; the same concepts apply to Vue, Solid, Svelte, etc., by replacing the SSR runtime, renderToString, and hydrate functions. However, Vue’s “Shell” optimization already achieves a similar effect through static VNode marking and partial client bundles, making Islands less beneficial for Vue‑based tools like VitePress.

Other frameworks lacking static‑node markers (e.g., Solid, Svelte) may benefit more from Islands to avoid full‑page hydration.

Conclusion

Islands architecture offers a middle ground between MPA and SPA by delivering fast first‑screen HTML while lazily hydrating only interactive parts, leading to lower JavaScript payloads and better performance for content‑heavy sites.

frontendssrSPAHydrationAstroFreshIslands ArchitectureMPA
ByteDance Web Infra
Written by

ByteDance Web Infra

ByteDance Web Infra team, focused on delivering excellent technical solutions, building an open tech ecosystem, and advancing front-end technology within the company and the industry | The best way to predict the future is to create it

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.