Host a static site single page app in Google Cloud Storage with routes
Asked Answered
S

6

26

There are guides and questions all over the place on how to do this, but never really a concrete answer that is satisfactory. Basically, I'm wondering if it's possible to host a static SPA (HTML/CSS/JS) in GCP Cloud Storage.

The main caveat of this is that the SPA has its own routing system (ReactRouter) so I want all paths to be served by index.html.

Most guides will tell you to set the ErrorDocument to index.html instead of 404.html. While this is a clever hack, it causes the site's HTTP response code to be 404 which is a disaster for SEO or monitoring tools. So that will work, as long as I can change the response code.

Is there any way to make this work? I have CloudFlare up and running too but from what I can tell there are no ways to trim the path or change the response status from there.

Scraggy answered 2/4, 2018 at 17:39 Comment(0)
P
3

A good approach here is to use Google App Engine to host a static SPA. https://cloud.google.com/appengine/docs/standard/python/getting-started/hosting-a-static-website

You can use the app.yaml file to map urls to the static file. Here’s an example:

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/(.*)

Documentation for app.yaml https://cloud.google.com/appengine/docs/standard/python/config/appref

Petulancy answered 3/4, 2018 at 12:45 Comment(4)
Thanks for the answer, this is definitely a viable option. Unfortunately it's also a somewhat heavy and costly option when all we're really talking about is serving up some HTML/JS files. We want to be hosting dozens of these SPAs so I'm hoping to find a way to do it with GCP buckets as the backend.Scraggy
I can confirm that it's not possible to change the response code with the bucket redirection. So if you'd like to serve all paths by index.html using buckets, you'll have the 404 response code. However I tested this example with App Engine and works as intended. I was able to serve all by index.html without getting 404. App engine has a free tier so you can take a look at it. cloud.google.com/free/docs/always-free-usage-limits#gae_namePetulancy
@MattDodge we are currently experiencing similar problems. Just curious, how did you end up solving this problem eventually? ThanksSanches
@TimurMamedov I ended up just using AWS S3 hahaScraggy
C
3

A very simple solution would be to just add the index.html file as the 404 fallback. This will always route everything to your single page app. enter image description here

Caveat answered 26/10, 2022 at 9:8 Comment(2)
This works but it will also return a 404 status code with that index page which might cause other issuesFilthy
This is bad for SEO. Search engine robots do not like 404 status code. In our case that affected our listing in the Playstore and Addon Store for the Workspaces.Marandamarasca
F
3

The recommended way would be putting a global external load balancer in front of the cloud storage bucket. In the load balancer you can create a routing rule which rewrites every request to your 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
Formalize answered 19/12, 2023 at 19:27 Comment(1)
Note that this option requires a global external application load balancer, which may mean it's not possible depending on how your network is set up. I'd much prefer to use this answer instead of have a dedicated App Engine or Cloud Run instance simply for doing this rewritingOvercharge
T
2

One way to circumvent the problem is to use server-side rendering. In SSR all client requests are passed to a backend app so there's no need for a Cloud Storage-hosted index.html.

This of course comes with its own set of complications but we're avoiding the above-mentioned 404 hack or resorting to any further dependencies like App Engine.

Alternatively you could go with hash-based routing, i.e. paths like https://example.com/#some-path.

Timbre answered 15/4, 2019 at 13:13 Comment(0)
A
-1

If you use Cloudflare, you can use a Cloudflare Worker to override the 404 status code, which comes from the Google Cloud Storage error page.

The code for the Worker should look like this:

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
}

I found it here in the Cloudflare community.

Attitude answered 24/4, 2020 at 20:27 Comment(0)
M
-1

I ended up hosting my application on Cloudflare Pages. They provide out-of the-box support for single page applications and have builtin integration with Github for deployment. It's a shame that a company the size of Google Cloud Platform doesn't provide a way to implement such a common/trivial use case which is hosting single page applications on their CDN service.

Marandamarasca answered 22/4, 2024 at 14:40 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.