Skip to content

Presto 网站架构

Presto 官网(Presto-homepage)是基于 Astro 5 的纯静态站点,部署在 Vercel 平台, 通过 CI/CD 与主仓库(Presto)联动,实现版本号同步和 Showcase 静态文件自动更新。 截至 2026 年 3 月。


系统全景


技术栈总览

层级技术版本来源用途
框架Astro^5.17.1package.json静态站点生成器
语言TypeScript^5.9.3package.json类型安全
前端框架架构决策纯 Astro 组件 + vanilla JS
CSS自定义 CSSglobal.cssCSS 变量 + 暗色模式
字体系统字体栈global.css无外部字体依赖
部署Vercelvercel.json托管 + CDN
HTML 压缩compressHTMLtrueastro.config.mjs减小体积
包管理器npmpackage-lock.json依赖管理

系统字体栈

css
--font-sans:
  system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Microsoft YaHei", "Noto Sans SC", Roboto,
  Oxygen, Ubuntu, Cantarell, sans-serif;
--font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;

页面路由和组件职责

页面路由结构

路由文件说明
/src/pages/index.astro首页,包含所有主要区块
/developerssrc/pages/developers/index.astro开发者页面,43KB 内容丰富的技术文档
/templatessrc/pages/templates/index.astro模板商店,iframe 嵌入 Presto 的商店 UI
/showcase/*public/showcase/Presto 构建的预渲染静态文件

组件架构

text
src/
├── components/
│   ├── Header.astro     # 导航栏(36KB)
│   ├── Hero.astro       # 首屏(版本号、下载按钮)
│   ├── Features.astro   # 功能特性展示
│   ├── Showcase.astro   # 实时 UI 展示(iframe)
│   ├── Download.astro   # 下载区域(多平台检测)
│   └── Footer.astro     # 页脚
├── layouts/
│   └── Layout.astro     # 全局 HTML 壳(i18n 检测、滚动动画)
└── styles/
    └── global.css       # 全局样式(CSS 变量、响应式断点)

组件职责

组件文件大小职责
Header36KB导航栏、双语切换、响应式菜单、滚动时样式变化
Hero7.5KB首屏标题、版本号(自动同步)、下载按钮、背景渐变
Features6KB功能特性网格布局,支持图标 + 双语描述
Showcase17KB产品展示轮播,5 个 iframe 嵌入 Presto 真实 UI 组件
Download16KB下载区域、多平台检测(macOS/Windows/Linux)、版本号(自动同步)
Footer2KB页脚链接、版权信息

关键架构决策

1. Showcase iframe 嵌入

What: 首页的 Showcase 区域通过 iframe 嵌入 Presto 应用的真实 UI 组件(非截图)。

Why:

  • 真实交互体验:用户可以实际操作 Presto 界面,而非静态图片
  • 自动更新:Presto 构建新的 showcase 静态文件后,通过 CI 自动同步到官网
  • 减少维护成本:无需手动截屏和替换图片
  • 性能优化:loading="lazy" + sandbox="allow-scripts allow-same-origin" 安全沙箱

实现细节(src/components/Showcase.astro):

astro
<iframe
  src={s.iframeSrc}
  loading="lazy"
  sandbox="allow-scripts allow-same-origin"
  class="showcase-iframe"
  title={s.en}
></iframe>

5 个 showcase 场景:

  • /showcase/editor-gongwen — 编辑器 · 公文
  • /showcase/editor-jiaoan — 编辑器 · 教案
  • /showcase/batch — 批量转换
  • /showcase/templates — 模板管理
  • /showcase/drop — 拖入文件

2. 模板商店 iframe 嵌入

What: /templates 页面通过 iframe 嵌入 Presto 的 /showcase/store-templates,商店 UI 由 Presto 仓库维护。

Why:

  • 职责分离:模板商店的业务逻辑属于主应用,官网只负责展示
  • 一致性:模板商店 UI 与 Presto 桌面端保持一致
  • 独立更新:商店 UI 更新无需修改官网代码
  • 减少重复:避免在两个仓库维护相同的商店 UI

3. 版本号自动同步

What: sync-release.yml 在 Presto 发布新版本时自动更新 Hero.astro 和 Download.astro 中的版本号。

Why:

  • 避免手动错误:版本号不一致会导致用户下载错误版本
  • 减少维护成本:发布流程自动化,无需手动修改官网代码
  • 及时性:Presto 发布后立即触发版本号更新

实现机制:

  1. Presto 仓库发布新版本 → repository_dispatch 事件 release-published
  2. sync-release.yml 下载 release 资产,创建 homepage release
  3. 使用 sed 更新版本号:
bash
# Download.astro
sed -i "s/^const version = '.*';$/const version = '${VER}';/" src/components/Download.astro

# Hero.astro
sed -i "s/最新版本 v[0-9][0-9.]*/最新版本 v${VER}/" src/components/Hero.astro
sed -i "s/Latest v[0-9][0-9.]*/Latest v${VER}/" src/components/Hero.astro
  1. 自动 commit 并 push,触发 Vercel 自动部署

4. 双语系统

What: 所有文本用 <span class="zh"> + <span class="en"> 包裹,通过 CSS 切换。

Why:

  • 简单高效:无需 i18n 框架,纯 CSS 实现
  • 避免 FOUC(Flash of Unstyled Content):Layout.astro 中通过 inline script 在渲染前检测语言
  • 性能优化:无需额外的 JavaScript 切换逻辑
  • 易于维护:所有文本集中在组件内,无需外部翻译文件

实现机制(src/layouts/Layout.astro):

html
<script is:inline>
  (function () {
    var stored = localStorage.getItem("presto-lang");
    var lang = stored || (navigator.language.startsWith("zh") ? "zh" : "en");
    document.documentElement.lang = lang;
  })();
</script>

CSS 切换逻辑(src/styles/global.css):

css
html[lang="en"] .zh {
  display: none;
}
html[lang="zh"] .en {
  display: none;
}

5. 暗色模式

What: 纯 CSS @media (prefers-color-scheme: dark) 自动切换,无 JS 切换按钮。

Why:

  • 跟随系统:用户的系统设置自动应用,无需手动切换
  • 性能优化:无 JavaScript 运行时开销
  • 简化代码:无需维护主题状态和切换逻辑
  • CSS 变量:所有颜色通过 CSS 变量定义,切换流畅

实现机制(src/styles/global.css):

css
:root {
  --color-bg: #ffffff;
  --color-text: #0f172a;
  --color-accent: #2563eb;
}

@media (prefers-color-scheme: dark) {
  :root {
    --color-bg: #09090b;
    --color-text: #fafafa;
    --color-accent: #60a5fa;
  }
}

6. 零框架策略

What: 不使用 React/Vue/Svelte 等前端框架,纯 Astro 组件 + inline vanilla JS。

Why:

  • 性能优先:纯静态 HTML,无 hydration 开销
  • 简化构建:无需前端框架的复杂构建配置
  • 减少 bundle 大小:无需加载框架运行时
  • SEO 友好:所有内容在构建时渲染为静态 HTML
  • 维护成本低:无框架版本升级和依赖兼容问题

仅有的 JavaScript:

  • i18n 语言检测(inline script,15 行)
  • 滚动动画 IntersectionObserver(inline script,30 行)
  • Showcase 轮播逻辑(inline script,在 Showcase.astro 内)

部署流程和 CI 联动

Vercel 自动部署

Presto-homepage 连接到 Vercel 平台,每次 main 分支有新的 commit 时自动触发构建和部署。

配置(vercel.json):

  • cleanUrls: true — 无 .html 后缀
  • 安全头:
    • X-Content-Type-Options: nosniff
    • X-Frame-Options: SAMEORIGIN
    • Referrer-Policy: strict-origin-when-cross-origin
    • Permissions-Policy: camera=(), microphone=(), geolocation=()
    • Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline';style-src 'self' 'unsafe-inline'; img-src 'self' data:;frame-src 'self'; connect-src 'self'; font-src 'self'

CI 工作流联动

sync-release.yml

触发条件:

  • Presto 仓库发布新版本(repository_dispatch: release-published
  • 手动触发(workflow_dispatch,需指定 tag)

步骤:

  1. 解析 tag(从 client_payloadinputs
  2. 从 Presto 仓库下载 release 资产(需要 PRESTO_PAT
  3. 创建 homepage release(同名 tag,复制 release notes)
  4. 更新版本号(Download.astro + Hero.astro)
  5. 自动 commit 并 push

sync-showcase.yml

触发条件:

  • Presto 仓库构建 showcase 完成(repository_dispatch: showcase-updated
  • 手动触发(workflow_dispatch

步骤:

  1. 清理旧文件(rm -rf public/_app public/showcase
  2. 从 Presto 仓库下载 artifact(showcase-static,需要 PRESTO_PAT
  3. 复制到 public/ 目录
  4. 自动 commit 并 push

响应式设计

断点列表

断点说明
1024px平板横屏
900px平板竖屏
768px大手机 / 小平板
640px手机横屏
560px大手机竖屏
480px小手机竖屏

IntersectionObserver 滚动动画

实现(src/layouts/Layout.astro):

javascript
document.addEventListener("DOMContentLoaded", function () {
  var els = document.querySelectorAll(".animate-on-scroll");
  if (!("IntersectionObserver" in window)) {
    // 降级处理:直接显示所有元素
    els.forEach(function (el) {
      el.classList.add("is-visible");
    });
    return;
  }
  var observer = new IntersectionObserver(
    function (entries) {
      entries.forEach(function (entry) {
        if (entry.isIntersecting) {
          entry.target.classList.add("is-visible");
          observer.unobserve(entry.target); // 只触发一次
        }
      });
    },
    { threshold: 0.05, rootMargin: "0px 0px -20px 0px" },
  );
  els.forEach(function (el) {
    observer.observe(el);
  });
});

CSS 动画(src/styles/global.css):

css
.animate-on-scroll {
  opacity: 0;
  transform: translateY(16px);
  transition:
    opacity 0.6s ease,
    transform 0.6s ease;
}

.animate-on-scroll.is-visible {
  opacity: 1;
  transform: translateY(0);
}

Showcase iframe 缩放

Showcase iframe 固定宽度 1200px,通过 JavaScript 动态缩放以适应容器宽度:

javascript
function scaleIframes() {
  var containers = document.querySelectorAll(".slide-image");
  for (var i = 0; i < containers.length; i++) {
    var iframe = containers[i].querySelector(".showcase-iframe");
    if (!iframe) continue;
    var cw = containers[i].offsetWidth;
    var scale = cw / 1200;
    iframe.style.transform = "scale(" + scale + ")";
    containers[i].style.height = Math.round(800 * scale) + "px";
  }
}

性能优化

构建时优化

  • compressHTML: true — Astro 自动压缩 HTML
  • 系统字体栈 — 无外部字体加载,避免 FOUT
  • 纯静态站点 — 无服务器端渲染,CDN 直接缓存

运行时优化

  • lazy loading iframe — Showcase iframe 延迟加载
  • IntersectionObserver — 只在可见时触发动画
  • CSS 变量 — 暗色模式切换无重绘开销
  • will-change: transform — 轮播动画 GPU 加速

Vercel 优化

  • 全球 CDN — 静态资源就近分发
  • HTTP/2 — 多路复用,减少连接开销
  • 自动压缩 — Gzip/Brotli 压缩

开发命令

bash
# 本地开发服务器(localhost:4321)
npm run dev

# 构建静态站点到 dist/
npm run build

# 预览构建产物
npm run preview

相关文档


Presto — Markdown to PDF