Skip to main content
Version: v3

Node.js Runtime Environment

info

This article serves as a thorough introduction to Cloud Engine’s Node.js runtime environment. To quickly get started with Cloud Engine, see Getting Started With Cloud Engine.

A Node.js project has to have a package.json under its root directory for Cloud Engine to correctly identify it as a Node.js project. This file also helps Cloud Engine understand the project’s requirements for the environment:

package.json
{
"name": "node-js-getting-started",
"scripts": {
"start": "node server.js",
"dev": "nodemon server.js -- "
},
"dependencies": {
"leancloud-storage": "^3.11.0",
"leanengine": "^3.3.2"
},
"devDependencies": {
"nodemon": "^1.18.7"
},
"engines": {
"node": "16.x"
}
}

If you are looking to start a new project, we recommend that you use our Node.js sample project as a boilerplate.

Startup Command

By default, Cloud Engine starts your project with npm start. You can change the entry point of your program or add additional options to node by editing scripts.start in package.json.

package.json
{
"scripts": {
"start": "node server.js"
}
}
note

When debugging locally by running lean up with the CLI, the CLI will start your project with npm run dev.

Configure Node.js Version

You can specify the version of Node.js by setting engines.node in package.json:

package.json
{
"engines": {
"node": "16.x"
}
}

You can set it to * to stick to the latest (current) version.

note
If you don’t specify a Node.js version, the latest stable (LTS) version will be used.

Configure Package Manager

Cloud Engine now supports these package managers:

Cloud Engine will automatically detect the package manager based on these conditions:

Package ManagerConditionVersion
pnpmA valid pnpm-lock.yaml exists
lockfileVersion: '6.0' or higher8
lockfileVersion: 5.3 or higher7
Otherwise6
Yarn 1yarn.lock exists1
Yarn 2+Not supported by default, enable via Corepack2+
npmOtherwisenpm with the Node.js is used

Experimental Corepack support

Due to Corepack is still experimental, Cloud Engine can't make sure the support for Corepack is stable, use at your own risk

To enable Corepack, setting the ENABLE_EXPERIMENTAL_COREPACK environment variable of the group to any non-empty string.

Cloud Engine will automatically detect package manager based on packageManager field in package.json, then use Corepack to install and enable the package manager. This is the only way to use Yarn 2+ for now.

Assume we have a package.json shown below:

package.json
{
"name": "example",
"packageManager": "[email protected]"
}

Now Cloud Engine will call corepack prepare --activate and detect the package manager is Yarn 2+.

Reference:Corepack

Default commands

The default commands may vary depending on the package manager, e.g. if pnpm is used, npm ci will be pnpm install --frozen-lockfile.

Cloud Engine will skip installing the devDependencies only when installDevDependencies is not true and the build script is empty (which either not specified in leanengine.yaml or scripts.build in package.json not exists).

PharsePackage MamagerConditionCommand
installnpmNode.js version is higher then 10 and package-lock.json or npm-shrinkwrap.json existsnpm ci
npm install or npm install --omit=dev
pnpmpnpm install --frozen-lockfile or pnpm install --frozen-lockfile --prod
Yarn 1yarn install or yarn install --production
Yarn 2+yarn install
note

Be adviced, Yarn 1 will use the resolved URL in yarn.lock without respecting your registry configuration, use proper registry before deploy to Cloud Engine, or build time might increase.

Install Dependencies (package.json)

Cloud Engine will automatically install dependencies according to the package.json in your project:

package.json
{
"dependencies": {
"leancloud-storage": "^3.11.0",
"leanengine": "^3.3.2"
},
"devDependencies": {
"nodemon": "^1.18.7"
}
}

While installing dependencies, Cloud Engine will trigger the life cycle scripts of npm, such as postinstall and prepare.

Since Cloud Engine installs dependencies on the server side, the CLI won’t upload node_modules by default. If you’re deploying with Git, you should include node_modules in .gitignore so it won’t be tracked by Git.

note

CLI will upload .yarn directory, if you don't want to enable Zero-installs when Yarn 2+ PnP(Plug'n'Play) is used, add .yarn/cache to your .gitignore and .leanignore

Customize Build Process

You can override the default behavior by specifying startup commands (run), dependency installation commands (install), and build commands (build) in leanengine.yaml:

leanengine.yaml
run: echo 'run another command'
install:
- {use: 'default'}
- echo 'install additional dependencies here'
build:
- echo 'overwrite default build command here'

See Reference: leanengine.yaml for more information. Below are a few examples:

Install Dependencies for Sub-Projects

leanengine.yaml
install:
- use: default
- require:
- ./frontend/package.json
- ./frontend/package-lock.json
- cd frontend && npm ci
build:
- npm run build
- cd frontend && run build

Here we keep the default behavior and install dependencies and run build commands for the frontend directory.

System Dependencies

You can specify the system dependencies provided by the server-side environment using leanengine.yaml:

leanengine.yaml
systemDependencies:
- imagemagick

See Reference: leanengine.yaml for a complete list of supported system dependencies.

Build Logs

By default, the logs generated during the build process won’t be printed to the console. If the build process fails, the logs from the last completed step will be printed to the console.

To print the complete build log for debugging, check Print build logs if you are deploying from the dashboard or add --options 'printBuildLogs=true' if you are deploying with the CLI.

Health Check

Cloud Engine is primarily optimized for web applications. Your app is expected to provide HTTP services through the port specified by the environment variable named LEANCLOUD_APP_PORT. Keep in mind that the app should listen on 0.0.0.0 (all interfaces) instead of 127.0.0.1 which is the default host of many frameworks.

While your app is being deployed, Cloud Engine will check your app every second to see if it has been successfully started. If your app has not been started within the time limit (30 seconds by default), the deployment will be canceled. After your app has been deployed, Cloud Engine will run health checks for your app regularly and automatically restart it if the check fails.

The way the health check works is that Cloud Engine will send an HTTP request to the homepage (/) of your app. If it gets an HTTP 2xx response, your app will pass the health check.

Health check and the Cloud Engine SDK

Cloud Engine will also check /__engine/1/ping which is handled by the SDK. If the SDK is integrated correctly, Cloud Engine will not check the homepage (/) anymore.

If Developer Center > Your game > Game Services > Cloud Services > Cloud Engine > Manage deployment > Your group > Settings > Cloud functions mode is set to Enable, or if functionsMode in leanengine.yaml is set to strict, Cloud Engine will check if the SDK is integrated correctly. If not, it will consider your app to have failed to start.

Customizing startup timeout (startupTimeout)

The default timeout for your app to start is 30 seconds. You can change it to any value between 15 and 120 seconds with leanengine.yaml:

leanengine.yaml
startupTimeout: 60

Cloud Environment

Custom Domains

Projects deployed to Cloud Engine can only be accessed with domains configured. You can bind domains by going to Developer Center > Your game > Game Services > Cloud Services > Cloud Engine > Manage deployment > Your group > Settings > Domains.

If you bind a domain that starts with stg- (e.g., stg-api.example.com), it will be assigned to the staging environment automatically.

We provide shared domains for apps that are still under testing. You can assign your app a shared domain with a prefix of your choice.

Load Balancer and CDN

All HTTP and HTTPS requests sent to Cloud Engine will go through a load balancer that deals with chores including HTTPS encryption, HTTPS redirection, and response compression. You won’t have to implement features for handling these tasks yourself for the programs hosted on Cloud Engine. Meanwhile, the load balancer brings the following restrictions that your program cannot bypass:

  • Paths starting with /.well-known/acme-challenge/ are used by Cloud Engine to automatically renew certificates. Requests sent to these paths won’t be forwarded to your program.
  • The size of a request header (URL and headers) should be within 64K and each line of the request header should be within 8K.
  • The size of a request (for uploading files) should be within 100M.
  • The timeout for connecting or waiting for a response is 60 seconds.

Getting the Client IP Address

Cloud Engine’s load balancer includes the following information depicting the original request in the HTTP header:

  • X-Real-IP: The original IP address.
  • X-Forwarded-Proto: The original protocol (http or https).
  • Forwarded: Information about the proxy, defined by RFC 7239. It contains the IP address and the protocol.

In Express:

app.get("/", function (req, res) {
console.log(req.headers["x-real-ip"]);
res.send(req.headers["x-real-ip"]);
});

HTTPS Redirect

When you bind a custom Cloud Engine domain, you can enable Force HTTPS to have the load balancer redirect HTTP requests to HTTPS while keeping the paths.

Environment Variables

The following environment variables are available for your application to use:

Variable nameDescription
LEANCLOUD_APP_IDThe App ID of the current application.
LEANCLOUD_APP_KEYThe App Key of the current application.
LEANCLOUD_APP_MASTER_KEYThe Master Key of the current application.
LEANCLOUD_APP_ENVThe environment your application is running in. If you are running your application on your local computer, the value will be non-existent or development (if you are starting your application with the CLI). It will be stage for the staging environment and production for the production environment.
LEANCLOUD_APP_PORTThe port opened up for your application. Your application has to listen on this port in order for users to access your service.
LEANCLOUD_API_SERVERThe address used to access the Data Storage service. Please use this value if your application needs to access the Data Storage service or other cloud services with the REST API.
LEANCLOUD_APP_GROUPThe group the instance is located at.
LEANCLOUD_REGIONThe region the application is running in. It will be CN for Mainland China and US for the United States.
LEANCLOUD_VERSION_TAGThe version number of the deployment.

You can also set up custom environment variables on the dashboard to store configurations.

Logs

note

See Cloud Engine Platform Features § Viewing Logs for more information on how to view logs and access logs on the dashboard.

Cloud Engine will collect the logs your application has printed to standard output (stdout) and standard error (stderr):

console.log("hello"); // stdout
console.error("some error"); // stderr
note

Each line of the logs can contain a maximum of 4096 characters. A maximum of 600 lines of logs can be collected every minute. The logs generated by your application that exceed these limits will be discarded.

Timezone

The timezone used on the server side is UTC+0.

File System

Your application can create temporary files under /home/leanengine and /tmp. The size limit for all the files created by your application is 1 GB.

caution

Each time you trigger a new deployment for your application, Cloud Engine will create a new container for it. Even though you don’t trigger deployments, Cloud Engine will still perform occasional maintenance operations. This means that your application should not treat the file system provided by Cloud Engine as permanent storage.

If the files created by your application bear relatively larger sizes, we recommend that your application always cleans them up once it finishes using them. Creating more files when there are already more than 1 GB files existing might lead to the Disk quota exceeded error. You can trigger a deployment to quickly clean up all the temporary files.

IP Addresses

Some third-party platforms (like Weixin Open Platform) may require that you provide an IP address whitelist. You can obtain the inbound and outbound IP addresses used by Cloud Engine on Developer Center > Your game > Game Services > Cloud Services > Cloud Engine > Manage deployment > Your group > Settings > Inbound IP and outbound IP.

We will do our best to minimize the frequency of changing the inbound and outbound IP addresses, but there remains the possibility for them to get changed. If you encounter any problems with IP addresses, the first thing you can do is look at the IP addresses displayed on the dashboard and see if they have been changed.

To get a fixed inbound IP address for your application, consider enabling dedicated IP.

Troubleshooting

Why are the dependencies listed under devDependencies not installed?

When you deploy your project, Cloud Engine will install dependencies (including those listed under devDependencies) for your project with npm ci. However, if the Node.js version you specified is below 10 or lockfile not exists, Cloud Engine will use npm install --production instead. This means that the dependencies listed under devDependencies will not be installed, see Default Commands. To have these dependencies installed as well, you can specify installDevDependencies: true in leanengine.yaml.

What should I do if I see npm ERR! peer dep missing?

If you see an error like this when deploying your project:

npm ERR! peer dep missing: graphql@^0.10.0 || ^0.11.0, required by [email protected]

This means that some of the peer dependencies are not successfully installed. The reason is that if the version of Node.js you specified is below 10, Cloud Engine will only install the dependencies listed under dependencies. Please make sure the required dependencies of the dependencies listed under dependencies are also listed under dependencies, not devDependencies.

You can reproduce the problem on your local computer by deleting node_modules and installing dependencies with npm install --production.

You may also consider upgrading Node.js to 10 or higher to solve the problem.

Timeout Settings

If a request triggers a function that doesn’t give a response due to an error, the server’s RAM will still be occupied for this request. To prevent the RAM from being occupied in this case and to have the client receive an error without delay, there needs to be a timeout set up on the server so that when a request doesn’t receive a response in a while, the server will return an HTTP error code to the client.

The default timeout for the custom routes defined with Express is 15 seconds. You can edit this value in app.js:

// Set the default timeout
app.use(timeout("15s"));