第五十章-Vben动态配置环境变量

1.说明

前面章节中,我们在build\vite\plugin中注释一段index.html中插入的script段。这一段script是用于Vben的动态配置环境变量的。

当你打包完项目之后,你的项目的环境变量就不可以变了。此时如果你想修改一下项目的基础API路径,那么你需要修改.env文件,然后再次打包一遍。这么做很麻烦。所以VbenAdmin将环境变量抽离出来。

当你的项目打包完成之后,如果你还想修改环境变量,那么可以直接修改dist包下的_app.config.js文件。

下面看实现。

2.安装fs-extra

yarn add fs-extra @types/fs-extra --dev

fs-extra的npm首页fs-extra添加本机fs模块中未包含的文件系统方法。

3.编写生成配置文件的程序

Node-Api-fs

build\script\buildConf.ts

/**
 * Generate additional configuration files when used for packaging. The file can be configured with some global variables, so that it can be changed directly externally without repackaging
 */
import { GLOB_CONFIG_FILE_NAME, OUTPUT_DIR } from '../constant';
import fs, { writeFileSync } from 'fs-extra';
import chalk from 'chalk';

import { getRootPath, getEnvConfig } from '../utils';
import { getConfigFileName } from '../getConfigFileName';

import pkg from '../../package.json';

function createConfig(
  {
    // ↓windows对象下的存储配置的属性名
    configName,
    // ↓存储配置的对象
    config,
    // ↓JS文件名
    configFileName = GLOB_CONFIG_FILE_NAME,
  }: { configName: string; config: any; configFileName?: string } = { configName: '', config: {} }
) {
  try {
    // ↓变量字符串
    const windowConf = `window.${configName}`;
    // Ensure that the variable will not be modified
    // ↓将配置的对象以JSON字符串格式拼接到变量字符串后面,最后用正则将空格去掉
    const configStr = `${windowConf}=${JSON.stringify(config)};
      Object.freeze(${windowConf});
      Object.defineProperty(window, "${configName}", {
        configurable: false,
        writable: false,
      });
    `.replace(/\s/g, '');
    // ↓创建dist文件夹
    fs.mkdirp(getRootPath(OUTPUT_DIR));
    // ↓将字符串写入到dist文件下的指定JS文件名的文件中
    writeFileSync(getRootPath(`${OUTPUT_DIR}/${configFileName}`), configStr);

    console.log(chalk.cyan(`✨ [${pkg.name}]`) + ` - configuration file is build successfully:`);
    console.log(chalk.gray(OUTPUT_DIR + '/' + chalk.green(configFileName)) + '\n');
  } catch (error) {
    console.log(chalk.red('configuration file configuration file failed to package:\n' + error));
  }
}

export function runBuildConfig() {
  // ↓获取我们可以配置的环境变量对象
  const config = getEnvConfig();
  // ↓获取配置文件的JS名
  const configFileName = getConfigFileName(config);
  // ↓创建文件
  createConfig({ config, configName: configFileName });
}

4.安装yargs

yargs的npm首页:读取你执行的命令行命令中的参数选项。

yarn add yargs --dev
yarn add @types/yargs --dev

5.编写脚本触发文件

chalk的npm首页:一个彩色console.log的工具,这个依赖被其他依赖作为生产依赖安装在本项目中了,所以也不去猜是哪个依赖的了,直接使用。

build\script\postBuild.ts

// #!/usr/bin/env node

import { argv } from 'yargs';
import { runBuildConfig } from './buildConf';
import chalk from 'chalk';

import pkg from '../../package.json';

// ↓定义创建配置文件的方法,最条件判断
export const runBuild = async () => {
  try {
    // 获取命令中不以'-'开头的参数
    const argvList = argv._;

    // Generate configuration file
    // ↓如果参数中包含'no-conf',那么就不创建配置文件
    if (!argvList.includes('no-conf')) {
      // ↓同步创建配置文件
      await runBuildConfig();
    }

    console.log(`✨ ${chalk.cyan(`[${pkg.name}]`)}` + ' - build successfully!');
  } catch (error) {
    console.log(chalk.red('vite build error:\n' + error));
    process.exit(1);
  }
};

// ↓执行方法
runBuild();

6.安装esno

esno的npm首页:命令行执行一个TS文件

yarn add esno --dev

7.编写脚本

在编译的时候调用TS文件:

package.json

{
  "scripts": {
    // ...
    "build": "vite build && esno ./build/script/postBuild.ts",
    "build-noconf": "vite build && esno ./build/script/postBuild.ts no-conf"
  }
}

8.index.html注入配置文件

build\vite\plugin\html.ts

/**
 * Plugin to minimize and use ejs template syntax in index.html.
 * https://github.com/anncwb/vite-plugin-html
 */
import type { Plugin } from 'vite';
import type { ViteEnv } from '../../utils';

import html from 'vite-plugin-html';

import pkg from '../../../package.json';
import { GLOB_CONFIG_FILE_NAME } from '../../constant';

export function configHtmlPlugin(env: ViteEnv, isBuild: boolean) {
  const { VITE_GLOB_APP_TITLE, VITE_PUBLIC_PATH } = env;

  const path = VITE_PUBLIC_PATH.endsWith('/') ? VITE_PUBLIC_PATH : `${VITE_PUBLIC_PATH}/`;

  const getAppConfigSrc = () => {
    return `${path || '/'}${GLOB_CONFIG_FILE_NAME}?v=${pkg.version}-${new Date().getTime()}`;
  };

  const htmlPlugin: Plugin[] = html({
    minify: isBuild,
    inject: {
      // Inject data into ejs template
      injectData: {
        title: VITE_GLOB_APP_TITLE,
      },
      // Embed the generated app.config.js file
      // ↓在此处插入
      tags: isBuild
        ? [
            {
              tag: 'script',
              attrs: {
                src: getAppConfigSrc(),
              },
            },
          ]
        : [],
    },
  });
  return htmlPlugin;
}

9.注意

之后在业务逻辑中获取环境变量,就需要从这个JS文件中获取了。从而达到在生产环境改配置的需求。

参考:src\utils\env.ts,但是这个后面再说。

上一章

第四十九章-Vben的获取配置文件名的方法

下一章

第五十一章-vite插件-vite-plugin-svg-icon

# vben 

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×