google-app-engineapp.yaml

Google App Engine Static Website Handler Wildcard Routes


I have a React.js website using create-react-app and just moved from Firebase Hosting to Google App Engine Standard Environment.

With Firebase Hosting, I could create routes like https://example.com/route or https://example.com/newRoute/123 and Firebase would know to serve the index.html for any of these routes.

I want to wildcard any route of our application to use the index.html while excluding .js and .css files. If I use only the wildcard /(.*) then the request for our main.js file also resolves to index.html.

Here is our handler config

handlers:
  - url: /
    secure: always
    application_readable: false
    static_files: build/index.html
    require_matching_file: false
    upload: build/index.html
  - url: /login
    secure: always
    application_readable: false
    static_files: build/index.html
    require_matching_file: false
    upload: build/index.html
  - url: '/(.*)'
    secure: always
    application_readable: false
    static_files: "build/\\1"
    require_matching_file: false
    upload: 'build/.*'

In the current configuration, every route I create must be registered as a handler. I was hoping to find a solution where all current routes and future routes can be handled by a wildcard.


Solution

  • The order of the handlers matters, the 1st one with a matching pattern wins.

    So to achieve what you want you could handle the exceptions first, before "wildcarding" the index.html. Something along these lines (I assumed the .css and .js files are also relative to the build dir):

    handlers:
    
      - url: /(.*\.css)$
        secure: always
        static_files: build/\1
        upload: build/.*\.css$
    
      - url: /(.*\.js)$
        secure: always
        static_files: build/\1
        upload: build/.*\.js$
    
      # continue similarly the other static assets
      # or maybe try a more generic one covering several of them:
      - url: /(.*\.(js|css|png|jpg|svg))$
        secure: always
        static_files: build/\1
        upload: build/.*\.(js|css|png|jpg|svg)$
    
      # wildcard everything else, serving index.html
      - url: '/(.*)'
        secure: always
        static_files: build/index.html
        upload: build/index.html
    

    Side note: for readability I also dropped the require_matching_file (no such thing in GAE) and application_readable (by default it is false).