Running a custom build step

By default, the node.js runtime will execute npm run build if a build script is detected in package.json file. If you require additional control over your build steps before starting your application, you can provide a custom build step. Custom build steps can be executed by adding gcp-build in your package.json file.

To prevent your build from running the npm run build script, you must either:

  • Add a gcp-build script with an empty value in your package.json file: "gcp-build":"". For details about configuring the package.json, see Node.js buildpacks configurations.
  • Add the GOOGLE_NODE_RUN_SCRIPTS build environment variable with an empty value in your app.yaml file.

For details about specifying build environment variables see build_env_variables section in the app.yaml file.

When this script is executed, the dependencies in the dependencies and devDependencies fields of your package.json file are available. After executing your custom build step, App Engine removes and regenerates the node_modules folder by only installing the production dependencies declared in the dependencies field of your package.json file.

For more information on how to configure the runtime for custom build steps, see Executing custom build steps during deployment for Node.js buildpacks.


A custom build script can be used for pre-processing tasks, such as pre-processing CSS, minifying client side JavaScript, or running tools, such as webpack or gulp.

For example, to compile TypeScript to JavaScript, your package.json file might look like the following. Note the gcp-build script:

  "name": "appengine-typescript",
  "description": "An example TypeScript app running on Google App Engine.",
  "version": "0.0.1",
  "private": true,
  "license": "Apache Version 2.0",
  "author": "Google Inc.",
  "engines": {
    "node": "16.x.x"
  "scripts": {
    "prepare": "npm run gcp-build",
    "pretest": "npm run gcp-build",
    "test": "c8 mocha -p -j 2 test/*.test.js --exit",
    "lint": "gts lint",
    "start": "node ./index.js",
    "deploy": "gcloud app deploy",
    "clean": "gts clean",
    "compile": "tsc -p .",
    "fix": "gts fix",
    "build": "tsc -p .",
    "gcp-build": "tsc -p ."
  "dependencies": {
    "@typescript-eslint/parser": "^6.0.0",
    "express": "^4.16.3"
  "devDependencies": {
    "@types/express": "^4.17.17",
    "@types/node": "^18.13.0",
    "c8": "^8.0.0",
    "chai": "^4.3.7",
    "gts": "^5.0.0",
    "mocha": "^10.2.0",
    "typescript": "^5.0.0",
    "wait-port": "^1.0.0"

Serving static files

When you generate or copy files during the custom build step, App Engine does not serve these static files directly from your app using either the static_dir or static_files elements defined in the app.yaml file. Instead, App Engine uploads the static files to the serving infrastructure in the standard environment before running the custom build step. Any request to the files generated or copied during the custom build step results in a 404 NOT FOUND HTTP error.