islands-architecture

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Islands Architecture

Islands架构

tl;dr: The islands architecture encourages small, focused chunks of interactivity within server-rendered web pages. The output of islands is progressively enhanced HTML, with more specificity around how the enhancement occurs. Rather than a single application being in control of full-page rendering, there are multiple entry points. The script for these "islands" of interactivity can be delivered and hydrated independently, allowing the rest of the page to be just static HTML.
简而言之:Islands架构鼓励在服务器渲染的网页中加入小型、聚焦的交互模块。Islands架构的输出是渐进增强的HTML,并且对增强的实现方式有更明确的定义。它不再由单个应用控制整页渲染,而是存在多个入口点。这些“交互孤岛”的脚本可以独立交付和水化,页面其余部分则仅为静态HTML。

When to Use

适用场景

  • Use this for primarily static websites that need sprinkles of interactivity (blogs, product pages, news sites)
  • This is helpful when you want to reduce the volume of JavaScript shipped to the client
  • Use this when SEO and fast initial page loads are priorities alongside selective interactivity
  • 适用于以静态内容为主,但需要少量交互的网站(如博客、产品页、新闻站点)
  • 当你希望减少发送给客户端的JavaScript体积时,这种架构会很有帮助
  • 当SEO和快速初始页面加载是优先事项,同时又需要选择性交互时,可采用该架构

Instructions

实施步骤

  • Identify static and dynamic regions of each page separately
  • Use frameworks like Astro, Marko, or Eleventy that support islands architecture
  • Hydrate interactive components independently using
    client:visible
    or similar directives
  • Keep the majority of the page as static HTML with zero JavaScript cost
  • 分别识别每个页面的静态区域和动态区域
  • 使用支持Islands架构的框架,如Astro、Marko或Eleventy
  • 使用
    client:visible
    或类似指令独立水化交互组件
  • 保持页面大部分内容为静态HTML,无JavaScript开销

Details

详细说明

Loading and processing excess JavaScript can hurt performance. However, some degree of interactivity and JavaScript is often required, even in primarily static websites. We have discussed variations of Static Rendering that enable you to build applications that try to find the balance between:
  1. Interactivity comparable to Client-Side Rendered (CSR) applications
  2. SEO benefits that are comparable to SSR applications.
The core principle for SSR is that HTML is rendered on the server and shipped with necessary JavaScript to rehydrate it on the client. Rehydration is the process of regenerating the state of UI components on the client-side after the server renders it. Since rehydration comes at a cost, each variation of SSR tries to optimize the rehydration process. This is mainly achieved by partial hydration of critical components or streaming of components as they get rendered. However, the net JavaScript shipped eventually in the above techniques remains the same.
The term Islands architecture was popularized by Katie Sylor-Miller and Jason Miller to describe a paradigm that aims to reduce the volume of JavaScript shipped through "islands" of interactivity that can be independent delivered on top of otherwise static HTML. Islands are a component-based architecture that suggests a compartmentalized view of the page with static and dynamic islands. The static regions of the page are pure non-interactive HTML and do not need hydration. The dynamic regions are a combination of HTML and scripts capable of rehydrating themselves after rendering.
加载和处理过多的JavaScript会影响性能。然而,即使是以静态内容为主的网站,通常也需要一定程度的交互性和JavaScript支持。我们之前讨论过多种静态渲染的变体,它们能帮助你在以下两者之间找到平衡:
  1. 可与客户端渲染(CSR)应用媲美的交互性
  2. 可与服务器端渲染(SSR)应用媲美的SEO优势
SSR的核心原则是在服务器上渲染HTML,并附带必要的JavaScript以在客户端进行水化。水化是指服务器渲染后,在客户端重新生成UI组件状态的过程。由于水化会产生成本,因此各种SSR变体都在尝试优化水化过程,主要通过关键组件的部分水化或组件渲染时的流式传输来实现。但上述技术最终发送的JavaScript总量并没有改变。
Islands架构这一术语由Katie Sylor-Miller和Jason Miller推广,用于描述一种旨在通过“交互孤岛”减少JavaScript发送量的范式,这些交互孤岛可以独立部署在纯静态HTML之上。Islands是一种基于组件的架构,它将页面划分为静态和动态的独立模块。页面的静态区域是纯非交互HTML,无需水化;动态区域则是HTML与脚本的组合,能够在渲染后自行完成水化。

Islands of dynamic components

动态组件孤岛

Most pages are a combination of static and dynamic content. Usually, a page consists of static content with sprinkles of interactive regions that can be isolated. For example:
  1. Blog posts, news articles, and organization home pages contain text and images with interactive components like social media embeds and chat.
  2. Product pages on e-commerce sites contain static product descriptions and links to other pages on the app. Interactive components such as image carousels and search are available in different regions of the page.
  3. A typical bank account details page contains a list of static transactions with filters providing some interactivity.
Static content is stateless, does not fire events, and does not need rehydration after rendering. After rendering, dynamic content (buttons, filters, search bar) has to be rewired to its events. The DOM has to be regenerated on the client-side (virtual DOM). This regeneration, rehydration, and event handling functions contribute to the JavaScript sent to the client.
The Islands architecture facilitates server-side rendering of pages with all of their static content. However, in this case, the rendered HTML will include placeholders for dynamic content. The dynamic content placeholders contain self-contained component widgets. Each widget is similar to an app and combines server-rendered output and JavaScript used to hydrate the app on the client.
In progressive hydration, the hydration architecture of the page is top-down. The page controls the scheduling and hydration of individual components. Each component has its hydration script in the Islands architecture that executes asynchronously, independent of any other script on the page. A performance issue in one component should not affect the other.
大多数页面都是静态内容和动态内容的组合。通常,页面以静态内容为主,同时包含一些可独立分离的交互区域。例如:
  1. 博客文章、新闻报道和企业主页包含文本和图片,同时附带社交媒体嵌入、聊天框等交互组件。
  2. 电商产品页包含静态的产品描述和应用内其他页面的链接,而图片轮播、搜索等交互组件分布在页面的不同区域。
  3. 典型的银行账户详情页包含静态的交易列表,同时提供带交互性的筛选功能。
静态内容是无状态的,不会触发事件,渲染后也不需要水化。而动态内容(如按钮、筛选器、搜索栏)在渲染后需要重新绑定事件,DOM需要在客户端重新生成(虚拟DOM)。这种重新生成、水化和事件处理的代码都会增加发送给客户端的JavaScript体积。
Islands架构支持在服务器端渲染包含所有静态内容的页面,但在这种情况下,渲染后的HTML会包含动态内容的占位符。这些动态内容占位符包含独立的组件小部件,每个小部件都类似一个小型应用,结合了服务器渲染的输出和用于在客户端水化的脚本。
在渐进式水化中,页面的水化架构是自上而下的,由页面控制各个组件的调度和水化。而在Islands架构中,每个组件都有自己的水化脚本,可独立于页面上的其他脚本异步执行,某个组件的性能问题不会影响其他组件。

Implementing Islands

实现Islands架构

The Island architecture borrows concepts from different sources and aims to combine them optimally. Template-based static site generators such as Jekyll and Hugo support the rendering of static components to pages. Most modern JavaScript frameworks also support isomorphic rendering, which allows you to use the same code to render elements on the server and client.
Jason's post suggests the use of
requestIdleCallback()
to implement a scheduling approach for hydrating components. Static isomorphic rendering and scheduling of component level partial hydration can be built into a framework to support Islands architecture. Thus, the framework should:
  1. Support static rendering of pages on the server with zero JavaScript.
  2. Support embed of independent dynamic components via placeholders in static content. Each dynamic component contains its scripts and can hydrate itself using requestIdleCallback() as soon as the main thread is free.
  3. Allow isomorphic rendering of components on the server with hydration on the client to recognize the same component at both ends.
Islands架构借鉴了不同技术的理念,并旨在将它们优化组合。基于模板的静态站点生成器(如JekyllHugo)支持将静态组件渲染到页面中;大多数现代JavaScript框架也支持同构渲染,允许使用相同的代码在服务器和客户端渲染元素。
Jason的文章建议使用
requestIdleCallback()
来实现组件水化的调度策略。静态同构渲染和组件级部分水化的调度可以集成到框架中,以支持Islands架构。因此,框架需要满足以下要求:
  1. 支持在服务器端静态渲染页面,无需JavaScript。
  2. 支持在静态内容中通过占位符嵌入独立的动态组件,每个动态组件包含自身的脚本,可在主线程空闲时通过requestIdleCallback()自行完成水化。
  3. 允许组件在服务器端同构渲染,并在客户端水化,以确保两端识别的是同一个组件。

Frameworks

相关框架

Different frameworks today are capable of supporting the Islands architecture. Notable among them are:
  1. Marko: Marko is an open-source framework developed and maintained by eBay to improve server rendering performance. It supports Islands architecture by combining streaming rendering with automatic partial hydration. HTML and other static assets are streamed to the client as soon as they are ready. Automatic partial hydration allows interactive components to hydrate themselves. Hydration code is only shipped for interactive components, which can change the state on the browser. It is isomorphic, and the Marko compiler generates optimized code depending on where it will run (client or server).
  2. Astro: Astro is a static site builder that can generate lightweight static HTML pages from UI components built in other frameworks such as React, Preact, Svelte, Vue, and others. Components that need client-side JavaScript are loaded individually with their dependencies. Thus it provides built-in partial hydration. Astro can also lazy-load components depending on when they become visible.
  3. Eleventy + Preact: Markus Oberlehner demonstrates the use of Eleventy, a static site generator with isomorphic Preact components that can be partially hydrated. It also supports lazy hydration. The component itself declaratively controls the hydration of the component. Interactive components use a
    WithHydration
    wrapper so that they are hydrated on the client.
Note that Marko and Eleventy pre-date the definition of Islands provided by Jason but contain some of the features required to support it. Astro, however, was built based on the definition and inherently supports the Islands architecture.
目前有多个框架支持Islands架构,其中比较知名的有:
  1. MarkoMarko是由eBay开发和维护的开源框架,旨在提升服务器渲染性能。它通过流式渲染与自动部分水化的组合来支持Islands架构,HTML和其他静态资源一旦准备好就会流式传输到客户端。自动部分水化允许交互组件自行水化,仅为那些能在浏览器中改变状态的交互组件发送水化代码。Marko是同构框架,其编译器会根据运行环境(客户端或服务器)生成优化后的代码。
  2. AstroAstro是一个静态站点生成器,可从React、Preact、Svelte、Vue等其他框架构建的UI组件生成轻量级静态HTML页面。需要客户端JavaScript的组件会与其依赖项一起单独加载,因此Astro提供了内置的部分水化功能,还可以根据组件的可见时机进行懒加载。
  3. Eleventy + PreactMarkus Oberlehner展示了如何将静态站点生成器Eleventy与可部分水化的同构Preact组件结合使用,该方案还支持懒加载。组件本身可声明式地控制自身的水化过程,交互组件通过
    WithHydration
    包装器实现客户端水化。
需要注意的是,Marko和Eleventy的出现早于Jason提出的Islands定义,但它们已经包含了支持该架构的部分特性。而Astro则是基于Islands定义构建的,天生支持Islands架构。

Sample implementation

示例实现

The following is a sample blog page implemented using Astro. The page SamplePost imports one interactive component, SocialButtons. This component is included in the HTML at the required position via markup.
astro
// Component Imports
import { SocialButtons } from '../../components/SocialButtons.js';

<html lang="en">
 <head>
   <link rel="stylesheet" href="/blog.css" />
 </head>

 <body>
   <div class="layout">
     <article class="content">
       <section class="intro">
         <h1 class="title">Post title (static)</h1>
         <br/>
         <p>Post sub-title (static)</p>
       </section>
       <section class="intro">
           <p>This is the post content with images that is rendered by the server.</p>
           <p>The next section contains the interactive social buttons component which includes its script.</p>
       </section>
       <section class="social">
           <div>
           <SocialButtons client:visible></SocialButtons>
           </div>
       </section>
     </article>
   </div>
 </body>
</html>
js
// SocialButtons.js
import { useState } from "preact/hooks";

export function SocialButtons() {
  const [count, setCount] = useState(0);
  const add = () => setCount((i) => i + 1);
  const subtract = () => setCount((i) => i - 1);
  return (
    <>
      <div>{count} people liked this post</div>
      <div align="right">
        <button onclick={add}>Like</button>
        <button onclick={subtract}>Unlike</button>
      </div>
    </>
  );
}
The
SocialButtons
component is a Preact component with its HTML, and corresponding event handlers included.
The component is embedded in the page at run time and hydrated on the client-side so that the click events function as required.
Astro allows for a clean separation between HTML, CSS, and scripts and encourages component-based design. It is easy to install and start building websites with this framework.
以下是使用Astro实现的示例博客页面。SamplePost页面导入了一个名为SocialButtons的交互组件,并通过标记将其嵌入到HTML的指定位置。
astro
// Component Imports
import { SocialButtons } from '../../components/SocialButtons.js';

<html lang="en">
 <head>
   <link rel="stylesheet" href="/blog.css" />
 </head>

 <body>
   <div class="layout">
     <article class="content">
       <section class="intro">
         <h1 class="title">Post title (static)</h1>
         <br/>
         <p>Post sub-title (static)</p>
       </section>
       <section class="intro">
           <p>This is the post content with images that is rendered by the server.</p>
           <p>The next section contains the interactive social buttons component which includes its script.</p>
       </section>
       <section class="social">
           <div>
           <SocialButtons client:visible></SocialButtons>
           </div>
       </section>
     </article>
   </div>
 </body>
</html>
js
// SocialButtons.js
import { useState } from "preact/hooks";

export function SocialButtons() {
  const [count, setCount] = useState(0);
  const add = () => setCount((i) => i + 1);
  const subtract = () => setCount((i) => i - 1);
  return (
    <>
      <div>{count} people liked this post</div>
      <div align="right">
        <button onclick={add}>Like</button>
        <button onclick={subtract}>Unlike</button>
      </div>
    </>
  );
}
SocialButtons
是一个Preact组件,包含自身的HTML和对应的事件处理程序。
该组件会在运行时嵌入到页面中,并在客户端完成水化,确保点击事件能正常工作。
Astro支持HTML、CSS和脚本的清晰分离,并鼓励基于组件的设计。它易于安装,能快速用于构建网站。

Pros and Cons

优缺点

The Islands architecture combines ideas from different rendering techniques such as server-side rendering, static site generation, and partial hydration. Some of the potential benefits of implementing islands are as follows.
  1. Performance: Reduces the amount of JavaScript code shipped to the client. The code sent only consists of the script required for interactive components, which is much less than the script needed to recreate the virtual DOM for the entire page and rehydrate all the elements on the page. The smaller size of JavaScript automatically corresponds to faster page loads and Time to Interactive (TTI).
Comparisons for Astro with documentation websites created for Next.js and Nuxt.js have shown an 83% reduction in JavaScript code. Other users have also reported performance improvements with Astro.
  1. SEO: Since all of the static content is rendered on the server; pages are SEO friendly.
  2. Prioritizes important content: Key content (especially for blogs, news articles, and product pages) is available almost immediately to the user. Secondary functionality for interactivity is usually required after consuming the key content becomes available gradually.
  3. Accessibility: The use of standard static HTML links to access other pages helps to improve the accessibility of the website.
  4. Component-based: The architecture offers all advantages of component-based architecture, such as reusability and maintainability.
Despite the advantages, the concept is still in a nascent stage. The limited support results in some disadvantages.
  1. The only options available to developers to implement Islands are to use one of the few frameworks available or develop the architecture yourself. Migrating existing sites to Astro or Marko would require additional efforts.
  2. Besides Jason's initial post, there is little discussion available on the idea.
  3. New frameworks claim to support the Islands architecture making it difficult to filter the ones which will work for you.
  4. The architecture is not suitable for highly interactive pages like social media apps which would probably require thousands of islands.
The Islands architecture concept is relatively new but likely to gain speed due to its performance advantages. It underscores the use of SSR for rendering static content while supporting interactivity through dynamic components with minimal impact on the page's performance. We hope to see many more players in this space in the future and have a wider choice of implementation options available.
Islands架构结合了服务器端渲染、静态站点生成和部分水化等多种渲染技术的理念,其潜在优势如下:
  1. 性能提升:减少发送给客户端的JavaScript代码量,仅包含交互组件所需的脚本,远少于重建整页虚拟DOM并水化所有元素所需的脚本体积。更小的JavaScript体积自然会带来更快的页面加载速度和更优的交互就绪时间(TTI)。
针对Astro与Next.js、Nuxt.js构建的文档网站对比显示,Astro的JavaScript代码量减少了83%。其他用户也反馈使用Astro获得了性能提升。
  1. SEO友好:由于所有静态内容都在服务器端渲染,页面对搜索引擎更友好。
  2. 优先展示核心内容:博客、新闻和产品页的关键内容几乎能立即呈现给用户,而交互类的次要功能会在用户浏览核心内容后逐步可用。
  3. 可访问性提升:使用标准静态HTML链接访问其他页面,有助于提升网站的可访问性。
  4. 基于组件的优势:该架构具备所有基于组件的架构优势,如组件复用性和可维护性。
尽管有这些优势,但该概念仍处于初期阶段,有限的支持也带来了一些缺点:
  1. 开发者实现Islands架构的选择有限,要么使用现有的少数框架,要么自行开发架构。将现有网站迁移到Astro或Marko需要额外的工作量。
  2. 除了Jason的初始文章外,关于该理念的讨论很少。
  3. 一些新框架声称支持Islands架构,这让开发者难以筛选出适合自己的框架。
  4. 该架构不适用于高度交互的页面(如社交媒体应用),这类页面可能需要数千个交互孤岛,实现起来并不现实。
Islands架构是一个相对较新的概念,但由于其性能优势,它很可能会快速发展。它强调使用SSR渲染静态内容,同时通过动态组件支持交互性,且对页面性能的影响极小。我们希望未来该领域能出现更多参与者,为开发者提供更丰富的实现选择。

Further reading

拓展阅读

Source

来源