用 Netlify 和 Neocities 部署静态页居然被坑了,分享几个避坑经验
给结论:如果你只是传个单页 HTML,千万别用 Git 自动部署到 Netlify,否则会被白白扣掉 Build Credits。想省事且完全免费,直接用 Cloudflare Pages,或者在 Netlify 用手动上传 Zip 的方式绕过构建流程。
这次折腾 KODA 版本的更新,让我深刻意识到基础设施的选择比写代码本身更影响稳定性。
Netlify 的构建额度陷阱
我用的是单文件 HTML,根本不需要编译,但习惯性地通过 Git 提交触发部署。结果 Netlify 每次都跑一遍所谓的 build 流程,直到我收到一个报错:Account credit usage exceeded - new deploys are blocked until credits are added。
说白了,就是它把这种简单的文件同步也算作构建次数,导致免费额度瞬间见底。因为没信用卡绑定,我直接被锁死了部署权限。
解决办法:
别用 Git 触发,直接在 Netlify 后台用手动上传 Zip 包的方式。这样它会跳过构建阶段,不扣额度,v16 版本也就这样强行上线了。
Neocities 的 CSP 限制导致 API 失联
为了找个永久域名,我尝试迁移到 Neocities。结果上传后发现,前端调用 AI 接口直接挂了,页面提示 OFFLINE SENSEI MODE。
检查后发现是 Neocities 免费版的 CSP(内容安全策略)太严格,直接在浏览器层面拦截了外部 API 的 fetch 请求。你的代码没写错,但宿主环境把你的 AI 脑子给掐断了。
怎么写一个能扛住环境崩溃的 fallback
这次最让我满意的是,虽然宿主环境在作妖,但 App 没崩,也没有出现那种让人绝望的白屏或无限加载圈。这得益于我在 v16 里加的几道防线。
如果你在写调用外部 API 的功能,建议把这套逻辑加上,别指望网络永远稳定:
1. 强制超时控制: 用 AbortController 给所有 AI 请求设 15 秒硬超时,防止请求在后台死等。
2. 错误上报: 在 Supabase 建一个 error_logs 表,只要 catch 到异常立刻写入,这样我能第一时间知道是网络问题还是代码 Bug。
3. 优雅降级: 预设一个 Fallback 界面(比如我写的 Offline Sensei 状态),在请求失败的 1 秒内立即切换。
具体的超时处理逻辑大致是这样:
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 15000);
try {
const response = await fetch('https://api.ai-provider.com/v1', {
signal: controller.signal,
// ...其他配置
});
} catch (error) {
if (error.name === 'AbortError') {
console.log('请求超时,触发降级界面');
showOfflineSensei();
} else {
// 写入 Supabase 错误日志
await supabase.from('error_logs').insert([{ error: error.message }]);
showOfflineSensei();
}
} finally {
clearTimeout(timeoutId);
}
总结和接下来的方案
这次经历告诉我,代码写得再稳,如果基础设施不对,照样会死。
目前 v16 暂时跑在 Netlify 的临时 URL 上,Neocities 只作为静态备份。接下来的计划是全线迁移到 Cloudflare Pages,配合 GitHub 仓库,彻底摆脱这种被构建额度绑架的尴尬。
另外,一个细节坑:如果你在做前端 UI,记得检查 z-index。我在 v16 修复了一个抽屉组件的层级问题,之前在某些低端安卓机(比如 POCO C55)上会出现遮挡,现在终于稳住了。
又在发这种没营养的广告?要是真能自动总结,我那 2 小时的周会记录能变成 3 行字吗?