This is the 18th day of my participation in the August Genwen Challenge.More challenges in August

In the actual project development, we often experience project development phase, testing phase, and finally the online stage, each stage may be different to the requirement of the project code, so how we can function under the different stages to make our project present different effect, use different functions? This is where the concept of environment comes in. Schemas and environment variables are described in the official documentation

Generally, a project will have the following three environments:

  • Development environment (development phase, local development version, usually with some debugging tools or additional accessibility);
  • Test environment (during the test phase, the pre-launch version, except for some bug fixes, will not be very different from the launch version);
  • Production environment (during the launch stage, the version officially released will be optimized and the error report will be turned off);

As a developer, we may need to write some different code for each environment and make sure that the code runs in the right environment. How can we determine the project environment in the code and execute different code simultaneously? This requires proper environment configuration and management.

1. Configuration file

Correctly configuring the environment first requires us to understand the relationship between different environment configurations, as shown in the figure:

We can see from the figure above that each environment has a different configuration, and they also have an intersection, which is the configuration item that they all share. So how should we deal with this in Vue?

We can create the following files in the root directory to configure variables in different environments:

Env. Local # is loaded in all environments, but will be ignored by Git. Env.[mode] # is only loaded in specified modes, such as: . Env. Development. The env. Production. The env. [mode]. Local # only in the specified mode is loaded, but will be git is ignoredCopy the code

For example, create a file named.env.development that indicates that it will only be loaded in the development environment. In this file, we can configure variables for the following key-value pairs:

Configure the development environment
NODE_ENV=development
VUE_APP_API_BASE_URL=https://www.baidu.com/
Copy the code

How do I access these variables in vue.config.js? Use process.env.[name] for access.

// vue.config.js
console.log(process.env.NODE_ENV); // development (output in terminal)
Copy the code

When you run the NPM run serve command, the output is development, because the default setting environment of vue-cli-service serve command is development. If we need to change it, we can use the serve script in package.json as follows:

// package.json
"scripts": {
  "serve": "vue-cli-service serve --mode stage",},Copy the code

— Mode stage changes the mode configuration item in Webpack 4 to stage and reads the corresponding.env.[model] file. If no configuration file is found, the default environment development will be used, and the default environment production will be used for vue-cli-service build.

If you create another.env file, configure the same variable again, but with different values.

# Environment configuration
NODE_ENV=ENV
VUE_APP_API_BASE_URL=http://www.soso.com/
Copy the code

Since the.env file will be loaded by all environments, i.e., the common configuration, what will be printed when you run vue-cli-service serve?

The answer is development.

But if the.env.development.local file is configured as the top one, the answer is env.

So.env.[mode]. Local overrides the same configuration as.env.[mode].

Env. Local overrides the same configuration under. Env.

Env.[mode].local >.env.[mode] >.env.local >.env In addition to the same configuration items with heavy weight and cover small, different configuration items will be merged, similar to the Javascript object. assign usage.

2. Environment injection

By creating the configuration file above, we have successfully set up the project environment using the command line and can switch freely, but note that the process.env printed in Vue front-end code may not be the same as the output in vue.config.js. Webpack injects process.env into client code via the built-in plug-in DefinePlugin.

/ / webpack configuration{...plugins: [
        new webpack.DefinePlugin({
            'process.env': {
                NODE_ENV: JSON.stringify(process.env.NODE_ENV)
            }
        }),
    ], 
    ...
}
Copy the code

Since this is already done for us in the Vue-CLI 3.x wrapped Webpack configuration, it is possible to print the value of process.env directly in the client code. This object can contain multiple key-value pairs, meaning that multiple values can be injected. However, after vuE-CLI encapsulation, only variables starting with VUE_APP_ in the environment configuration file can be injected, excluding NODE_ENV and BASE_URL.

For example, in the most heavily weighted.env.development.local file, write:

Configure the development environment
NODE_ENV=developmentLocal
VUE_APP_API_BASE_URL=https://www.baidu.com/
NAME=javaScript
Copy the code

Then we try to print process.env in vue.config.js, with the terminal output:

{...npm_config_ignore_scripts: ' '.npm_config_version_git_sign: ' '.npm_config_ignore_optional: ' '.npm_config_init_version: '1.0.0'.npm_package_dependencies_vue_router: '^ 3.0.1'.npm_config_version_tag_prefix: 'v'.npm_node_execpath: '/usr/local/bin/node'.NODE_ENV: 'developmentLocal'.VUE_APP_API_BASE_URL: 'https://www.baidu.com/'.NAME: 'javaScript'.BABEL_ENV: 'development'. }Copy the code

You can see that the output contains a lot of NPM information in addition to the variables in the environment configuration, but printing in the entry file main.js will find the output:

{
  BASE_URL: "/".NODE_ENV: "developmentLocal".VUE_APP_API_BASE_URL: "https://www.baidu.com/",}Copy the code

The extra BASE_URL is the value you set in vue.config.js. The default value is /, which is invalid in the environment configuration file.

3. Perform additional configurations

Above, we can configure different variable values for different project environments by creating configuration files, which can realize the basic environment management of the project. However, parameters in configuration files such as. Env only support static values, and cannot use dynamic parameters, which cannot realize specific requirements in some cases. You can create a config folder under the root directory to store additional configuration files.

/* Config file index.js */
 
// Public variables
const com = {
  IP: JSON.stringify('xxx')};module.exports = {
  // Development environment variables
  dev: {
    env: {
      TYPE: JSON.stringify('dev'),
      ...com
    }
  },
  // Production environment variables
  build: {
    env: {
      TYPE: JSON.stringify('prod'),
      ...com
    }
  }
}
Copy the code

The above code divides environment variables into public variables, development variables, and production variables, although these variables may be dynamic, such as the user’s IP address. Now we need to inject these variables into vue.config.js and modify the values in DefinePlugin using chainWebpack:

/* vue.config.js */
const configs = require('./config');
 
// Merge
const merge = require('webpack-merge');
 
// Determine which configuration to use based on the environment
const cfg = process.env.NODE_ENV === 'production' ? configs.build.env : configs.dev.env;
module.exports = {
  chainWebpack: config= > {
    config.plugin('define').tap(args= > {
      let name = 'process.env';
      // Use merge to keep the original values unchanged
      args[0][name] = merge(args[0][name], cfg);
      return args
    })
  },	
}
Copy the code

Finally, an object containing dynamic configuration can be successfully printed on the client side:

{
  BASE_URL: "/".IP: "xxx".NODE_ENV: "developmentLocal".TYPE: "dev".VUE_APP_API_BASE_URL: "https://www.baidu.com/",}Copy the code

4. Actual scenario

Use process.env.xxx to access properties

<script>
export default {
  data() { 
    return {
      BASEURL:process.env,
    } 
  },  
  mounted(){
 	console.log(this.BASEURL.VUE_APP_API_BASE_URL) // https://www.baidu.com/
  }
}
</script> 
Copy the code
// Create an axios instance
const service = axios.create({
  baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
  timeout: 5000
})
Copy the code

conclusion

The configuration and management of the environment plays a crucial role in the construction of the project. By configuring different environments for the project, we can not only increase the flexibility of development and improve the extensibility of the program, but also help us to understand and analyze the operation mechanism of the project in different environments and establish a global concept.