到处都有关于如何做到这一点的指南和问题,但从来没有真正令人满意的具体答案。基本上,我想知道是否可以在 GCP Cloud Storage 中托管静态 SPA (HTML/CSS/JS)。
主要需要注意的是 SPA 有自己的路由系统 (ReactRouter),所以我希望所有路径都由 index.html 提供服务。
大多数指南会告诉您将 ErrorDocument 设置为
index.html
而不是 404.html
。虽然这是一个聪明的黑客,但它会导致网站的 HTTP 响应代码为 404,这对于 SEO 或监控工具来说是一场灾难。这样就可以了,只要我可以更改响应代码。
有什么办法可以做到这一点吗?我也启动并运行了 CloudFlare,但据我所知,无法从那里修剪路径或更改响应状态。
这里的一个好方法是使用 Google App Engine 托管静态 SPA。 https://cloud.google.com/appengine/docs/standard/python/getting-started/hosting-a-static-website
您可以使用 app.yaml 文件将 url 映射到静态文件。这是一个例子:
runtime: python27
api_version: 1
threadsafe: true
handlers:
- url: /
static_files: www/index.html
upload: www/index.html
- url: /(.*)
static_files: www/\1
upload: www/(.*)
app.yaml 文档 https://cloud.google.com/appengine/docs/standard/python/config/appref
规避该问题的一种方法是使用服务器端渲染。在 SSR 中,所有客户端请求都会传递到后端应用程序,因此不需要云存储托管
index.html
。
这当然有其自身的复杂性,但我们正在避免上述 404 黑客攻击或诉诸任何进一步的依赖项,例如 App Engine。
或者,您可以使用基于哈希的路由,即类似
https://example.com/#some-path
的路径。
推荐的方法是在云存储桶前面放置一个全局外部负载均衡器。在负载均衡器中,您可以创建一个路由规则,它将每个请求重写到您的
index.html
。
defaultService: projects/xxxx/global/backendBuckets/spa
name: path-matcher-1
routeRules:
- matchRules:
- pathTemplateMatch: /**
priority: 10
service: projects/xxxx/global/backendBuckets/spa
routeAction:
urlRewrite:
pathTemplateRewrite: /index.html
如果您使用 Cloudflare,则可以使用 Cloudflare Worker 覆盖来自 Google Cloud Storage 错误页面的 404 状态代码。
Worker 的代码应该如下所示:
addEventListener('fetch', event => {
event.respondWith(fetchAndLog(event.request))
})
async function fetchAndLog(req) {
const res = await fetch(req)
console.log('req', res.status, req.url)
if (res.status === 404 && req.method === 'GET') {
console.log('overwrite status', req.url)
return new Response(res.body, {
headers: res.headers,
status: 200
})
}
return res
}
我在 Cloudflare 社区这里找到了它。