跳到正文
纸墨小站
技术约 2 分钟

Astro Islands 的一个取舍记录

站点里到底哪些东西值得做成 React 岛,哪些用原生脚本更划算。

  • Astro
  • React
  • 性能

搭站时最容易犯的错,是把“能做成组件”当成“应该做成组件”。Astro 的岛屿架构把这件事的成本摆到了明面上,值得记一笔。

先分清两类交互

我把页面上所有要动的东西列出来,然后按一个问题归类:它需要跨渲染持有状态吗?

  • 需要——搜索框、筛选器、预览弹层。这些有 useState,涉及多个元素联动。
  • 不需要——淡入、平滑滚动、悬停浮起。这些只是“到了某个时刻,加个 class”。

第一类做成 React 岛。第二类如果也做成岛,就白白拖进一份运行时。

第二类的做法

淡入用 IntersectionObserver 加一个 class 就够了:

const io = new IntersectionObserver(
  (entries) => {
    for (const e of entries) {
      if (e.isIntersecting) {
        e.target.classList.add("is-in");
        io.unobserve(e.target);
      }
    }
  },
  { rootMargin: "0px 0px -12% 0px" },
);

动画本身写在 CSS 里,JS 只负责在正确的时刻把开关拨过去。这样做还有个副作用是好的:晕动效的用户只要在 CSS 里把 transition-duration 压到接近零,整个降级就完成了,不用改一行脚本。

平滑滚动同理,交给 Lenis 一个独立的 vanilla 入口,不进 React 树。

值得吗

值得。最后只有两个岛:日志页的筛选器、文件页的搜索和预览。其余全是静态 HTML。首屏要下载的 JS 因此少了一个数量级,而交互该有的地方一点没少。

代价是写法上多一层判断——每次想 import 一个 React 组件之前,得先问一遍那个问题。