Astro介绍
Astro介绍
1.2 什么是Astro
Astro是一个现代化的静态站点生成器和前端框架。Astro由原Snowpack团队于21年4月创建,并于22年8月发布了1.0正式版本,当前已经发布到了4.x版本。从创建至今的3年时间里,Astro的Star数已经达到46k。对比创建3年时的Vue Star数是26k、React Star数是 37k。从下图可以看出来Astro Star 增长曲线还是很陡峭的,一直处于火热状态。
图1. Asro Star数变化趋势
1.3 Astro的特点
-
群岛架构:一种基于组件针对内容驱动网站进行优化的 Web 架构。
Astro 开创并推广了一种叫做 “群岛” 的前端架构。群岛架构通过帮助你避免单体 JavaScript 模式并自动从页面中剥离所有非必需的 JavaScript,从而实现了更好的前端性能。开发者在使用 Astro 的同时,仍然可以继续使用他们最喜欢的 UI 组件和框架,并且从中得到受益。
图2. 群岛架构示意图,来源:Jason Miller
-
UI 无关 : 支持 React、Preact、Svelte、Vue、Solid、Lit、HTMX、Web 组件等等。
---
import Header from '../components/Header/index.tsx'
import Footer from '../components/Footer/index.vue'
---
<div>
<Header client:idle />
<Footer client:idle />
</div>
React 文件内容
import React from 'react';
export default function() {
return (
<div>
<p>react header</p>
</div>
)
}
Vue 文件内容
<script setup>
import { ref, onMounted } from 'vue'
const words = ref('vue footer')
onMounted(() => {
console.log(123)
words.value = 'vue footer 2'
})
</script>
<template>
<div class="vue-footer-cont">
<p>{{ words }}</p>
</div>
</template>
SSR模式输出的 html 部分
<astro-island
uid="r30xB"
prefix="r0"
component-url="/_astro/index.db5e9ed3.js"
component-export="default"
renderer-url="/_astro/client.802dacf3.js"
props='{"data-astro-cid-j7pv25f6":[0,true]}'
ssr=""
client="idle"
opts='{"name";"Header", "value":true}'
await-children=""
>
<div>
<p>react header</p>
</div>
<!--astro:end-->
</astro-island>
<astro-island
uid="X0T3U"
component-url="/_astro/index.6bfab11a.js"
component-export="default"
renderer-url="/_astro/client.6f88b9f8.js"
props='{"data-astro-cid-j7pv25f6":[0,true]}'
ssr=""
client="idle"
opts='{"name":"Footer", "value":true}'
await-children=""
>
<div class="vue-footer-cont" data-astro-cid-j7pv25f6="true">
<p>vue footer</p>
</div>
<!--astro;end-->
</astro-island>
component-url:原始组件逻辑代码
renderer-url:组件渲染时需要的代码,如React的jsx-runtime。通过改写,支持.astro组件renderToString。
从输出的 html 部分内容与 React 和 Vue 源码可以简单观察到,Astro 是使用 React 和 Vue 的SSR模式协助渲染输出内容。外边包一层自定义标签,标签属性记录一些岛屿组件状态、渲染和逻辑 js 代码地址等,用来实现传递数据,群岛按需加载,状态标记等功能。
-
服务器优先:将沉重的渲染移出访问者的设备。
在 Astro 中,大部分处理都是在服务器上进行,而非浏览器中。这通常使你的网站或应用在性能羸弱的设备或在较慢的互联网连接上查看时比客户端渲染更快
-
默认无 JS:让客户端更少的执行 JS ,以提升网站速度。
Astro 默认不使用客户端渲染。它们在构建时或使用服务器端渲染(SSR)按需呈现为 HTML,默认情况下不用任何 JavaScript。当需要交互必须写js时,可以利用客户端指令或者inline script。
-
可定制:Tailwind、MDX 和数百个集成可供选择。
Astro官方和社区提供了丰富的可定制的功能,比如多UI框架、多SSR托管平台适配器、Astro db、tailwind、MDX等。只需要运行一行或几行命令,就可以为你完成必要的配置更改。
Web SSR类框架性能对比
指标 |
良好的 |
需要改进的 |
不良 |
LCP(最大内容绘制) |
<=2.5s |
<=4s |
>4s |
FID(首次输入延迟) |
<=100ms |
<=300ms |
>300ms |
CLS(累积布局偏移) |
<=0.1 |
<=0.25 |
>0.25 |
项目实践
在APP内的H5:CSR转向SSR,减少前端的js体积。目前的前端业务,采用React和Vue,大部分都是CSR渲染模式,js体积庞大,性能并不是最优。SSR和SSG能大幅减少体积,提升性能。
SEO页面优化:当前主站SEO页面是基于Vue的SSR+JQuery模式,没有用框架。项目配置较复杂,上手成本较高。可以利用Astro的服务器优先策略,默认支持SSR模式。配置简单,上手成本低。UI无关,可以不用框架,或者少用框架,即可快速搭建页面。
-
活动类型的业务:当前业务中,存在多技术栈的组件,Vue 和 React 组件均有,可以利用 UI 无关的特点,利用已有组件快速搭建活动页面。
3.2 示例项目
3.3 项目示意代码
---
export const prerender = false
import Layout from '../layouts/Layout.astro'
import Page from '../components/BrokerOwnerCheck/posterToC/index'
import { url } from './api'
const data = await fetch(url)
---
<script src="lib-flexible/flexible"></script>
<Layout title="业主品牌馆">
<Page data={data} />
</Layout>
主文件是个 Astro 文件:
prerender 是配置当前页面预渲染状态,因为项目是配置的 hybrid 模式,所prerender=false 才能启动实时渲染(文档地址:https://docs.astro.build/zh-cn/getting-started/);
Layout 是 Astro 组件,用来放置公共 Layout 代码,像页面 head 标签内一些公共内容和公共底部等;
Page 是 React 组件,大部分逻辑都放在 React 组件中;
import styles from './index.module.less';
export default ({ data }) => {
const renderTitleBox = (title) => {
return <div className={styles.titleBox}>
<span className={styles.titleText}>{title}</span>
</div>
};
const renderTextBox = (role, text) => {
return <div className={styles.textBox}>
<div className={styles.textIcon}>A</div>
<div className={styles.text}>
<span style={{ fontWeight: 700, color: '#333' }}>{role}</span>
<span>{text}</span>
</div>
</div>
};
return (
<div className={styles.posterContainer}>
<img className={styles.headPoster} src={data.img1} />
<div className={styles.moduleBox}>
{ renderTitleBox(data.title1) }
{ renderTextBox(data.desc1) }
{ renderTextBox(data.desc2) }
</div>
<div className={styles.moduleBox}>
{ renderTitleBox(data.title1) }
<img className={styles.poster} src={data.img2} />
</div>
</div>
)
};
很标准的React写法,数据从上层传过来,拿到数据进行填充到对应位置。整体写法采用的是以React组件为主,Astro入口文件为辅。从代码层面可以看出来对前端同学开发非常友好,上手几乎零成本。还可以兼容各个UI框架的组件。
3.4 性能对比
在页面资源方面,使用Astro开发,页面 js, css, html 资源约占6.6KB,且没有js渲染。如果使用传统React客户端渲染开发,页面js, css, html 资源约占 150KB,且还需要js渲染。两者资源体积相差20+倍。
3.5 最佳实践
小结:React、 Vue 分别在各自的 useEffect onMounted 方法中和在交互事件绑定的方法中才能使用浏览器API。
总结:区分场景,按场景来使用浏览器或 node 特有API。
目前在我们保障专区、安心租PC/APP的活动邀请、业主认证C端引导页已经完成了项目落地实践。相对于之前的开发模式,页面性能和开发者体验都提升不少。
但实践过程也发现Astro不足之处:Astro静态资源前缀地址只支持一种前缀地址配置。但是我们业务中通常不止一个CDN地址。
在 build.assetsPrefix 选项中:
Pull Request
一些小技巧
API设计 & 开发
// assetsPrefix function
import { defineConfig } from 'astro/config';
export default defineConfig({
build: {
assetsPrefix: (fileType) => {
if (fileType === 'js') {
return 'https://js.example.com/'
} else if (fileType === 'css') {
return 'https://css.example.com/'
}
return ''
}
}
});
展望规划
-
以活动专题页开始试点Astro框架应用 -
搭建标准化开发框架,更多应用场景试点 -
基于Astro搭建一种“高效能服务端渲染平台”,可以快捷地生产高性能页面
本文分享自微信公众号 - 58技术(architects_58)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。