部署流程
本站是纯静态站点,没有服务端代码。但有一条硬性要求:必须能设置自定义响应头。
前置要求
- Node.js 20+
- 能设置响应头的静态托管 —— Cloudflare Pages、Netlify、自建 nginx 都可以。 GitHub Pages 不行(它不支持自定义响应头,跨域隔离开不起来)。
本地构建
npm install
npm run build # 准备 ORT 资源 → 类型检查 → 打包
npm run preview # 本地起服务,带上 COOP/COEP 头
构建产物结构:
dist/
├── index.html 中文首页(压缩功能)
├── upscale/index.html 中文放大页
├── cutout/index.html 中文抠图页
├── blog/ 中文博客(手写静态页)
├── docs/ 本套文档
├── en/ zh-CN/ 英文 / 中文旧路径,结构同上
├── assets/ 打包后的 JS + CSS
├── ort/ ONNX Runtime 资源(构建时生成,gzip 存储)
├── models/ 放大模型权重
├── _headers Cloudflare 响应头(跨域隔离 + 缓存)
└── robots.txt sitemap.xml site.webmanifest
方式一:Cloudflare Pages(推荐)
仓库已带 wrangler.toml,直接推送到 Cloudflare 即可:
npm run deploy # = npm run build && wrangler pages deploy dist --project-name=image-tools
或者在 Cloudflare 控制台连接 Git 仓库,构建设置填:
| 项 | 值 |
|---|---|
| 构建命令 | npm run build |
| 输出目录 | dist |
| 环境变量 | 不需要 |
public/_headers 是 Cloudflare Pages 的原生特性,跨域隔离头会自动生效,无需额外配置。
方式二:其他静态托管
没有任何服务端代码,把 dist/ 丢上去即可。但要注意三点:
-
public/_headers是 Cloudflare 专有格式。 其他平台要写各自等价的配置 —— Netlify 用同名的_headers、 nginx 用add_header、EdgeOne 用响应头规则。 跨域隔离头必须真的生效,否则会掉到单线程 WASM。 - ORT 运行时在
dist/ort/里,别漏传。 -
放大模型权重在
dist/models/里(已提交到仓库)。 抠图权重不在dist/里 —— 它是运行时从 HuggingFace 按需拉取并缓存的, 部署时不需要额外准备。
nginx 示例
location / {
add_header Cross-Origin-Opener-Policy "same-origin" always;
add_header Cross-Origin-Embedder-Policy "require-corp" always;
try_files $uri $uri/ $uri/index.html =404;
}
部署前必须知道的几件事
1. 跨域隔离是性能开关,不是可选项
Cross-Origin-Opener-Policy: same-origin 与
Cross-Origin-Embedder-Policy: require-corp 是解锁
SharedArrayBuffer、进而让 WASM 多线程推理生效的前提。
缺了它们站点仍然能用,但没有 WebGPU 的机器会掉到单线程 WASM,
慢好几倍。详见浏览器端推理。
2. require-corp 会拦 no-cors 子资源
页面目前只加载自己的资源,所以是安全的。但如果你加了 CDN 脚本、远程字体或统计代码, 就必须给它们配好 CORP 头,否则会被拦下 —— 或者重新考虑这套策略。
fetch() 是唯一的例外,抠图拉权重靠的就是它。
3. ORT 的 wasm 是 25.5 MB,超过 Cloudflare 单文件 25 MiB 上限
scripts/prepare-ort.mjs 因此在构建时把它转成 gzip 存储(约 6.3 MB),
浏览器端用 DecompressionStream 解压。这同时把首次加载量砍掉了四分之三。
出于同样的原因,放大模型权重必须提交到仓库: 构建环境里既没有 Python 也没有上游模型源,不可能在构建时下载。 (抠图权重是 94–452 MB,远超任何静态托管能接受的范围,所以走运行时拉取这条路。)
换自定义域名
canonical、hreflang、og:url、og:image、
JSON-LD、sitemap 与 robots.txt 用的都是绝对 URL,
所以换域名要在这些文件里全局查找替换:
index.html、en/index.html、zh-CN/index.htmlupscale/index.html、en/upscale/index.html、zh-CN/upscale/index.htmlcutout/index.html、en/cutout/index.html、zh-CN/cutout/index.htmlpublic/blog/**/*.html、public/en/blog/**/*.html、public/zh-CN/blog/**/*.htmlpublic/docs/**/*.html、public/en/docs/**/*.htmlpublic/sitemap.xml、public/robots.txtsrc/i18n/index.ts里的SITE_ORIGIN常量
/、/upscale/、/cutout/;
/zh-CN/** 是早期路径,其 canonical 一律指回非 zh-CN 的版本,属于别名。