Astro Island架构实现原理
什么是Islands架构
Islands架构类似于微前端架构,但Islands主要是为了优化页面性能和用户体验,而微前端是为了解耦不同业务模块。

为什么要使用Islands
- 可以优先展示或者水合重要内容,比如电商商品详情页可以优先展示和水合商品主图、商品描述、购买按钮。
- 浏览器加载的js变少,能够提升TTI。
使用
Astro有很多指令表示一个组件是在服务端渲染还是客户端渲染、渲染时机。
directives | description | priority |
---|---|---|
client:load | 页面加载后立即水合 | high |
client:idle | 在requestIdleCallback中进行水合 | medium |
timeout | 最大等待时间后水合 | low |
client:visible | 进入视口后水合 | low |
client:media | 媒体查询后水合 | low |
client:only | 不进行服务端渲染 | low |
server:defer | 按需渲染 |
可以使用这个astro的模版快速搭建一个demo
使用client:load标记组件为Island组件,并且高优先级水合
1 | <BuyNowButton client:load onClick={handleClick}>点击购买</BuyNowButton> |
原理
通过Astro的compiler将astro代码编译成如下
1 | import { render as $$render, createAstro as $$createAstro, createComponent as $$createComponent, renderComponent as $$renderComponent } from "astro/compiler-runtime"; |
在renderComponent中会将标记为client:load的组件渲染成
1 | <astro-island uid="Z1xkbrp" component-url="/src/components/BuyNowButton.tsx" component-export="default" renderer-url="/node_modules/.vite/deps/@astrojs_preact_client-dev__js.js?v=ec7158f6" props="{"data-astro-cid-sckkx6r4":[0,true]}" client="load" before-hydration-url="/@id/astro:scripts/before-hydration.js" opts="{"name":"BuyNowButton","value":true}" server-render-time="1.461416999999983" await-children="" client-render-time="1"><aside hidden="" class="_container_jwp5b_1"><p>Your cart is empty!</p></aside></astro-island> |
服务端返回的就是上面的html,并且会返回astro-island.js文件,该文件注册astro-island自定义元素,
该元素在connectCallback后获取astro dom上的component-url、renderer-url(hydrator水合器)和props。最后await hydrator(<Component {…props}/>)渲染组件
参考
https://jasonformat.com/islands-architecture/
https://docs.astro.build/zh-cn/concepts/why-astro/#_top