3
votes

I'm trying to (con)figure the best way to structure a JS client + NodeJS server app to host it on Google Cloud AppEngine (plus possibly other GCP resources). So I'm looking for advice / best practices here.

We have an API server running on a non-default AppEngine service and would like to be able to run several, e.g. development/staging/production versions on the same project (if possible).

We would like to host / serve our static client app on this system because we want to use the same domain to point at it.

In our normal server based setup, the client app is proxied/served on domain.com/ and requests to the API are on domain.com/v1/

I've been working through different options - hosting a separate static site running on AppEngine and using dispatch.yaml to try to route requests - this option doesn't seem to work with domain prefixes, only wildcards, e.g.

dispatch:
- url: "my-client-service-project.appspot.com/"
  service: my-client-service
- url: "my-client-service-project.appspot.com/v1/*"
  service: my-backend-service

Doesn't work, but:

- url: "*/v1/*"
  service: my-backend-service

Does, which we didn't want because we'd like to run dev, staging & production if possible.

The other option I've been looking at is having the static folder hosted as part of my app, but I can't seem to get this working either, here is the snippet from my app.yaml:

handlers:
  - url: /.*
    static_files: client/dist/index.html
    upload: frontend/dist/index.html
  - url: /v1/*
    script: dist/index.js

My guess is that script may not work the same as for Python apps, but I could be wrong - the doc's aren't very clear.

Ideally, I'd like to host the client front-end static files on storage and point to the AppEngine API server (without specifically pointing to a domain from the client, e.g. /v1/auth/login rather than my-backend-service-project.appspot.com/v1/

References:

How can I use bucket storage to serve static files on google flex/app engine environment?

Node.js + static content served by Google App Engine

https://cloud.google.com/appengine/docs/flexible/nodejs/serving-static-files

https://cloud.google.com/appengine/docs/standard/python/how-requests-are-routed#routing_via_url

https://cloud.google.com/appengine/docs/standard/python/config/appref

https://cloud.google.com/appengine/docs/standard/python/config/dispatchref

2

2 Answers

3
votes

To begin: you're mixing up standard and flexible env docs - not a good idea as they don't work the same way. See How to tell if a Google App Engine documentation page applies to the standard or the flexible environment.

Since your app is Node.JS you have to use the flexible env, for which script and static_files aren't applicable inside app.yaml. Which is why you can't get them to work.

The first reference in your list shows the options you have for serving the static files. But I kinda question your desire to use the shared GCS option - it will serve the same content regardless of the dev/staging/production environment, so:

  • you can't have different client side environments
  • how do you see selecting a particular server-side environment since the client side references can only point in one direction (i.e. environment, if I understand your intention correctly)?

If your desire to use a single domain means that you'd still be OK with using different subdomains (of that domain) and if you'd be willing to use a custom domain this might be of interest: How to use GAE's dispatch.yaml with multiple development environments?

UPDATE:

Node.JS is currently available in the standard environment as well, so you can use those features, see:

2
votes

Take this answer as a complement to the one of @Dan Corneliscu, as I think it is pretty useful and summarizes what you are doing wrong and what can be achieved in the type of scenario you present. In any case, I would like to provide some more information which may be useful.

As for the reason why the dispatch rules approach you suggested does not work, you should update your paths in the application accordingly. They should now be listening to /v1/your_endpoint instead of /your_endpoint as they probably did before. It is not enough with changing your dispatch file. Then also make sure that the Dispatch routes field is populated in your App Engine > Services tab in the Console.

Also the alternative approach you suggested will indeed not work using static_files, but you can follow this guide explaining how to serve Static Files from a GAE Flexible application.