openElement 的 island 是 DSD HTML 之后的 Custom Element upgrade。它不是整页 hydration,也不是把应用状态完整恢复到客户端。
浏览器解析 HTML 时,Declarative Shadow DOM 已经把组件内容和样式放进 shadow root。客户端 entry 加载后调用 customElements.define(),浏览器把已有元素升级为真正的 Custom Element。这个过程更准确地叫 Island Upgrade。
| 场景 | 推荐方式 |
|---|---|
| 可读内容、导航、布局 | HTML + DSD |
| Hover、focus、响应式状态、简单展开 | CSS 和原生 HTML 元素 |
| 剪贴板、localStorage、IntersectionObserver | 使用浏览器 API 的小型 island |
| 本地状态、事件编排、API 轮询、乐观 UI | Island Upgrade |
本地 island 放在 app/islands。构建器会扫描它,生成 client entry,并在静态 HTML 中注入 entry script。
// app/islands/my-counter.ts
import { DsdElement } from '@openelement/core';
import { StyleSheet } from '@openelement/style-sheet';
import { signal } from '@openelement/signals';
export const tagName = 'my-counter';
const sheet = new StyleSheet();
sheet.replaceSync(':host { display: inline-flex; gap: 0.5rem; align-items: center; }');
export default class MyCounter extends DsdElement {
count = signal(0);
static override styles = sheet;
override render() {
return html\`
<button @click={() => this.count.value--}>-</button>
<span>{this.count}</span>
<button @click={() => this.count.value++}>+</button>
\`;
}
}
if (!customElements.get(tagName)) customElements.define(tagName, MyCounter);可复用包可以导出 island metadata,openElement 在构建时读取这些信息,用于 SSR 注册和 client entry 生成。
当前实现仍以全局 island entry 为主。下一阶段需要把 strategy 从 metadata 真正带进 client build,并引入页面级 island manifest,让每个页面只加载实际出现的 island。