4df8dc6f87
新建 web/website/(Astro 零 SSR): - 组件迁移:交互块保留 .jsx 经 @astrojs/react(Header/AnnouncementBar/SignupForm/PricingPlans),纯展示块转 .astro 去运行时 JS;像素以原型为基准。 - 令牌同源:build-tokens.mjs 从 design/colors_and_type.css 生成 tokens.gen.css,仅剔除第三方 Google Fonts @import,数值不改。 - 字体自托管:@fontsource(Sora/Manrope/Noto Sans SC/JetBrains Mono),无第三方 CDN。 - 图标:Lucide 构建期内联 SVG(替代 unpkg CDN),零运行时、零 CDN。 - i18n:/(zh)与 /en/(en)双路由单显,语言切换组件;文案沿用 ui_kits 脱敏文案。 - 安全:public/_headers 严格 CSP(全 self + 自托管资源 + 内联片段 sha256,无 unsafe-inline)+ HSTS;无支付表单。 - CI:.gitea/workflows/website.yml 构建(红线扫描+lint+CSP 哈希)→ 同时发布 Cloudflare Pages 主站与镜像。 - 灾备:README 写明干净环境 npm ci && npm run build 可直接部署到任意静态托管;dist 指纹确定性,主站镜像一致。 测试:npm run lint(0 error)/ npm test(build+CSP 哈希注入+红线扫描 0 命中)/ 两次干净构建 dist 指纹一致。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
29 lines
1.1 KiB
JavaScript
29 lines
1.1 KiB
JavaScript
// @ts-check
|
||
import { defineConfig } from 'astro/config';
|
||
import react from '@astrojs/react';
|
||
|
||
// 纯静态站点 (SSG),零 SSR。
|
||
// `site` 仅用于生成绝对 URL(sitemap / canonical),镜像部署时可被任意域名覆盖,
|
||
// 不影响「整站可秒级复制到任意备用域名」:产物为纯相对路径静态文件。
|
||
// 主站 canonical 域名。镜像构建务必用「同一个」SITE_URL,使 canonical 始终指向主站
|
||
// (避免镜像与主站 SEO 竞争),且主站/镜像产物 hash 完全一致(验收:内容一致性)。
|
||
const SITE_URL = process.env.SITE_URL || 'https://pangolin.example';
|
||
|
||
export default defineConfig({
|
||
site: SITE_URL,
|
||
output: 'static',
|
||
trailingSlash: 'always',
|
||
build: {
|
||
// 内联样式/脚本会破坏严格 CSP(script-src/style-src 'self'),全部产出为独立资源文件。
|
||
inlineStylesheets: 'never',
|
||
assets: '_astro',
|
||
},
|
||
integrations: [react()],
|
||
vite: {
|
||
build: {
|
||
// 关闭 JS 内联,保证 script-src 'self' 严格 CSP 下可运行。
|
||
assetsInlineLimit: 0,
|
||
},
|
||
},
|
||
});
|