In actual project development, different environment variables need to be set based on a variety of environments so that they can be used in the construction stage or the running stage. For example, it is common to determine whether the current construction environment is development or production by using process.env.node_env during construction. For example, you need to access different interface servers in your development, test, and production environments.

To simulate a real project, a minimal project structure is constructed using WebPack:

├ ─ package. Json ├ ─ SRC | └ index. The JSX ├ ─ public | └ index. The HTML ├ ─ config | └ webpack. Config. JsCopy the code

Node environment variable

The Node environment variable refers to the process.env property

What is process.env?

It is the process.env property in the Nodejs application that returns the object containing the user environment, so it cannot be used in client-side code, and therefore cannot be used in the browser environment.

// process.env(official example) {TERM: 'xterm-256color', SHELL: '/usr/local/bin/bash', USER: 'nodejscn', PATH: '~/.bin/:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin', PWD: '/Users/nodejscn', EDITOR: 'vim', SHLVL: '1', HOME: '/Users/nodejscn', LOGNAME: 'nodejscn', _: '/usr/local/bin/node' }Copy the code

Modify Node environment variables

1. Modify the package.json file

Cross-env dependencies support cross-platform configuration of environment variables.

// package.json { ... , "scripts": { "start": "npm run dev", "dev": "cross-env NODE_ENV=development AAA=123 webpack serve --config ./config/webpack.config.js", "build:test": "cross-env NODE_ENV=test webpack --config ./config/webpack.config.js", "build:pro": "cross-env NODE_ENV=production webpack --config ./config/webpack.config.js" }, ... }Copy the code

Environment variables are injected by setting variables in the package.json script, and cross-env supports setting multiple environment variables, separated by Spaces, such as NODE_ENV=development and AAA=123 in the dev script.

This allows you to retrieve the corresponding environment variables from process.env when executing NPM start.

// webpack.config.js console.log(" [process.env] ", process.env.aaa);Copy the code

Can be printed on the terminal at build time

But in theindex.jsxPrint from a file in the browser environmentprocess.envWould be an error

The reason for this is that the peocess.env is an attribute of the Node environment and cannot be retrieved by the browser environment. Let the browser environment get the required variables and we’ll talk about that later.

2. Use the. Env file

Injecting environment variables directly into a script script is not conducive to centralized management of environment variables, nor is it friendly when there are many environment variables, so you need a way to centrally manage these environment variables.

Environment variables can be loaded from the.env file to process.env using the Dotenv dependency package.

Dotenv by default loads the root. Env file to inject environment variables, requiring (‘dotenv’).config().

//webpack.config.js dotenv.config(); / / env file AAA = 123Copy the code

It can also be seen on the terminal

Dotenv multi-environment configuration

In multi-environment configuration, it is necessary to specify the. Env file corresponding to different environments, for example, now specify. Env. test as the corresponding environment variable of the test environment,.env.production as the production environment, and.env as the development environment. Then dotenv.config({path:}) is used to load the environment variables of the corresponding files.

//webpack.config.js const PROJECT_PATH = resolve(__dirname, ".. / "); const dotenvFile = resolve(PROJECT_PATH, `./.env.${process.env.NODE_ENV}`); Env file dotenv.config({path: fs.existssync (dotenvFile)? dotenvFile : resolve(PROJECT_PATH, `./.env`), }); Console. log(" [process.env] ", process.env.env);Copy the code

Process.env.node_env is used to determine the current operating environment to load the corresponding. Env file.

// package.json
"scripts": {
  "start": "npm run dev",
  "dev": "cross-env NODE_ENV=development webpack serve --config ./config/webpack.config.js",
  "build:test": "cross-env NODE_ENV=test  webpack --config ./config/webpack.config.js",
  "build:pro": "cross-env NODE_ENV=production  webpack --config ./config/webpack.config.js"
}

//.env.production
ENV=pro

//.env
ENV=dev
Copy the code

performnpm start

performnpm run build:pro

You can see that the variables of the different environments have indeed been injected successfully.

Browser environment variables

The browser environment also needs to handle some logic based on different environment variables, but it does not get process.env so it cannot be implemented in the same way as injecting Node environment variables. Browser environment variables are introduced at project build time based on the webpack.definePlugin plugin, which makes them available globally in the front-end code.

The basic way to use it is to pass in the desired variable key value pairs into DefinePlugin. Note that variable values need to be wrapped via json.stringify.

module.exports = {
  plugins: [
    new DefinePlugin({
        aaa: JSON.stringify("!!!!")
    })
  ]
}
Copy the code

After executing the script, you can get the corresponding result in index.jsx

//index.jsx console.log(" [app] ", aaa); const App = () => { return <div>app</div>; };Copy the code

Configure browser variables for multiple environments

The browser environment also needs to introduce different variables according to the project environment. We have obtained different environment variables in the Node environment before, we can create a mapping table based on this to introduce the corresponding browser environment variables according to the Node environment variables obtained during the project construction.

// webpack.config.js const define = {dev: {baseURL: "/ API /dev",}, test: {baseURL: "/api/test", }, pro: { baseURL: "/api/pro", }, }; module.exports = { new DefinePlugin({ "process.env": Object.keys(define[process.env.ENV]).reduce((env, key) => { env[key] = JSON.stringify(define[process.env.ENV][key]); return env; }, {})})}Copy the code

performnpm startYou can see the results on the browser console

performnpm run build:pro, start a server in the dist directory, and you can see the results on the browser console

In actual projects, when the interface server address is switched according to different environments, the interface address in different environments can be obtained in this way.

Configure multiple environment variables in the UMI

Umi is often used as a project framework in peacetime development. Umi uses the environment variable UMI_ENV to distinguish different environments and specify different configurations.

Specifically, UMI_ENV= XXX is injected into the script to match the corresponding config.xxx.js configuration file, and then the variables that need to be imported into the browser environment are configured in the define attribute.

For details, see the official documentation for multi-environment configuration, variables available in the code

// webpack.config.js module.exports = { ... , "scripts": { "start": "cross-env UMI_ENV=dev umi dev", "build:test": "cross-env UMI_ENV=test umi build", "build:pre": "cross-env UMI_ENV=pre umi build", "build:pro": "cross-env UMI_ENV=pro umi build", } ... , } //config.dev.js import { defineConfig } from 'umi'; export default defineConfig({ define: { 'process.env': { BASE_API: '/api/dev', }, }, });Copy the code