Skip to main content

Frontend Runtime Environment

You can deploy frontend apps (like websites) to Cloud Engine. For apps built with frameworks like React and Vue, their build processes can be run on Cloud Engine so you don’t have to clutter your Git repositories with production builds or set up additional CI environments. With Cloud Engine, you can easily bind custom domains to your app, set up auto-renewal for SSL certificates, and enable HTTPS redirects. These features help you reduce the time spent on deploying and maintaining your app.


This article serves as an introduction to Cloud Engine’s frontend runtime environment. For features provided by the Cloud Engine platform, see Cloud Engine Platform Features.

If your project has a file named static.json or index.html under its root directory, Cloud Engine will identify it as a frontend project. When you deploy your project, Cloud Engine will build it with the Node.js runtime environment and automatically start an HTTP server with serve.

Getting Started

Most frontend scaffolds can be deployed to Cloud Engine with little to no configurations. Consider using them if you plan to create a new project.

create-react-app provides out-of-the-box toolchains that automatically set up build tools for your React project so you can focus on development:

npx create-react-app react-for-engine --use-npm

Then navigate to the project’s directory (react-for-engine in the example above) and create a configuration file named static.json that rewrites non-existing URLs to index.html. This allows your single-page application to use its own frontend router (like react-router):

"public": "build",
"rewrites": [{ "source": "**", "destination": "/index.html" }]

Then create a file named leanengine.yaml and specify the build command in it:

build: npm run build

The build process can be run on Cloud Engine so you don’t have to include a production build in your Git repository or set up additional CI environments.

Deploy to Cloud Engine

Run the following command to deploy your project to the production environment:

lean deploy --prod

Configure Node.js Version

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

"engines": {
"node": "16.x"

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

For newly created apps, if you don’t specify a Node.js version, the latest stable (LTS) version will be used. For apps created before 9/2/2021, Node.js `0.12` will be used by default to ensure compatibility.

Config 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
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:

"name": "example",
"packageManager": "yarn@4.0.2"

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


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 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

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:

"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.


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

Configure serve

To customize the behavior of serve, create a file named static.json under the root directory of your project.

"public": "build", // Start the website from the `build` directory rather than the root directory
"rewrites": [
{ "source": "**", "destination": "/index.html" } // Redirect all non-existing URLs to `index.html` (applicable to most single-page applications)

See serve-handler · Options for more options and usages of serve.

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:

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

See Reference: leanengine.yaml for more information.

System Dependencies

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

- 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.

Cloud Environment

Custom Domains

Projects deployed to Cloud Engine can only be accessed with domains configured. You can bind domains by going to Dashboard > LeanEngine > Manage deployment > Your group > Settings > Domains.

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

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.

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.


Force HTTPS won’t work properly if CDN is enabled. You’ll still need to implement redirect in your project’s code.

CDN Caching

If you resolve your custom domain to the CDN (including the shared domain provided by Cloud Engine), the CDN will cache the responses for the requests it has received. There are some default rules for caching followed by the CDN.

The CDN will cache the response if:

  • The response header contains Last-Modified (this indicates that the resource requested is static; for HTML files, they will be cached for at most 60 seconds).

The CDN will not cache the response if:

  • There is an error with the response (not 2xx).
  • The request is not idempotent (like a POST request).
  • The response header doesn’t contain Last-Modified (this often indicates that the resource requested is dynamic).

The age of the cache for a given file will depend on the file type and the value of the Last-Modified header. The less frequently the file gets modified, the longer the file gets cached. You can override the default behavior by configuring Cache-Control and the CDN will try its best to follow your configurations. For example:

  • You can use Cache-Control: no-cache to prevent the response from being cached.
  • You can use Cache-Control: max-age=3600 to specify the age of the cache (here we set it to be 1 hour).

To prevent your application from being affected by the caching mechanism, consider enabling dedicated IP. You can learn more about the differences between CDN and dedicated IP on Binding Your Domains § Cloud Engine Domains.


The server side uses Beijing Time (UTC+8).