3

My App.yaml configuration file is :

runtime: nodejs12


handlers:
  # Serve all static files with url ending with a file extension
  - url: /(.*\..+)$
    static_files: build/\1
    upload: build/(.*\..+)$
  # Catch all handler to index.html
  - url: /.*
    static_files: build/index.html
    upload: build/index.html
    secure: always
    redirect_http_response_code: 301
  - url: /static
    static_dir: static

When I deploy it doesn't update the frontend. I think the static files are not changing whenever I deploy. Is it caching? I don't know what to do

1 Answers1

2

First, are you deploying to a new version and not migrating traffic to it? In the GCP console, you can go to "App Engine" > "Versions" (https://console.cloud.google.com/appengine/versions) to see your currently deployed versions and it will tell you which one is receiving traffic.

Next, make sure your files actually got deployed. If you go to the "Debugger" in the GCP console (https://console.cloud.google.com/debug), you'll be able to browse what files have been deployed. If you have multiple versions, there is a version dropdown to switch between them, so make sure you are browsing the correct version.

Is it caching?

App engine does set the cache period for static assets to 10 minutes if you dont otherwise specify.

default_expiration Optional. Sets a global default cache period for all static file handlers for an application. You can also configure a cache duration for specific static file handlers. The value is a string of numbers and units, separated by spaces, where units can be d for days, h for hours, m for minutes, and s for seconds. For example, "4d 5h" sets cache expiration to 4 days and 5 hours after the file is first requested. If omitted, the production server sets the expiration to 10 minutes.

https://cloud.google.com/appengine/docs/standard/nodejs/config/appref#runtime_and_app_elements

EDIT: Also, the order of your handlers: matters. They are checked in order. So your rule for url: /.* is probably capturing all of the traffic you intended to be captured by your rule for url: /static

Furthermore, I think its a mistake for your catch-all url: /.* handler to return index.html. It'd be better to have something like url: /index.html return your index.html and let the rest just 404. You probably have other errors/typo'd urls that you aren't noticing right now.

EDIT 2:

I'm actually surprised your current setup ever worked, because in the reference for app.yaml it says:

In order to use static handlers, at least one of your handlers must contain the line script: auto or define an entrypoint element to deploy successfully.

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

So I put together a sample project, this is my project structure:

- build
  - index.html
- node_modules
  - <folders-from-npm-install>
- static
  - css
    - bootstrap.css
- app.js
- app.yaml
- package.json

In app.yaml I did a few things.

  • I put url: /static first because url: /(.*\..+)$ was capturing /static/css/bootstrap.css.
  • I removed the entry for index.html because url: /(.*\..+)$ was already taking care of it
  • i added a final catch-all entry to send all remaining traffic to app.js

app.yaml:

runtime: nodejs12

handlers:
  - url: /static
    static_dir: static
  # Serve all static files with url ending with a file extension
  - url: /(.*\..+)$
    static_files: build/\1
    upload: build/(.*\..+)$
  - url: /.*
    script: auto

For app.js and package.json i copied them from GAE's "Hello World" example here https://github.com/GoogleCloudPlatform/nodejs-docs-samples/tree/master/appengine/hello-world/standard

app.js:

'use strict';

// [START gae_node_request_example]
const express = require('express');

const app = express();

app.get('/', (req, res) => {
  res.status(200).send('Hello, world!').end();
});

// Start the server
const PORT = process.env.PORT || 8080;
app.listen(PORT, () => {
  console.log(`App listening on port ${PORT}`);
  console.log('Press Ctrl+C to quit.');
});
// [END gae_node_request_example]

module.exports = app;

package.json:

{
  "name": "appengine-hello-world",
  "description": "Simple Hello World Node.js sample for Google App Engine Standard Environment.",
  "version": "0.0.2",
  "private": true,
  "license": "Apache-2.0",
  "author": "Google Inc.",
  "repository": {
    "type": "git",
    "url": "https://github.com/GoogleCloudPlatform/nodejs-docs-samples.git"
  },
  "engines": {
    "node": ">=12.0.0"
  },
  "scripts": {
    "start": "node app.js",
    "test": "mocha --exit test/*.test.js"
  },
  "dependencies": {
    "express": "^4.17.1"
  },
  "devDependencies": {
    "mocha": "^8.1.3",
    "supertest": "^5.0.0"
  }
}

I ran npm install and npm start to run it locally, per the instructions in the hello world, but unfortunately that doesnt emulate the behavior of handlers: in app.yaml

when i deployed it, going to https://my_project_id.appspot.com/index.html did work.

Alex
  • 4,510
  • 8
  • 24
  • I added the url: /index.html and now when I deploy I get 502 error bad gateway nginx and It won't go away anymore even when I go back to my old app.yaml, any idea why? – BigSteppaJC Oct 09 '20 at 01:18
  • See 'EDIT 2' in my answer. I think you need to include a basic `app.js` and have a catch-all handler route to it. – Alex Oct 09 '20 at 16:41