Rsbuild supports injecting env variables or expressions into the code during build, which is helpful for distinguishing the running environment or replacing constants.
This chapter introduces how to use env variables in Rsbuild.
Rsbuild by default injects the some env variables into the code using source.define. These will be replaced with specified values during the build:
import.meta.env
contains these env variables:
process.env
contains these env variables:
You can use import.meta.env.MODE
in the client code to read the value of the mode configuration.
In development mode, the above code will be compiled to:
In production mode, the above code will be compiled to:
During code minification, if (false) { ... }
will be recognized as invalid code and removed automatically.
If mode is 'development'
, the value is true
; otherwise, it is false
.
If mode is 'production'
, the value is true
; otherwise, it is false
.
You can use import.meta.env.BASE_URL
in the client code to access the server's base path, which is determined by the server.base configuration, which is helpful for referencing public folder assets in the code.
For example, we set the base path of the server to /foo
through server.base configuration:
Then, the access URL to the favicon.ico
file in the public directory is http://localhost:3000/foo/favicon.ico
. You can use import.meta.env.BASE_URL
to concatenate the URL in JS files:
You can use import.meta.env.ASSET_PREFIX
in the client code to access the URL prefix of static assets.
assetPrefix
to make string concatenation easier.For example, we copy the static/icon.png
image to the dist
directory through output.copy configuration:
Then we can access the image URL in the client code:
In development mode, the above code will be compiled to:
In production mode, the above code will be compiled to:
Rsbuild also allows using process.env.BASE_URL
, which is an alias of import.meta.env.BASE_URL.
For example, in the HTML template, you can use process.env.BASE_URL
to concatenate the URL:
Rsbuild also allows using process.env.ASSET_PREFIX
, which is an alias of import.meta.env.ASSET_PREFIX.
For example, in the HTML template, you can use process.env.ASSET_PREFIX
to concatenate the URL:
By default, Rsbuild will automatically set the process.env.NODE_ENV
environment variable to 'development'
in development mode and 'production'
in production mode.
You can use process.env.NODE_ENV
directly in Node.js and in the client code.
In development mode, the above code will be compiled to:
In production mode, the above code will be compiled to:
During code minification, if (false) { ... }
will be recognized as invalid code and removed automatically.
.env
FileWhen a .env
file exists in the project root directory, Rsbuild CLI will automatically use dotenv to load these env variables and add them to the current Node.js process.
You can access these env variables through import.meta.env.[name]
or process.env.[name]
.
Rsbuild supports reading the following types of env files:
File Name | Description |
---|---|
.env |
Loaded by default in all scenarios. |
.env.local |
Local usage of the .env file, should be added to .gitignore. |
.env.development |
Read when process.env.NODE_ENV is 'development' . |
.env.production |
Read when process.env.NODE_ENV is 'production' . |
.env.development.local |
Local usage of the .env.development file, should be added to .gitignore. |
.env.production.local |
Local usage of the .env.production file, should be added to .gitignore. |
If several of the above files exist at the same time, they will all be loaded, with the files listed at the bottom of the table having higher priority.
Rsbuild also supports reading .env.[mode]
and .env.[mode].local
files. You can specify the env mode using the --env-mode <mode>
flag.
For example, set the env mode as test
:
Rsbuild will then read the following files in sequence:
The --env-mode
option takes precedence over process.env.NODE_ENV
.
It is recommended to use --env-mode
to set the env mode, and not to modify process.env.NODE_ENV
.
By default, the .env
file is located in the root directory of the project. You can specify the env directory by using the --env-dir <dir>
option in the CLI.
For example, to specify the env directory as config
:
In this case, Rsbuild will read the ./config/.env
and other env files.
For example, create a .env
file and add the following contents:
Then in the rsbuild.config.ts
file, you can access the above env variables using import.meta.env.[name]
or process.env.[name]
:
Now, create a .env.local
file and add the following contents:
The value of BAR
is overwritten to '2'
:
All env variables starting with PUBLIC_
can be accessed in client code. For example, if the following variables are defined:
In the client code, you can access these env variables through import.meta.env.PUBLIC_*
or process.env.PUBLIC_*
. Rsbuild will match the identifiers and replace them with the corresponding values.
Public variables will replace identifiers in the client code, with the replacement scope including:
.js
, .ts
, .tsx
, etc.Note that public variables will not replace identifiers in the following files:
.css
, .scss
, .less
, etc.For example, when migrating a Create React App project to Rsbuild, you can read env variables starting with REACT_APP_
and inject them through the source.define config as follows:
By using source.define, you can replace global identifiers with some expressions or values in compile time.
define
is similar to the macro definition capabilities provided by other languages. It is often used to inject env variables and other information to the code during build time.
The most basic use case for define
is to replace global identifiers in compile time.
The value of the environment variable NODE_ENV
will change the behavior of many vendor packages. Usually, we need to set it to production
.
Note that the value provided here must be a JSON string, e.g. process.env.NODE_ENV
with a value of "production"
should be passed in as "\"production\""
to be processed correctly.
Similarly { foo: "bar" }
should be converted to "{\"foo\":\"bar\"}"
, which if passed directly into the original object would mean replacing the identifier process.env.NODE_ENV.foo
with the identifier bar
.
For more about source.define
, just refer to API References.
The environment variable NODE_ENV
shown in the example above is already injected by the Rsbuild, and you usually do not need to configure it manually.
Note that source.define
can only match complete global identifiers. You can think of it as a text replacement process.
If the identifier in the code does not exactly match the key defined in define
, Rsbuild will not be able to replace it.
When using source.define
, please avoid replacing the entire process.env
object, e.g. the following usage is not recommended:
If the above usage is adopted, the following problems will be caused:
process.env
code will be replaced by a complete environment variable object, the bundle size of the front-end code will increase and the performance will decrease.Therefore, please inject the env variables on process.env
according to actual needs and avoid replacing them in its entirety.
When you access an environment variable in a TypeScript file, TypeScript may prompt that the variable lacks a type definition, and you need to add the corresponding type declaration.
For example, if you reference a PUBLIC_FOO
variable, the following prompt will appear in the TypeScript file:
To fix this, you can create a src/env.d.ts
file in your project and add the following content:
You can extend the type of import.meta.env
like this:
If the type for process.env
is missing, please install the dependency @types/node:
Then extend the type of process.env
:
define
can also be used to mark dead code to assist the Rspack with tree shaking optimization.
Build artifacts for different languages is achieved by replacing import.meta.env.LANGUAGE
with a specific value, for example.
For an internationalized code:
Specifying the environment variable LANGUAGE=zh
and then running build will eliminate the dead code.
Unused components will not be bundled, and their dependencies will be removed accordingly, resulting in smaller build outputs.