Astro 最迷人的地方在于:默认零 JavaScript,但在需要交互的地方又能精准注水。配合视图过渡(View Transitions),页面切换可以达到接近 SPA 的丝滑感。

岛屿架构

传统的 MPA 每次导航都要重新解析全部资源;Astro 的岛屿(Islands)让交互组件独立水合:

---
// 一个交互组件只在进入视口时才加载 JS
import SearchBox from '../components/SearchBox.astro';
---
<SearchBox client:visible />

零依赖的客户端脚本

Astro 的 <script> 标签会被打包、去重并按需加载,用原生 API 就能实现大部分交互:

// 目录高亮:IntersectionObserver 监听标题可见性
const observer = new IntersectionObserver((entries) => {
  for (const entry of entries) {
    if (entry.isIntersecting) activate(entry.target.id);
  }
}, { rootMargin: '-15% 0px -70% 0px' });

document.querySelectorAll('.md-body h2[id]').forEach((h) => observer.observe(h));

实测数据

  • [x] 首页 LCP 稳定在 0.4s 以内
  • [x] 全站 JS 体积 < 30KB gzip
  • [ ] 把 TOC 滚动监听换成 CSS scroll driven animations
  • [ ] 试试浏览器原生的 View Transition API

性能优化的最高境界不是优化,而是从一开始就不发送多余的代码。

—— 某位前端工程师的碎碎念

博客这种小服务,最怕的不是流量大,而是搬家与数据丢失。用 Docker Compose 把 Typecho 和数据库固定下来,再配一个定时备份,一劳永逸。

基础编排

services:
  typecho:
    image: joyqi/typecho:nightly-php8.3
    restart: always
    ports:
      - "8080:80"
    volumes:
      - ./usr:/app/usr
    depends_on:
      - db
  db:
    image: mariadb:11
    restart: always
    environment:
      MARIADB_ROOT_PASSWORD: change-me
      MARIADB_DATABASE: typecho
    volumes:
      - ./db:/var/lib/mysql

定时备份

数据库用 mysqldump,附件目录直接打 tar 包:

#!/usr/bin/env bash
set -euo pipefail
STAMP=$(date +%F-%H%M)
DEST=/backups/${STAMP}
mkdir -p "${DEST}"

docker compose exec -T db sh -c   'exec mariadb-dump -uroot -p"${MARIADB_ROOT_PASSWORD}" typecho'   > "${DEST}/typecho.sql"

tar -czf "${DEST}/usr.tgz" ./usr

# 只保留最近 14 份
ls -1dt /backups/*/ | tail -n +15 | xargs rm -rf

crontab 里加一行,每天凌晨 3 点执行:

0 3 * * * cd /srv/blog && ./backup.sh >> /var/log/blog-backup.log 2>&1

常见问题

现象原因处理
数据库连接失败容器未就绪加 healthcheck 与 depends_on 条件
上传图片 403目录权限chown www-data usr/uploads
备份包为空dump 密码未转义用环境变量传递密码

坚持「配置即文件」的原则,搬家时 git clone + docker compose up -d 两步就能恢复。

这不是 Markdown

这篇文章的正文是原生 HTML(Typecho 富文本编辑器的产物),用于验证前端渲染器对非 Markdown 内容的透传与净化能力。

  • HTML 列表项一
  • 列表项二,包含一段 inline code
  • 列表项三,一个外链
元素预期表现
标题左侧青色竖线
代码行内代码高亮
表格圆角边框 + 斑马纹

原生 HTML 与 Markdown 渲染结果应保持一致的视觉风格。

—— 如果这段文字前出现了斜体“来自脚本”字样,说明净化逻辑失效:来自脚本

Tailwind 4 把配置从 tailwind.config.js 搬进了 CSS 本身,@theme 指令让设计令牌真正成为 CSS 变量。

主题即变量

@import "tailwindcss";

@theme {
  --color-neon-400: #22d3ee;
  --font-mono: ui-monospace, "SF Mono", Menlo, monospace;
  --shadow-glow: 0 8px 40px -8px rgb(34 211 238 / 0.35);
}

声明后即可直接使用 text-neon-400、shadow-glow 这些工具类,运行时还能用 var(--color-neon-400) 引用。

与 Astro 的组合

// astro.config.mjs
import tailwindcss from '@tailwindcss/vite';

export default {
  vite: { plugins: [tailwindcss()] },
};

不需要 PostCSS 配置,不需要 content 扫描白名单,Vite 插件搞定一切。

一些值得注意的迁移点

  • @apply 依然可用,但自定义类要先 @utility 注册
  • 默认边框颜色从 gray-200 变为 currentColor
  • 渐变工具类从 bg-gradient-to-r 改名为 bg-linear-to-r

整体感受:4.0 是一次「减法」升级,心智负担反而更小了。