This article is an original article, please quote the source, welcome everyone to collect and share 💐💐

Business background

In recent years, with the development of front-end engineering architecture, front-end projects can also have module capabilities such as back-end engineering. Just as the so-called “more capabilities, more responsibilities”, front-end engineering now not only needs to meet business requirements, but also with more complex environmental adaptation issues, such as:

  • The domain name requested by the API varies from environment to environment;
  • Online environment and testing environment in packaging strategy is different “, such as online to isolate sourceMap, shielding the vue | react devtools etc…” ;
  • Front-end SPA components make different logic according to different environments;

The boss wanted to put all the application end into one project, what micro front-end, UNIAPP multi-terminal solution followed… However, no matter what the solution is, there is a core point: environmental variables and multi-environment adaptation. So, today we are going to talk about how to implement a powerful multi-environment adaptation in Vite.

Service patterns in multiple environment scenarios

Let’s start by looking at what a front-end engineering architecture process looks like in a multi-environment environment.

As shown above, at project startup/build time:

  1. Environment variable injection: Generally through the command parameter mode, can be inpackage.jsonIn the configuration;
  2. Multi-mode files: Vite reads configuration files according to environment variables and extracts file parameters to distinguish features. This is also called Vite environment mode.
  3. Environment collector: simply understood as a function, the thing to do is to consolidate the second step of the characteristics of the parameters to a place and do some specific logic, then through the plug-in to generate the final parameters of the client and spit out;
  4. Customizing client environment differences: client (i.e. in the project.vue、.ts、.tsxAnd other front-end files) to obtain environmental parameters to do some specific distinction logic;
  5. Build and release: After that, the project will be packaged according to the environmental feature files produced in the above steps, and finally pushed to the server to complete the production of the whole front-end engineering.

The above is the general process, the next step will be broken down to explain how to achieve. For your understanding, the author specially opened a new GitHub project to store all the implementation code of this article, interested students can take it down to practice 🌹🌹.

Vite multi-environment scheme implementation

Multi-mode file configuration

Customize environment variables

VitethroughmultimodalTo configure the feature environment variables for different startup scenarios, you can create custom schema files as follows:This project created four modes compatible with each otherRelease, Beta, test, localEnvironment, each mode has its own specific environment variables, for example.env.localAs follows:

# .env._local
Pass through client parameters
VITE_NODE_ENV=localVITE_OWNER=Tom VITE_POSITION= Guangzhou, Tianhe# private parameters, only available from vite server,
# If your project contains such sensitive variables. Files should be added to your.gitignore to prevent them from being checked in by Git.
MODE_KEY=PRIVATE_KEY_LOCAL
Copy the code

According to Vite convention rules, only variables starting with “VITE_” are captured on the client as follows: import.meta.env.{parameter name}.

Variables that do not start with “VITE_” are private and will not be passed. Suppose your project contains such sensitive variables. Files should be added to your.gitignore to prevent them from being checked in by Git.

After the above configuration, we just need to add the corresponding startup command in package.json to let Vite get the mode to run the project:

{
  "name": "vite-mul-env-learn"."version": "0.0.0"."scripts": {
    "dev:local": "vite --mode _local"."dev:test": "vite --mode test"."build:beta": "vite build --mode beta"."build:release": "vite build --mode release"."lint": "eslint --fix --ext .js,.vue,ts src"}}Copy the code

Vite default environment variable

Vite exposes environment variables on a special import.meta.env object. Here are some built-in variables that can be used in all cases:

  • Import.meta.env. MODE: {string} MODE in which the application runs.
  • Import.meta.env. BASE_URL: {string} Basic URL for application deployment. It is determined by the Base configuration item.
  • Import.meta.env. PROD: {Boolean} Whether the application is running in the production environment.
  • import.meta.env.DEV: {Boolean} Whether the application is running in a development environment (always withimport.meta.env.PRODOn the contrary).
  • Import.meta.env. SSR: {Boolean} Whether the application is running in a server rendering environment.

In addition, DEV and PROD are determined by the DEV and build commands in package.json respectively, while SSR is determined by the middlewareMode variable set at Vite startup:

const { createServer: createViteServer } = require('vite')

const vite = await createViteServer({
    server: { middlewareMode: 'ssr'}})Copy the code

Pass through environment variables through plug-ins

In many cases, our environment variables are not just strings, but are computed twice in the Vite service, similar to computed in Vue or useMemo or useCallback in React. For non-static environment variables like this, we need to use the plugin capability to make them return to the client as well. There are many plugins.

You can provide a list of environment variable names to expose to your client code:

import { defineConfig } from 'vite'
import EnvironmentPlugin from 'vite-plugin-environment'

export default defineConfig({
  plugins: [
    EnvironmentPlugin(['API_KEY'.'DEBUG']),],})Copy the code

And then use them as:

const apiKey = process.env.API_KEY
Copy the code

On this basis, we can also make joint judgment with the mode file:

import { defineConfig, ConfigEnv, loadEnv } from 'vite';
import vue from '@vitejs/plugin-vue';
import path from 'path';
import EnvironmentPlugin from 'vite-plugin-environment';
import { fetchEnv } from './server/envUitls';

// https://vitejs.dev/config/
export default defineConfig(({ command, mode }: ConfigEnv) = > {
  const env = loadEnv(mode, __dirname);
  const { proxy } = fetchEnv(env.VITE_NODE_ENV); // Set the domain name and port

  return {
    base: '/'.plugins: [
      vue(),
      EnvironmentPlugin({
        PROXY: proxy
      })
    ]
  };
});
Copy the code

const env = loadEnv(mode, __dirname); Env._local is all non-private parameters, and the program can then calculate the final environment variables based on the mode parameters, which are returned to the client through the plug-in.

The fetchEnv method can be thought of as an environment collector, where logic can be written to unify the environment parameters.

Client environment customization

This is easy to understand, simply by specifying a method to obtain environment variables, to conditionally render the Vue or React component. Here is a demo:

<script setup lang="ts">
import { ref } from 'vue';
import { proxy } from '@/api/proxy';

interface IEnv extends ImportMetaEnv {
  VITE_NODE_ENV: string;
  VITE_OWNER: string;
  VITE_POSITION: string;
}
const viteEnv: IEnv = import.meta.env;
</script>

<template>
  <div class="app">
    <img alt="Vue logo" src="./assets/logo.png" />
    <section class="main">
      <div class="card">
        <h3>① Parameters passed in through the environment file</h3>
        <div class="tips">Note: contains only arguments starting with "VITE_"</div>
        <div>Project owner: {{viteenv.vite_owner}}</div>
        <div>{{viteenv.vite_position}}</div>
        <div>Project mode: {{viteenv.vite_node_env}}</div>
      </div>
      <div class="card">
        <h3>② Parameters passed by the environment plug-in</h3>
        <div class="tips">Note: Through the vite-plugin-environment plug-in to pass, generally for the second calculation after the parameter. If it is a static parameter value, it can be directly returned through scheme ①.</div>
        <p>Service request domain: {{proxy}}</p>
      </div>
      <div class="card">
        <h3>③ The Vite environment has built-in parameters</h3>
        <div class="tips">Note: Vite default parameters, see<a href="https://cn.vitejs.dev/guide/env-and-mode.html#env-variables"
            >Vite environment variable </a ></div>
        <p>SSR mode: {{viteenv.ssr}}</p>
        <p>Local mode or not: {{viteenv.dev}}</p>
        <p>Build mode: {{viteenv.prod}}</p>
        <p>The current startup command reads the mode: {{viteenv.mode}}</p>
        <p>Basic URL for application deployment: {{viteenv.base_URL}}</p>
      </div>
    </section>
  </div>
</template>

<style lang="less" scoped>
.app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
.main {
  display: flex;
  .card {
    margin: 10px;
    padding: 10px;
    width: 300px;
    text-align: left;
    background-color: #dbf1e7;
    font-size: 14px;
    h3 {
      margin-bottom: 0;
    }
    .tips {
      margin-bottom: 10px;
      font-size: 12px;
      color: # 898989; }}}</style>
Copy the code

rendering

Solve the business scenario thinking

In addition to the most intuitive scenarios described in the “Business background” module of this article, many high-level operations related to project engineering can also be done.

If the project construction operation is carried out on the remote server, the service API can be linked to produce different versions and different modes of build packages before the construction packaging, and even the SSR logic can be put into this piece to achieve the effect of “thousands of faces”.

conclusion

That’s the end of this article. If it was useful to you, you can support it. If you have a better opinion, please feel free to comment

Welcome everyone to pay attention to my public number “is ma Fei Ma”, play together! 🌹 🌹

All the demos in this article are specially opened a GitHub project to save, students who need to take down the practice.