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.
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).
The answer from Dan still does it.
The only addition I had to implement was for fonts extension in the 3rd handler.
As a FYI, I am using this config for a Vue 3 app and the default build settings.
Final app.yaml for me:
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|woff|woff2|ttf))$
secure: always
static_files: dist/\1
upload: dist/.*\.(js|css|png|jpg|svg|woff|woff2|ttf)$
# wildcard everything else, serving index.html
- url: '/(.*)'
secure: always
static_files: build/index.html
upload: build/index.html
Related
I have set up a website using docusaurus which works great, but when I check the indexing status of my website on google, I got a lot of 'Discovered - currently not indexed' problems, which appears to be a routing problem.
The compiled version of the docusaurus website generates an 'index.html' file for every page or md file in the docusauus project in a separate folder, but the generated links don't add the 'index.html' and instead end like this: https://cam-inspector.com/contact. The browser doesn't seem to go to 'https://cam-inspector.com/contact/index.html', instead it uses the root index.html page and appears to handle the routing locally. This works for viewing, but the google crawler only gets to see the root, so every page contains a canonical url of 'https://cam-inspector.com'. When you browse directly to 'https://cam-inspector.com/contact/index.html', the correct file is retrieved from the server and the canonical tag is correct to 'https://cam-inspector.com/contact'.
I tried to add a redirect to the yaml file of the google app engine deployment so that it would add 'index.hmtl' to all routes that don't end with a file extension, but that doesn't seem to work:
handlers:
# for url without extensions, needs to go to index.html to get seo correct
- url: /(?:/|^)[^./]+$
static_files: www/\1/index.html
upload: www/(.*)/index.html
# files with extension, needed to get all the files
- url: /(.*\..+)$
static_files: www/\1
upload: www/(.*\..+)$
# Catch all handler to index.html, needed to get the root
- url: /.*
static_files: www/index.html
upload: www/index.html
In this post: app.yaml : Redirect any URL ending with / to {url}/index.html they appear to say that you can't add a redirect like that to the yaml def.
So now I'm a little stuck, the only thing I can think of is to add '/index.html' to all the links in the docusaurus code, but that sort of creates something very difficult and tricky to maintain (especially with the auto generated side bar of the docs, where it's much harder to change the links).
Any ideas on how to fix this?
found the solution:
use the following config in docusaurs.config.js: trailingSlash: true,
use these handlers in app.yaml:
- url: /
static_files: www/index.html
upload: www/index.html
- url: /(.*)/$
static_files: www/\1/index.html
upload: www/(.*)
- url: /(.*)
static_files: www/\1
upload: www/(.*)
make certain you declare the links to your pages this way: \contacts\
then things start to behave as expected.
Here's my version of deploying a Docusaurus site to Google App Engine.
handlers:
# static files with a URL ending with a file extension
# (e.g. favicon.ico, manifest.json, jylade.png)
- url: /(.*\..+)$
static_files: build/\1
upload: build/(.*\..+)$
# index page
- url: /
static_files: build/index.html
upload: build/index.html
# anything that ends with a slash (e.g. /docs/)
- url: /(.*)/$
static_files: build/\1/index.html
upload: build/(.*)
# anything else (e.g. /docs)
- url: /(.*)
static_files: build/\1/index.html
upload: build/(.*)
Works for me with the default Docusaurus configuration.
It does not require trailingSlash: true.
Here's my current app.yaml:
runtime: nodejs10
service: default
instance_class: F1
automatic_scaling:
min_instances: 0
max_instances: 2
handlers:
# Serve extension from where they were requested
- url: /(.*\.(css|ico|js|png|jpg|gif|mp4|txt|xml|json))$
static_files: dist/apps/my-app/browser/\1
upload: dist/apps/my-app/browser/.*\.(css|ico|js|png|jpg|gif|mp4|txt|xml|json)$
secure: always
expiration: "365d"
# Handle blog SEO routes
- url: /blog
static_files: dist/apps/my-app/browser/blog/index.html
upload: dist/apps/my-app/browser/blog/index.html
secure: always
expiration: "0s"
- url: /blog/introducing-my-app
static_files: dist/apps/my-app/browser/blog/introducing-my-app/index.html
upload: dist/apps/my-app/browser/blog/introducing-my-app/index.html
secure: always
expiration: "0s"
- url: /blog/added-international-support
static_files: dist/apps/my-app/browser/blog/added-international-support/index.html
upload: dist/apps/my-app/browser/blog/added-international-support/index.html
secure: always
expiration: "0s"
- url: /blog/new-blog-entry
static_files: dist/apps/my-app/browser/blog/new-blog-entry/index.html
upload: dist/apps/my-app/browser/blog/new-blog-entry/index.html
secure: always
expiration: "0s"
# Handle default index.html
- url: /(.*)
static_files: dist/apps/my-app/browser/index.html
upload: dist/apps/my-app/browser/index.html
secure: always
expiration: "0s"
How can I combine the rules under "Handle blog SEO routes" in to one rule? Updating app.yaml with every blog entry is not scalable.
This structure is generated from an Angular Universal Prerender project.
I have tried a few combinations with no luck:
- url: /blog/(.*)
static_files: dist/apps/my-app/browser/blog/\1/index.html
upload: dist/apps/my-app/browser/blog/\1/index.html
secure: always
expiration: "0s"
I think your last try is very close to the actual solution. Please, simply adjust the upload value:
- url: /blog/(.*)
static_files: dist/apps/my-app/browser/\1/index.html
upload: dist/apps/my-app/browser/(.*)/index.html
secure: always
expiration: "0s"
As you can see in the Google Cloud documentation when describing the upload key, you need to provide regex placeholders and not back references in its definition.
Please, consider review similar question here in SO like this one or this other.
I'm trying to deploy a multi-page Vue.js app using google apps python engine.
In order for the Vue.js application to work I need all URL's to fallback so the vue javascript router can take over.
Index.html links:
/foo
/bar
/foo/bar
Subpage.html links:
/subpage/foo
/subpage/bar
/subpage/foo/bar
In my current configuration if I remove the wildcard from the index, then the subpage is accessible, but the index links no longer work. Is it possible to achieve multiple fallbacks, first to '/' and second to '/subpage/'?
I've included my app.yaml which, in my opinion should work as written but doesn't.
runtime: python27
api_version: 1
threadsafe: true
handlers:
# Fonts and images
- url: /(.+\.(eot|otf|tt[cf]|woff2?|cur|gif|ico|jpe?g|png|svgz?|webp))
static_files: dist/\1
upload: dist/(.+\.(eot|otf|tt[cf]|woff2?|cur|gif|ico|jpe?g|png|svgz?|webp))
secure: always
http_headers:
Access-Control-Allow-Origin: "*"
# CSS, Javascript, text and other file types
- url: /(.+\.(css|js|xml|txt|map))
static_files: dist/\1
upload: dist/(.+\.(css|js|xml|txt|map))
expiration: "10m"
secure: always
# HTML pages
- url: /(.+\.html)
static_files: dist/\1
upload: dist/(.+\.html)
expiration: '10m'
secure: always
http_headers:
X-UA-Compatible: 'IE=edge'
# Index entry point
- url: /.*
static_files: dist/index.html
upload: dist/index.html
expiration: '10m'
secure: always
http_headers:
X-UA-Compatible: 'IE=edge'
# Subpage entry point
- url: /subpage/.*
static_files: dist/subpage.html
upload: dist/subpage.html
expiration: '10m'
secure: always
http_headers:
X-UA-Compatible: 'IE=edge'
skip_files:
- ^(.*/)?app\.yaml
- ^(.*/)?app\.yml
- ^(.*/)?#.*#
- ^(.*/)?.*~
- ^(.*/)?.*/RCS/.*
- ^(.*/)?\..*
- ^(.*/)?tests$
- ^(.*/)?test$
- ^test/(.*/)?
- ^COPYING.LESSER
- ^README\..*
- \.gitignore
- ^\.git/.*
- \.*\.lint$
- ^node_modules/(.*/)?
- public/*
- src/*
Your problem is that - url: /.* catches EVERYTHING not yet caught. So, the handlers never get to /subpage/.*
Move the /subpage/.* handler above the wildcard - url: /.*:
# Subpage entry point
- url: /subpage/.*
static_files: dist/subpage.html
upload: dist/subpage.html
expiration: '10m'
secure: always
http_headers:
X-UA-Compatible: 'IE=edge'
# Index entry point
- url: /.*
static_files: dist/index.html
upload: dist/index.html
expiration: '10m'
secure: always
http_headers:
X-UA-Compatible: 'IE=edge'
I am trying to make an Angular 2 app running on App Engine Standard Environment. It works with the following app.yaml configuration when navigating within the app:
handlers:
- url: /api/.*
script: _go_app
- url: (.*)/
static_files: static\1/index.html
upload: static
- url: (.*)
static_files: static\1
upload: static
I can click on a link from / to /clients or /clients/234234 and it works fine.
However if I refresh the browser in a non base path e.g. http://myapp.appspot.com/clients/234234 then I get a 404 error. I guess I need to serve my index.html from all paths which is what I thought (.*)/ and (.*) would do.
How can I set up my handlers/app so I can use HTML5 routing and not let this happen?
I have a bunch of static files that need to be served so I added their mappings first. I also (most importantly) changed the way index.html was served:
handlers:
- url: /api/.*
script: _go_app
- url: /(.*\.svg)
static_files: static/\1
upload: static/(.*\.svg)
- url: /(.*\.js)
static_files: static/\1
upload: static/(.*\.js)
- url: /(.*\.map)
mime_type: application/octet-stream
static_files: static/\1
upload: static/(.*\.map)
- url: (.*)/
static_files: static/index.html
upload: static
- url: (.*)
static_files: static/index.html
upload: static
I cant seem to find this anywhere.
What I have is an appengine project that just serves html pages. But it only correctly loads files when the filename is 'exactly' correct.
I.e. mywebsite.com/lastproject/ loads perfectly
but mywebsite.com/lastproject does not load at all
I want the website to load correctly when the trailing / is left out. What am I missing???
Here is my app.yaml
application: websitewithsubfolder
version: 1
runtime: python
api_version: 1
handlers:
- url: (.*)/
static_files: static\1/index.html
upload: static/index.html
- url: /
static_dir: static
#Shay means the line should be:
- url: (.*)
That is a route that handles all URL requests you will not get any 404 errors, and all Requests are handled by a static index.html page. Your second route will not ever be handled as it is more specific and after your generic route.
You want the more specific routes above your catch all routes.
application: websitewithsubfolder
version: 1
runtime: python
api_version: 1
handlers:
- url: /static
static_dir: static
- url: /favicon.ico
static_files: static/images/favicon.ico
upload: static/images/favicon.ico
mime_type: image/vnd.microsoft.icon
- url: /robots.txt
static_files: robots.txt
upload: robots.txt
- url: /(.*\.(gif|png|jpg))
static_files: \1
upload: (.*\.(gif|png|jpg))
- url: /static/css
static_dir: static/css
- url: /static/js
static_dir: static/js
- url: (.*)
static_files: static/index.html
upload: static/index.html
The app.yaml file above is more in line with what you want.
I suggest you read the app.yaml docs which go over this in more detail.
Your first mapping in the yaml file tells the AppEngine "every url that ends with / should be mapped to ...". You don't have any mapping to something that doesn't ends with /.
this will map everything to a folder named static/html (untested let me know if it works)
- url: /.*
static_dir: static/html
mime_type: text/html