为什么要把环境变量生成单独的文件?
在打包时生成额外的配置文件。该文件可以配置为一些全局变量,这样就可以在外部直接更改它,而无需重新打包,比如api的请求地址需要修改时,我们不需要重新修改 env文件然后再进行构建
一.修改package.json文件build命令
{
"scripts": {
"serve": "npm run dev",
"dev": "vite",
"build": "cross-env NODE_ENV=production vite build && esno ./build/script/postBuild.js",
}
}
esno是Node.js的"增强版",可以运行TypeScript和ESM。 Node.js默认遵循CommonJS规范实现模块化语法
二 实现postBuild.js
export const runBuild = async () => {
try {
// 运行 build 命令时命令行中传入的参数
const argvList = process.argv.splice(2);
// 生成配置文件
// disabled-config 表示不构建配置文件
if (!argvList.includes('disabled-config')) {
runBuildConfig();
}
console.log(`✨ ${colors.cyan(`[${pkg.name}]`)}` + ' - build successfully!');
} catch (error) {
console.log(colors.red('vite build error:\n' + error));
process.exit(1);
}
};
runBuild();
export function runBuildConfig() {
// 获取env文件中的配置
const config = getEnvConfig();
const configFileName = getConfigFileName(config);
createConfig({ config, configName: configFileName, configFileName: "_app.config.js" });
}
获取env文件中的配置,由于env 有公用环境下,又有development,production等都当前环境的配置文件。 并且不需要VITE_PUBLIC_PATH, VITE_PORT等,在编写环境变量是提供同一前缀 必须使用VITE_ 开头。
/**
* 获取以指定前缀开头的环境变量
* @param 前缀
* @param 配置文件
*/
export function getEnvConfig(match = 'VITE_GLOB_', confFiles = getConfFiles()) {
let envConfig = {};
confFiles.forEach((item) => {
try {
// dotenv.parse 是环境变量的文件内容的引擎。它接受字符串或者Buffer,并返回一个对象,其中包含解析过的键和值。
// 具体可以查看 https://github.com/motdotla/dotenv#parsing
const env = dotenv.parse(fs.readFileSync(path.resolve(process.cwd(), item)));
envConfig = { ...envConfig, ...env };
} catch (e) {
console.error(`Error in parsing ${item}`, e);
}
});
const reg = new RegExp(`^(${match})`);
// 剔除不需要的环境变量
Object.keys(envConfig).forEach((key) => {
if (!reg.test(key)) {
Reflect.deleteProperty(envConfig, key);
}
});
return envConfig;
}
/**
* 获取当前环境下生效的配置文件名
*/
function getConfFiles() {
// 运行构建的node命令
const script = process.env.npm_lifecycle_script;
const reg = new RegExp('--mode ([a-z_\\d]+)');
const result = reg.exec(script as string) as any;
if (result) {
const mode = result[1] as string;
return ['.env', `.env.${mode}`];
}
return ['.env', '.env.production'];
}
export const getConfigFileName = (env) => {
return `__PRODUCTION__${env.VITE_GLOB_APP_SHORT_NAME || '__APP'}__CONF__`
.toUpperCase()
.replace(/\s/g, '');
}
生成文件
import pkg from '../../package.json';
import fs, { writeFileSync } from 'fs-extra';
import colors from 'picocolors';
function createConfig(params) {
const { configName, config, configFileName } = params;
try {
const windowConf = `window.${configName}`
let configStr = `${windowConf}=${JSON.stringify(config)};`
// 把属性设置为不可修改
configStr += `
Object.freeze(${windowConf});
Object.defineProperty(window, "${configName}", {
configurable: false,
writable: false,
});
`.replace(/\s/g, '')
fs.mkdir(path.resolve(process.cwd(), 'dist'));
writeFileSync(getRootPath(`dist/_app.config.js`), configStr);
console.log(colors.cyan(`✨ [${pkg.name}]`) + ` - configuration file is build successfully:`)
console.log(colors.gray('dist'+ '/' + colors.green('_app.config.js')) + '\n')
} catch (error) {
console.log(colors.red('configuration file configuration file failed to package:\n' + error))
}
}
现在文件就生成了但是构建完成的dist中的文件并没有引用 配置文件
可以使用 vite-plugin-html在构建时插入一条script
export default ({ command }) => {
const isBuild = command === 'build';
return {
//.....其他配置
plugins: [
vue(),
createHtmlPlugin({
minify: isBuild,
inject: {
data: {
title: "",
},
// Embed the generated app.config.js file
tags: isBuild
? [
{
tag: 'script',
attrs: {
src: '/_app.config.js',
},
},
]
: [],
},
}),
],
};
};
这样就能在外部生成配置文件★,°:.☆( ̄▽ ̄)/$:.°★ 。
转发请注明出处