Personally, I think Vben Admin is a good project, complete and well-documented, and the technology stack is always up to date. When I was following through with the documentation, I didn’t immediately use it because I didn’t understand a lot of things.
Of course, it is also necessary to use it after all understanding it. After all, it is much better to use it and watch it. The guide part of the document on how to use it is very clear and the source code is highly encapsulated, and this part is often the need to modify according to the actual business, so I decided to take a look at this part of the source code before using.
- Vben Admin in-depth understanding of routing, menu, permission design
Doubt point
This section focuses on the handling of environment variables and how to use a Vite plug-in.
In Vite only variables starting with VITE_ are embedded in client-side packages. A new variable whose rule starts with VITE_GLOB_ will be added to _app.config.js when packing.
- So what transformations and extensions have been done to the environment variables?
- then
_app.config.js
How is it generated and written?
Parse the environment variable file
Start with the viet.config. ts entry.
Use loadEnv to read the corresponding environment configuration file (.env +.env.[mode] +.env.[mode].local), which can be used in the subsequent configuration. Load mode details environment variables and modes.
// vite.config.ts
import { loadEnv } from 'vite';
import { wrapperEnv } from './build/utils';
export default ({ command, mode }: ConfigEnv): UserConfig= > {
const root = process.cwd();
// Load environment variables for the corresponding schema
const env = loadEnv(mode, root);
// Parse the values of environment variables
const viteEnv = wrapperEnv(env);
};
};
Copy the code
Use wrapperEnv to further process the read content.
// build/utils.ts
export function wrapperEnv(envConf: Recordable) :ViteEnv {
const ret: any = {};
for (const envName of Object.keys(envConf)) {
let realName = envConf[envName].replace(/\\n/g."\n");
// Convert Boolean values
realName = realName === "true" ? true : realName === "false" ? false : realName;
// Convert port configuration
if (envName === "VITE_PORT") {
realName = Number(realName);
}
// Transform proxy configuration
if (envName === "VITE_PROXY") {
try {
realName = JSON.parse(realName);
} catch (error) {}
}
ret[envName] = realName;
// Why do I assign to process.env? What's the use of that?
if (typeof realName === "string") {
process.env[envName] = realName;
} else if (typeof realName === "object") {
process.env[envName] = JSON.stringify(realName); }}return ret;
}
Copy the code
Then pass the parsed viteEnv into the plug-in list for use.
// vite.config.ts
export default ({ command, mode }: ConfigEnv): UserConfig= > {
const viteEnv = wrapperEnv(env);
return {
plugins: createVitePlugins(viteEnv, isBuild)
};
};
Copy the code
How is _app.config.js generated
After the search logic, a script is executed using ESno to generate the build.
"build": "cross-env NODE_ENV=production vite build && esno ./build/script/postBuild.ts"
Copy the code
The main function is to parse the environment variable file and write the contents to the file.
// build/script/buildConf.ts
function createConfig({ configName, config, configFileName = GLOB_CONFIG_FILE_NAME }) {
try {
// File contents
const windowConf = `window.${configName}`;
const configStr = `${windowConf}=The ${JSON.stringify(config)};
Object.freeze(${windowConf});
Object.defineProperty(window, "${configName}", {
configurable: false,
writable: false,
});
`.replace(/\s/g."");
fs.mkdirp(getRootPath(OUTPUT_DIR));
// Generate the file
writeFileSync(getRootPath(`${OUTPUT_DIR}/${configFileName}`), configStr);
} catch (error) {
console.log(chalk.red("configuration file configuration file failed to package:\n"+ error)); }}export function runBuildConfig() {
// Get the values starting with VITE_GLOB_ in the environment variable configuration file, which are resolved by Dotenv like Vite
const config = getEnvConfig();
// Get the variable configuration name '__PRODUCTION__${env.vite_glob_app_short_name}__CONF__'
const configFileName = getConfigFileName(config);
// Generate code and write to file
createConfig({ config, configName: configFileName });
}
Copy the code
Finally, _app.config.js is introduced in index. HTML, where the use of viet-plugin-html is also written by the Vben authors themselves.
Plugins are centrally managed in build/vite/plugin, and after configuration are processed, the array is returned and configured to vite plugins.
// build/vite/plugin/html.ts
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}/ `;
// Get the path configuration
const getAppConfigSrc = () = > {
return `${path || "/"}${GLOB_CONFIG_FILE_NAME}? v=${pkg.version}-The ${new Date().getTime()}`;
};
const htmlPlugin: Plugin[] = html({
minify: isBuild,
inject: {
data: {
title: VITE_GLOB_APP_TITLE
},
// Build mode imports the app.config.js file
tags: isBuild ? [{tag: "script".attrs: {
src: getAppConfigSrc()
}
}
]
: []
}
});
return htmlPlugin;
}
Copy the code
Use of environment variables
First of all, we can still use the method provided by Vite.
import.meta.env.VITE_XXX;
Copy the code
According to the documentation, useGlobSetting is used to obtain the dynamic configuration.
// src/hooks/setting/index.ts
export const useGlobSetting = () = > {
const { VITE_GLOB_APP_TITLE } = getAppEnvConfig(); // The production environment is dynamically configured
const glob = {
title: VITE_GLOB_APP_TITLE
};
return glob;
};
Copy the code
Implementation of dynamic configuration in production environment.
// src/utils/env.ts
export function getAppEnvConfig() {
// Get the alias of the configuration
const ENV_NAME = getConfigFileName(import.meta.env);
// In the case of development, the development environment is retrieved from the environment variable
// If the production environment gets (_app.config.js) from the window property
const ENV = import.meta.env.DEV ? import.meta.env : window[ENV_NAME];
const { VITE_GLOB_APP_TITLE } = ENV;
return {
VITE_GLOB_APP_TITLE
};
}
Copy the code
conclusion
We know what and how Vben Admin does when we configure an environment variable. This way we can do whatever we want if we have problems or add new plugin logic.