种子轮融资 700 w,Astro 的正式发布给前端界带来了什么?

2022-11-11 16:23:56 浏览数 (1)

就在上周,Astro 团队发布了 1.0 的正式版本。

从年初我就开始关注这个项目了,但当时只是学习了一下仓库的工程化搭建相关的东西 (changesets 自动发包之类),并没有深入了解它本身的功能。借着正式发版的机会,这几天熟悉了一下 Astro 1.0,发现了很多有意思的地方,下文会分别从团队背景框架定位核心优势几个维度给大家展开介绍,最后也会推荐一些学习资料。

团队背景

在正式介绍 Astro 之前,先给大家聊一聊相关的背景。Astro 的作者是 Fred K. Schott,没错,就是那个开发 Snowpack 的老哥,可以说是 Unbundle 构建工具的祖师爷:

但无奈的是 Vite 发展势头实在太猛,而 Snowpack 渐渐日薄西山,他本人也写了文章发出下面的感慨:

文章链接: https://dev.to/fredkschott/5-more-things-i-learned-building-snowpack-to-20-000-stars-5dc9

大意就是 Snowpack 前途渺茫,用户越来越少,感觉要做到头了啦,而 Vite 发展的非常好,那后面开发的 Astro 就基于 Vite 来做吧。现在连 Snowpack 的官网都表示弃坑了,主动给 Vite 引流:

当然,除了 Snowpack,Fred K. Schott 的团队(叫Pika)还做了一件比较知名的产品: Skypack,即 NPM 包的 ESM CDN 服务:

不幸的是,Skypack 也很长时间(一年多)没有维护了,可以看出团队也不再想继续投入这个项目了,个人感觉主要有两个原因:

  • 竞争对手的强大。竞品 esm.sh 一直在持续迭代且已经得到了 Deno 的官方推荐。
  • 方案落地困难。此类 ESM CDN 应用到实际的业务项目中仍然有诸多的现实障碍,如请求数量多、不能 Tree Shaking、不能本地调试等等,要落地是一个比较难的问题,本人在 Bundle-less 的思考和实践分享 一文中也有过专门的总结。

在近些年的时间里,Fred K. Schott 团队一直将重心放在了新项目 Astro 上面,经过 16 个月的打磨, Astro 在全球拥有了 30000 多个用户,被 Google、Netlify 等大公司使用,Github 的 star 已经达到 15k 。

值得一提的是,Fred K. Schott 为了这个项目专门成立了一个创业公司: The Astro Technology Company,并且已经融到了 700 万美刀的种子轮投资,打算一直以开源的方式发展下去。相比于一些知名开源项目的赞助收入,如 Webpack[1] 22 w 刀/年、Babel[2] 30 w 刀/年,Astro 在经济方面有如鱼得水的优势。

框架定位

接下来聊一聊 Astro 框架的定位,是像 Vue、React 这样的底层渲染框架,还是像 Next.js 这种上层的研发框架?

这一点其实挺困扰初学者的,因为 Astro 既自创了类似于.vue.jsx文件的 .astro 语法,又提供了像 Next.js 里面各种运行时的能力,比如约定式路由、构建优化、SSR 等等。

但实际上它给自己的定位非常清晰,即 content-focused 应用开发框架,换句话说,就是重内容、轻交互场景下的上层研发框架,比如大多数电商网站、文档站、博客站、证券网站等等。

你可以将 Astro 理解为一个垂直场景下的Next.js,但它可以在它适用的领域里面可以胜过其它所有竞品(如Next.jsRemixVuepress 等),这是它能够做起来的重要原因。接下来,我们就来看看 Astro 的优势在于哪些地方。

核心优势

Astro 的主要优势包括如下几点:

  • Islands 架构,解决传统 SSR/SSG 框架的全量 hydration 问题,做到尽可能少的 Client 端 JS 的开销,甚至是 0 JS。
  • 学习成本低。.astro 语法和传统的 .jsx.vue 非常相似,对于新手前端来说也比较容易掌握。
  • 使用灵活。对于页面的开发,你既可以使用官方的.astro 语法,也同样可以使用 .md.vue.jsx 语法,也就是说,你可以自由选择其它前端框架的语法来开发,甚至可以在一个项目中同时写 Vue 组件和 React 组件!
  • 构建迅速。底层构建体系基于 Vite 以及 Esbuild 实现,项目启动速度非常快。

Islands 架构

在如上的几个优点中,我们来重点说一说 Astro 的 Islands 架构,因为这是它高性能最主要的原因。

Islands 架构模型早在 2019 年就被提出来了,并在 2011 年被 Preact 作者Json MillerIslnads Architecture[3] 一文中得到推广。这个模型主要用于 SSR (也包括 SSG) 应用,我们知道,在传统的 SSR 应用中,服务端会给浏览器响应完整的 HTML 内容,并在 HTML 中注入一段完整的 JS 脚本用于完成事件的绑定,也就是完成 hydration (注水) 的过程。当注水的过程完成之后,页面也才能真正地能够进行交互。

那么当应用的体积逐渐增大时,需要在客户端执行的 JS 脚本也会越来越多,这也意味着 TTI(可交互时间) 指标越来越高:

为了解决这个问题,Islands 架构将页面拆分为各自独立的组件,包含静态组件可交互组件,如下图的例子所示:

可以清楚的看到,一个页面中只有部分的组件交互,那么对于这些可交互的组件,我们可以并行地执行 hydration 过程,因为组件之间是互相独立的。

而对于静态组件,即不可交互的组件,我们可以让其不参与 hydration 过程,直接复用服务端下发的 HTML 内容。

可交互的组件就犹如整个页面中的孤岛(Island),因此这种模式叫做 Islands 架构:

相比于传统 SSR 中的全量 hydration,Islands 模式可以实现局部(partial) hydration,从而优化 JS 的体积,减少网络传输的成本和 JS 运行时的开销。

在 Astro 中,默认所有的组件都是静态组件,比如:

代码语言:javascript复制
// index.astro
import MyReactComponent from '../components/MyReactComponent.jsx';
---
<MyReactComponent />

值得注意的是,这种写法不会在浏览器添加任何的 JS 代码。但有时我们需要在组件中绑定一些交互事件,那么这时就需要激活孤岛组件了,在 Astro 如何来激活呢?其实很简单,在使用组件时加上client:load指令即可:

代码语言:javascript复制
// index.astro
---
import MyReactComponent from '../components/MyReactComponent.jsx';
---
<MyReactComponent client:load />

如此一来,Astro 会给浏览器传输一部分 JS 代码供这个组件完成 hydration,以便后续的交互。

对比 Next.js 和 Remix

读到这里,你可能会说了,相比于其它的业界方案,Astro 到底优势在哪里呢?我们不妨来盘点一下。

首先是大名鼎鼎的 Next.js,我们知道 Next.js 是一个非常经典的 React SSR 框架,也是使用传统的 SSR/SSG 技术,可以适用于几乎所有的 Web 开发场景。而 Astro 在其适用的content-focused场景下,性能会明显高于 Next.js,以下是两个真实的迁移案例:

可以看到,Astro 相比 Next.js 可以大幅度减少 JS 代码的体积(90% 以上),同时页面的运行时性能也提升了 30% 以上。除此之外,Astro 不仅支持使用 React 框架,而且支持 Vue、Solid 等在内的各种前端框架,灵活性更高。

其次是最近比较火的新秀框架 Remix,它基于 react-router 管理组件,通过 loader 和 action 的概念尽可能将逻辑代码放到服务端的 bundle,从而减少客户端 JS 的代码体积,同样是崇尚 0 JS 的理念,Remix 却仍然需要全量 hydration,无法完成 partial hydration。此外,Astro 还有两大优势:

  • 除了 React,也支持其它的众多前端框架;
  • 同时支持 SSR 和 SSG,而 Remix 不支持 SSG。

对比 React 18 的 Selection Hydration 特性

React 18 提供了 renderToPipeableStream API,真正实现了 SSR 场景下的 Selection Hydration,主要有如下的几个特点:

  • 在完整的 HTML 渲染之前就可以进行组件的 hydrate,而不用等待 HTML 的内容发送完毕
  • hydration 可中断。比如页面中有两个组件: Sidebar 和 Comment,当这个部分的 HTML 发送至浏览器时,React 打算开始对 Sidebar 组件进行 hydrate:

如果用户在这个过程中点击了 Comment 组件,那么 React 会中断当前对于 SideBar 组件的 hydrate,从而去执行 Comment 组件的 hydrate:

详情可见 React 18 SSR Architecture: https://github.com/reactwg/react-18/discussions/37

那么 Astro 中的 Islands 架构,即 Partial Hydration,和 React 的 Selection Hydration 到底是不是一个东西呢?

答案是否定的。两者存在着非常大的区别:

  • 从渲染框架上来看, Selection Hydration 依附于具体框架的实现,而 Partial Hydration 可以做到框架无关,即使是 Vue、Solid 的项目也可以做到 Partial Hydration
  • 从客户端执行的 JS 总量来看, Partial Hydration 可以做到加载部分组件的 JS 代码,而 Selection Hydration 仍然需要加载和执行全量的 JS 代码。
  • 从服务端和客户端的交互来看, Selection Hydration 严重依赖于流式(Streaming)渲染,服务端需要加上 transfer-encoding: chunked 的响应头,而 Partial Hydration 没有这个限制。

因此,虽然两者都是在 Hydration 上做文章,但其实是两种完全不同的方案,而且 Partial Hydration 更加通用,限制更少,执行的 JS 更少。

小结

以上就是对 Astro 的介绍和分析,后面有机会给大家剖析一下内部的源码实现。文中如有不妥的地方,欢迎大家评论和指正。最后给大家推荐一些 Astro 的学习资料,方便大家读完文章进一步了解:

  • Astro 官方文档: https://astro.build/
  • Astro 实战系列教程: https://aalam.in/blog/astro-get-up-and-running

参考资料

[1]

Webpack: https://opencollective.com/webpack

[2]

Babel: https://opencollective.com/babel

[3]

Islnads Architecture: https://jasonformat.com/islands-architecture/

0 人点赞