Front-end environment variables and local environment configuration practice in vite

Preface

The front end did not have the concept of engineering before, and even the development environment, test environment, and production environment were all manually configured by everyone.

With nodejs, the concept of environment variables has slowly entered the front-end field of view, which facilitates the automated configuration of various front-end environments and the operation of local environments. Nowadays, packaging tools such as webpack, rollup, and vite are very popular, and we have to pay attention to them. In the entire link of modern front-end development, environment variables serve as the configuration hub of a project and are also an important part of improving front-end efficiency. Today, we will analyze step by step the usage scenarios of environment variables in the front-end and how environment variables play a role in the front-end environment.

1. cross-env configures environment variables,

"build": "cross-env NODE_ENV=production webpack --config build/webpack.config.js"

You often see this kind of code, where cross-env NODE_ENV=production, the specified environment variable key is NODE_ENV, and the value is production. After calling this, we can get the corresponding environment variable through process.env.NODE_ENV.

process is a process environment of node, in which the environment variables in the process environment can be obtained through process.env, which facilitates node to process various environmental information when calling.

This is the most basic way to configure environment variables. There are basically only two commonly used NODE_ENVs, development and production, which are used to distinguish development and production.

2. First look at the script part of pageage.json.

"scripts": {

    "dev": "vite",

    "build": "tsc && vite build",

    "preview": "vite preview"

  },

When we execute npm run dev, NODE_ENV will automatically change to develop. Why can it be set automatically? Only by understanding the essence of the matter can we use various commands more confidently and boldly. To know why it is executed like this, we first need to know what the vite method executed by npm run dev does, and then we will dig out the source code step by step. First find the folder vite.

First of all, we need to know that when executing npm run, the scripts object in the current directory will be automatically found. For example, if we npm run dev, we will find the dev instruction under scripts under package.json. I believe some students may have tried to execute vite directly in the current directory, and then got this:

Or you may have this question, why npm run dev executes the dev under the script to trigger the execution of vite, but we can't execute it directly? This is because executing vite in the interface must be installed globally. If you want to use it without global installation, use scripts to execute it, and scripts will find the corresponding folder under the current node_modules by default, such as vite. After finding the corresponding vite folder, it will search for the executable file corresponding to bin under the corresponding package.json, like vite as follows:

Then following the above question, why is there the default development environment variable? The source code in vite is as follows:

It will have a default value. If not set, it will default to development.

When vite builds, production will be passed in by default, so it becomes production.

 So in vite, when the two instructions vite and vite build are executed, the value of the environment variable NODE_ENV defaults to development and production.

3. Introduced the configuration of environment variables and default environment variables in Vite. Below we use the Vite packaging tool for actual implementation. In actual project development, we will distinguish multiple environments. For our own projects, there will be development , test, grayscale, production. The development environment is divided into development 1, development 2, development 3, development 4, and the testing is divided into test 1 and so on.

3.1 The most trouble-free approach to common basic projects

import { defineConfig } from "vite";

import react from "@vitejs/plugin-react";

import * as path from "path";

const target = "https://dev1.advai.cn”;

export default defineConfig(({ command, mode }) => {

  return {

    plugins: [react()],

    server: {

      host: "0.0.0.0",

      proxy: {

        "/api/dashboard": {

          target,

          changeOrigin: true,

          secure: false,

          xfwd: false,

        },

      },

    },

    base: mode === "production" ? "./" : "",

    resolve: {

      alias: {

        "@": path.resolve(__dirname, "./src"),

      },

    },

  };

});

The advantage of this solution is that it can be understood at a glance. The disadvantage is that if you change the address, the code will be uploaded and other people's local addresses will be overwritten.

When we need to distinguish multiple environments locally, this solution will not work. Therefore, various construction tools provide the configuration and use of environment variables. Here we focus on the use of vite and why vite can be used in this way. Only by knowing yourself and the enemy can you use it. Better, more fun.

Let’s look at our previous script case again,

"scripts": {

    "dev": "vite",

    "build": "tsc && vite build",

    "preview": "vite preview"

},

When executing vite, an environment variable called NODE_ENV will be automatically planted to distinguish our current environment.

Well, in fact, the various environments of our local request backend can also be set through environment variables. We can add two files .env.development and .env.development.local to the root directory.

Among them, .env.development can contain all configuration items of each environment, which is more like a list. The approximate content is as follows:

# dev1

# VITE_TARGET=https://dev1.advai.cn

# dev2

#VITE_TARGET=https://dev2.advai.cn

 # prod

VITE_TARGET=https://prod.advai.cn

The .env.development.local file contains the specific backend environment to be used, for example:

# dev1

VITE_TARGET=https://dev1.advai.cn

There is an advantage to this. Normally, the .env.development.local file is ignored by git ignore, so that after the code is uploaded, there will be a VITE_TARGET enabled by default.

After the configuration is completed, how do we use the environment variables?

export default defineConfig(({ command, mode }) => {

  const env = loadEnv(mode, path.resolve(process.cwd()));

  console.log('env', env);

});

At this time we can get our own environment variables.

Complete example:

import path from 'path';

import fs from 'fs';

import process from 'process';

import { defineConfig, loadEnv } from 'vite';

import legacy from '@vitejs/plugin-legacy';

import react from '@vitejs/plugin-react';

// https://vitejs.dev/config/

export default defineConfig(({ command, mode }) => {

  const env = loadEnv(mode, path.resolve(process.cwd()));

  console.log('env', env);

  return {

    plugins: [

      react(),

    ],

    server: {

      proxy: {

        '/api/service': {

          target: env.VITE_TARGET,

          changeOrigin: true,

          secure: false,

        },

      },

      host: true,

    },

  };

});

By using env.VITE_TARGET we can dynamically obtain the backend address in the local environment variable.

Some of you may think that VITE_ is a bit intrusive. Shouldn't we write TARGET directly? Let's give it a try. Let's change env.development.local to:

# dev1
TARGET=https://dev1.advai.cn

Then re-execute npm run dev and you will find that you have obtained an empty object:

why? To understand this problem, we first need to know what the loadEnv method we call is used for. It is also introduced on the official website:

loadEnv receives three parameters. The first is the name after .env, the second is the absolute path, and the third parameter is the prefix of your environment variable name. The default in Vite is VITE_. Why not pass the VITE_ environment variable? Wouldn't it be displayed? The source code is here:

vite/env.ts at 134ce6817984bad0f5fb043481502531fee9b1db · vitejs/vite · GitHub , I took out several important places:

(1). Name of the file to be captured

const envFiles = [

    /** default file */ `.env`,

    /** local file */ `.env.local`,

    /** mode file */ `.env.${mode}`,

    /** mode local file */ `.env.${mode}.local`,

  ]

Here you define the file names that Vite will capture, and the order is the priority, that is, `.env.${mode}.local` > `.env.${mode}` > `.env.local` > `.env `. The priority of the environment variables here is loaded according to the priority of the file. When there are environment variables with the same name, the value of the environment variable will be overwritten according to the priority of the file.

(2) Determine the key containing prefixes

for (const key in process.env) {

   if (prefixes.some((prefix) => key.startsWith(prefix)) &&

      env[key] === undefined) {

      env[key] = process.env[key];

   }

}

This code is written for the reason why the environment variable without VITE_ was not obtained just now, because this will determine whether the key contains the prefixes you wrote, and then load it into the env object. If you do not pass prefixes, the default is VITE_.

(3) Read the path content and return it to process.env

for (const file of envFiles) {

        const path = lookupFile(envDir, [file], { pathOnly: true, rootDir: envDir });

        if (path) {

            const parsed = dotenv.parse(fs__default.readFileSync(path), {

                debug: ((_a = process.env.DEBUG) === null || _a === void 0 ? void 0 : _a.includes('vite:dotenv')) || undefined

            });

            // let environment variables use each other

            main({

                parsed,

                // prevent process.env mutation

                ignoreProcessEnv: true

            });

            // only keys that start with prefix are exposed to client

            for (const [key, value] of Object.entries(parsed)) {

                if (prefixes.some((prefix) => key.startsWith(prefix)) &&

                    env[key] === undefined) {

                    env[key] = value;

                }

                else if (key === 'NODE_ENV' &&

                    process.env.VITE_USER_NODE_ENV === undefined) {

                    // NODE_ENV override in .env file

                    process.env.VITE_USER_NODE_ENV = value;

                }

            }

        }

    }

Traverse the envFiles file list, determine if there is a corresponding path, read the path content, take out the environment variable starting with prefix, and return it to process.env.

Some friends may ask, why do I have to create two files in the root directory? This looks very messy to me, I want to create a folder to store those env environment variables. In fact, Vite also provides configuration items for loading env files in specified directories. This is the introduction from the official website.

Finally, our vite configuration file was changed to:

export default defineConfig(({ command, mode }) => {

  const env = loadEnv(mode, path.resolve(process.cwd()));

  return {

    envDir: './env',

    plugins: [

      react(),

        ],

    server: {

      proxy: {

        '/api/iam-service': {

          target: env.VITE_TARGET,

          changeOrigin: true,

          secure: false,

        },

        '/accounts/': {

          target: env.VITE_TARGET,

          changeOrigin: true,

          secure: false,

        },

      },

      host: true,

    },

}

  });

The default directory of the environment variable is changed from the current path to the env folder under the current path:

 Contents of .env.development:

# dev1

# VITE_TARGET=https://dev1.advai.cn

# dev2

#VITE_TARGET=https://dev2.advai.cn

 # prod

VITE_TARGET=https://prod.advai.cn

Contents of .env.development.local:

# dev1

VITE_TARGET=https://dev1.advai.cn

 Don’t forget to modify .git ignore so that we can make our local environment variables only apply locally.

node_modules
.DS_Store
dist
dist-ssr
*.local
node_modules/*
.vscode/

Summary: The front-end is changing every day. From jquery at the beginning to vue, react, and angular now, it is not difficult to use it. The difficulty is to keep our pace of progress. Although the front-end is about environment variables There are not many things, but a thorough understanding of such simple things will allow us to grow gradually.

Guess you like

Origin blog.csdn.net/lizhen_software/article/details/117691685