Node.JS app dependency installations can be handled by npm or yarn.
This KB is specific to Node.JS app dependency installations via npm.
When pushing a Node.JS app on Tanzu Application Service for VMs, the Node.JS buildpack will run a series of npm commands to ensure dependencies are met and in sync while staging the droplet. Due to changes within npm, staging a Node.JS app may fail with newer buildpack releases that previously worked with the older buildpack releases. This KB article aims to discuss some of the observed staging failure scenarios.
Three observed reasons for staging failures:
An example of the error observed during cf push if the application is effected from items 1 or 2 above:
2021-12-09T12:17:03.10-0500 [STG/2] OUT Installing node modules (package.json + package-lock.json) 2021-12-09T12:32:10.24-0500 [API/9] ERR Failed to stage build: staging failed
Examples of errors observed during cf push if the application is effected from item 3 above:
2022-02-28T09:38:06.68-0500 [STG/0] OUT Installing any new modules (package.json + package-lock.json) 2022-02-28T09:38:10.47-0500 [STG/0] OUT > my-nodejs-service@1.0.0 postinstall 2022-02-28T09:38:10.47-0500 [STG/0] OUT > ./scripts/my-post-install-script.sh 2022-02-28T09:38:10.48-0500 [STG/0] OUT > my-nodejs-service@1.0.0 prepare 2022-02-28T09:38:10.48-0500 [STG/0] OUT > husky install 2022-02-28T09:38:10.48-0500 [STG/0] OUT sh: 1: husky: not found 2022-02-28T09:38:10.49-0500 [STG/0] OUT npm ERR! code 127 2022-02-28T09:38:10.49-0500 [STG/0] OUT npm ERR! path /tmp/app 2022-02-28T09:38:10.49-0500 [STG/0] OUT npm ERR! command failed 2022-02-28T09:38:10.49-0500 [STG/0] OUT npm ERR! command sh -c husky install 2022-02-28T09:38:10.55-0500 [STG/0] OUT npm ERR! A complete log of this run can be found in: 2022-02-28T09:38:10.55-0500 [STG/0] OUT npm ERR! /home/vcap/.npm/_logs/2022-02-28T14_38_10_495Z-debug.log
2022-02-28T10:51:11.64-0500 [APP/PROC/WEB/0] OUT > MY-APP@1.0.0 start 2022-02-28T10:51:11.64-0500 [APP/PROC/WEB/0] OUT > node index.js 2022-02-28T10:51:11.76-0500 [APP/PROC/WEB/0] ERR node:internal/modules/cjs/loader:936 2022-02-28T10:51:11.76-0500 [APP/PROC/WEB/0] ERR throw err; 2022-02-28T10:51:11.76-0500 [APP/PROC/WEB/0] ERR ^ 2022-02-28T10:51:11.76-0500 [APP/PROC/WEB/0] ERR Error: Cannot find module 'nodemon' 2022-02-28T10:51:11.76-0500 [APP/PROC/WEB/0] ERR Require stack: 2022-02-28T10:51:11.76-0500 [APP/PROC/WEB/0] ERR - /home/vcap/app/index.js
node
versions come packaged with each buildpack version. See the Node.JS version table to see which npm version comes with a given node
release. See the Node.JS buildpack releases to get insight into default node versions used per buildpack.Security patches were introduced to npm starting with v6.14.15 and v7.21.0, resulting a performance regression.
For more information about this issue, refer to NPM Restore 15 times slower on versions > 6.14.13 #3939.
The performance regression has been partially patched in npm v7.21.1 and npm v8, however, there are no plans to backport the patch to npm v6.
Node.JS Buildpack v1.7.61 provides npm v6.14.15 as the default npm version. Due to this, Node.JS applications may fail to stage when using this buildpack. The failure will be observed while installing dependencies referenced in package.json
if either of the following is true:
Dependencies are not packaged with the application.
A working node and/or npm version combination isn't specified by the application's package.json
.
This failure scenario is specific to apps that have dependencies vendored, which is a common use case for air-gapped environments or environments that have networking rules in place to block internet bound traffic egressing from Diego Cells. Vendoring dependencies with the app means that the app is pushed with a package-lock.json file and a node_modules directory containing all dependencies needed to stage and run the application.
By vendoring the dependencies with the app, there should not be a need for the staging container to reach out to the npm registry.
It has been observed that network calls to the npm registry can happen due to an incompatibility of the package-lock.json files between different versions of npm.
The following events may result in this staging failure scenario:
Locally installing dependencies for the application with npm v6 and pushing the application with a newer buildpack that contains npm v7+.
Npm debug log output would show something similar to:
npm WARN old lockfile npm WARN old lockfile The package-lock.json file was created with an old version of npm, npm WARN old lockfile so supplemental metadata must be fetched from the registry. npm WARN old lockfile npm WARN old lockfile This is a one-time fix-up, please be patient...
In this scenario, staging would fail if the npm registry can not be reached from the staging container.
Starting with Node.JS buildpack v1.5.35 the environment variable NODE_ENV is set to "production".
Starting with npm v7, the npm config property "omit" is set to "dev" when the environment variable NODE_ENV is set to "production" as seen in the documentation:
omit Default: 'dev' if the NODE_ENV environment variable is set to 'production', otherwise empty.
This "omit" property is not in the config for npm v6.
If an application has scripts or runtime dependencies that rely on the dependencies under the devDependencies section in the package.json file then those dependencies will not be available when called if the following is true:
Workaround 1
Vendor dependencies if you can.
Due to the incompatibility of the package-lock.json files between different versions of npm it is recommended to run npm install
locally against your app using the target version of npm
that the buildpack uses. For example if you are using buildpack 1.7.63, then use npm v8.0.0 to run npm install
locally.
Workaround 2
If dependencies cannot be vendored, pin to a known working version of node and/or npm within package.json
. See the Node.JS buildpack docs for details on how to do this. It’s not necessary to specify an npm
version if the specified node
version comes packaged with a working npm version already.
For example:
"engines": { "node": "12.x.x" }
For each of the above recommendations, it’s advisable to use the most recent version of the buildpack available to you. If neither of the above recommendations work, however, you may pin the buildpack itself to a known working version. See Managing Custom Buildpacks.
Notes
include=dev
**ERROR** We're unable to download the version of npm you've provided.
package-lock.json
to ensure build reproducibility.before a TAS upgrade so apps can be verified to work with newer buildpacks first then running the following before the upgrade will help:
cf update-buildpack nodejs_buildpack --lock
--- applications: - name: my-app-name buildpack: nodejs_buildpack env: NODE_VERBOSE: true NPM_CONFIG_LOGLEVEL: silly