原文地址:jasonformat.com/islands-arc…
原文作者:Jason Miller
我一直努力想要在网上找到有关这个的引用,但是今年在描述这里概述的方法时,我发现这个名字被多次提及。据我所知,“组件岛屿”模式是在 2019 年的一次会议上,由 Etsy 的前端架构师 Katie Sylor-Miller 提出的。
“岛屿”架构的总体思路看似十分简单:在服务端渲染 HTML,然后在高度动态的区域注入占位符或者插槽。这些占位符或者插槽都包含其相对应部件输出的服务端渲染 HTML。它们表示可以在客户端“注水”成小型独立部件的区域,重用它们服务端渲染的初始 HTML。
你可以把它想象成一个包含了多个独立嵌入式应用的静态 HTML 文档:
咋一看,好像和“微前端”很相似。两者都提出了将应用拆分成多个独立单元的想法,但是“微前端”通常并不意味着这些单元的组成是使用 HTML 实现的。
和“岛屿”方法相近的模拟是渐进式增强,本质上是在添加 SSR 水合和一个一致的隐喻,用于为页面上的某个区域添加交互性。传统的渐进式增强中,通过 <script> 在页面上查找图片轮播,并实例化一个 jQuery 插件。而现在图片轮播会在服务端渲染好,然后触发一个专用的 <script> 用来加载图片轮播实现并就地升级为可交互的。
为什么这很重要?
事实证明,和典型的单页面应用结构相比,这里描述的方法有许多好处。
免费的“渐进式水合”
我曾经吹捧过 React、Angular、Preact 和 Vue 等框架的 渐进式水合 技术的性能优势。通过这个架构,随着时间的推移,在页面上的独立部件会被加载和初始化。这可以借助 requestIdleCallback 使用简单的调度方法来完成,或者是考虑其他因素,例如视口可见性,交互可能性,产品价值等。
和渐进式水合类似,使用岛屿架构来渲染页面会导致页面上较复杂的动态部分不仅逐步初始化,而且单独初始化。这意味着页面上的各个区域变得可交互,而无需先加载页面上的其他内容。
不像渐进式水合,岛屿架构不需要自上而下的渲染。这是一个明显的好处,因为这样就不需要外部“根”组件必须要在其他子组件前被初始化。页面上每个部分都是独立的单元,并且一个单元的性能问题不会影响到其他单元。
无需权衡 SEO 和用户体验问题
为了 SEO,在单页应用中使用 SSR 是十分必要的。但是,SSR 对用户体验来说是有负面影响的——用户只能一边盯着这假的页面,一边等待页面真正的功能到达。
许多应用还没有意识到正在遭受这无声的 SSR 性能陷阱。在虚拟 DOM 中,很容易(也很普遍的)意外的构造一种情况,首次渲染会破坏服务端渲染好的 HTML DOM 结构,然后重头的去构建一次(这个过程通常是同步的)。这是一些常见误解的结果,这些误解可能来源于文档中给出的理想化水合观点,而忽略了一些棘手的警告。
即使 SSR 水合按设计运行的情况下,现状和预期还是有差距。页面加载期间执行的 JS 工作量仍比可能被认为是“高效的”多很多数量级。
在岛屿模式中,服务端渲染不是旨在提升 SEO 或者用户体验的附加优化,相反,它是页面如何交付给浏览器的基础部分。响应导航返回的 HTML 是包含了用户请求的内容的有意义且可立即渲染的表示。
部分 HTML 可能会缺少客户端的可交互性,但是页面中应该至少包含最基本的内容。例如,在一篇新闻的页面中应该包含文章的主体,一个产品的页面中应该包含这个产品的描述。
其他内容都是次要的信息,将其包含在 HTML 中成为产品决策。这些信息对于访问页面的用户来说有多重要?这些小的部件对商业模式来说有多重要?直接关系到收入的“立即购买”按钮应当比与信息收集相关的网站反馈调查按钮优先级更高。
更好的可访问性和可发现性
使用标准 HTML 链接用作导航的网站会更易于无障碍访问技术和网络爬虫。无论链接或表单是否被 JS 拦截并重新路由到客户端逻辑,这都是正确的。因为基本假设仍然是正确:点击链接会跳转到给定的页面。
有趣的是,想下你曾经发送了一个你正在阅读的链接给对方,但却发现链接里并没有包含任何有用信息的次数:
构建基于页面的应用可能并不能完全的阻止这类奇怪的体验,只会让这样的决定做起来更加的直接。这使得默认的结果就是可访问的结果。
归根结底,发布一个需要更少代码来做某事的架构会使得未来的你(或你的同事)对此感到感谢的长期利益类型。有可能采用这样的模式需要更多的前期设计思维。目前很少有开箱即用的选项可用于将应用拆解成独立的小部件。谁知道呢,说不定我们可以解决这个问题。