网站建设会碰到什么问题,智慧服务区下载,网站建设合同有效期,网页素材大宝库现实需求
在vite开发过程中#xff0c;一些变量可以放在.env#xff08;基础公共部分变量#xff09;.env.dev#xff08;开发环境#xff09;、.env.production#xff08;生产环境#xff09;中管理#xff0c;通常分成开发和生产两个不同的配置文件管理#xff0c…现实需求
在vite开发过程中一些变量可以放在.env基础公共部分变量.env.dev开发环境、.env.production生产环境中管理通常分成开发和生产两个不同的配置文件管理方便调试和部署。但是在应用部署在若干个不同的运行环境则需要修改.env.production中的部分变量如api地址重新打包会比较麻烦。
怎么样实现不重新打包的前提下修改配置呢
答在build打包时将.env.production和.env文件统一打包成额外的配置js文件在通过外部挂载的方式做成全局变量即可。
文件结构如下
1、构建脚本的文件夹结构 程序内部调用的文件结构 前提条件 .env文件
VITE_GLOB_APP_TITLE测试平台
VITE_BASE_URL/newpath/
VITE_GLOB_APP_SHORT_NAMEGIS_APP.env.production文件
VITE_API_BASE_URL/
VITE_LOGIN_API_URLhttps://www.baidu.com/login一、新建打包脚本build.ts及依赖文件
脚本目的是在打包目录下生成_app.config.js效果如下 _app.config.js结构如下
window.__PRODUCTION__APP__CONF__ {VITE_GLOB_APP_TITLE: 测试平台,VITE_BASE_URL:/newpath/,VITE_GLOB_APP_SHORT_NAME: APP,VITE_API_BASE_URL:/,VITE_LOGIN_API_URL: https://www.baidu.com/login
};
Object.freeze(window.__PRODUCTION__APP__CONF__);
Object.defineProperty(window, __PRODUCTION__APP__CONF__, {configurable: false,writable: false,
});1、build.ts
import { runBuildConfig } from ./buildConf
import pkg from ../../package.jsonexport const runBuild async () {try {const argvList process.argv.splice(2)if (!argvList.includes(disabled-config)) {runBuildConfig()}console.log([${pkg.name}] - 构建成功!)} catch (error) {console.log(虚拟构建错误:\n error)process.exit(1)}
}
runBuild()
2、buildConf.ts文件
/*** 用于打包时生成额外的配置文件。该文件可以配置一些全局变量这样就可以直接在外部修改而无需重新打包*/
import fs, { writeFileSync } from fs-extra
import { getEnvConfig, getRootPath } from ../utils
import { getConfigFileName } from ../getConfigFileName
import pkg from ../../package.json// 打包脚本的名称
const GLOB_CONFIG_FILE_NAME _app.config.js
// 输出文件的根目录
const OUTPUT_DIR distinterface CreateConfigParams {configName: string;config: any;configFileName?: string;
}function createConfig(params: CreateConfigParams) {const { configName, config, configFileName } paramstry {const windowConf window.${configName}// 确保变量不会被修改const configStr ${windowConf}${JSON.stringify(config)};Object.freeze(${windowConf});Object.defineProperty(window, ${configName}, {configurable: false,writable: false,});.replace(/\s/g, )// 拼接新的输出根目录地址const filePath ${OUTPUT_DIR}${config.VITE_BASE_URL || /}// 创建根目录fs.mkdirp(getRootPath(filePath))writeFileSync(getRootPath(filePath configFileName), configStr)console.log(✨ [${pkg.name}] - 配置文件构建成功:)console.log(filePath \n)} catch (error) {console.log(配置文件配置文件打包失败:\n error)}
}export function runBuildConfig() {const config getEnvConfig()const configFileName getConfigFileName(config)createConfig({ config, configName: configFileName, configFileName: GLOB_CONFIG_FILE_NAME })
}3、getConfigFileName.ts文件
/*** 获取配置文件变量名* param env*/
export const getConfigFileName (env: Recordstring, any) {return __PRODUCTION__${env.VITE_GLOB_APP_SHORT_NAME || __APP}__CONF__.toUpperCase().replace(/\s/g, )
}4、utils.ts文件
import fs from fs
import path from path
import dotenv from dotenvexport function isDevFn(mode: string): boolean {return mode development
}export function isProdFn(mode: string): boolean {return mode production
}/*** 是否生成包预览*/
export function isReportMode(): boolean {return process.env.REPORT true
}/*** 读取所有环境变量配置文件到process.env* param envConf* returns*/
export function wrapperEnv(envConf: any) {const ret: any {}for (const envName of Object.keys(envConf)) {let realName envConf[envName].replace(/\\n/g, \n)realName realName true ? true : realName false ? false : realNameif (envName VITE_PORT) {realName Number(realName)}if (envName VITE_PROXY realName) {try {realName JSON.parse(realName.replace(//g, ))} catch (error) {realName }}ret[envName] realNameif (typeof realName string) {process.env[envName] realName} else if (typeof realName object) {process.env[envName] JSON.stringify(realName)}}return ret
}/*** 获取当前环境下生效的配置文件名*/
function getConfFiles() {const script process.env.npm_lifecycle_script// eslint-disable-next-line prefer-regex-literalsconst reg new RegExp(--mode ([a-z_\\d]))const result reg.exec(script as string) as anyif (result) {const mode result[1] as stringreturn [.env, .env.${mode}]}return [.env, .env.production]
}/*** 获取以指定前缀开头的环境变量* param match prefix* param confFiles ext*/
export function getEnvConfig(match VITE_, confFiles getConfFiles()) {let envConfig {}confFiles.forEach((item) {try {const env dotenv.parse(fs.readFileSync(path.resolve(process.cwd(), item)))envConfig { ...envConfig, ...env }} catch (e) {console.error(解析错误:${item}, e)}})const reg new RegExp(^(${match}))Object.keys(envConfig).forEach((key) {if (!reg.test(key)) {Reflect.deleteProperty(envConfig, key)}})return envConfig
}/*** 获取用户根目录* param dir file path*/
export function getRootPath(...dir: string[]) {return path.resolve(process.cwd(), ...dir)
}二、修改vite.config.ts文件
脚本目的是将生成_app.config.js在index.html文件中添加引用效果如下
1、安装 vite-plugin-html
yarn add vite-plugin-html -D 或
npm i vite-plugin-html -D2、vite.config.ts中引用createHtmlPlugin和package.json并添加createHtmlPlugin
import createHtmlPlugin from vite-plugin-html
import pkg from ./package.jsonconst getAppConfigSrc () {return ${ENV.VITE_BASE_URL || /}${GLOB_CONFIG_FILE_NAME}?v${pkg.version}-${new Date().getTime()}} createHtmlPlugin({minify: isBuild,inject: {data: {title: },// Embed the generated app.config.js filetags: isBuild? [{tag: script,attrs: {src: getAppConfigSrc()}}]: []}})三、代码内部引用
1、env.ts文件
import { getConfigFileName } from ../../../build/getConfigFileName
import pkg from ../../../package.jsonexport function getCommonStoragePrefix() {const { VITE_GLOB_APP_SHORT_NAME } getAppEnvConfig()return ${VITE_GLOB_APP_SHORT_NAME}__${getEnv()}.toUpperCase()
}/*** 根据版本生成缓存键* returns*/
export function getStorageShortName() {return ${getCommonStoragePrefix()}${__${pkg.version}}__.toUpperCase()
}export function getAppEnvConfig() {const ENV_NAME getConfigFileName(import.meta.env)// 根据当前运行状态判断取值如果是开发环境取.env.dev配置如果是生产环境取_app.config.js引用的全局变量 const ENV (import.meta.env.DEV ? (import.meta.env as unknown as any) : window[ENV_NAME as any]) as unknown as any// 此处可以进行过滤判断根据业务需求处理示例未做任何处理const { VITE_GLOB_APP_SHORT_NAME } ENVif (!/^[a-zA-Z\_]*$/.test(VITE_GLOB_APP_SHORT_NAME)) {console.log(VITE_GLOB_APP_SHORT_NAME变量只能是字符/下划线请在环境变量中修改后重新运行。)}return ENV
}/*** description: Development mode*/
export const devMode development/*** description: Production mode*/
export const prodMode production/*** description: Get environment variables* returns:* example:*/
export function getEnv(): string {return import.meta.env.MODE
}/*** description: Is it a development mode* returns:* example:*/
export function isDevMode(): boolean {return import.meta.env.DEV
}/*** description: Is it a production mode* returns:* example:*/
export function isProdMode(): boolean {return import.meta.env.PROD
}
2、业务调用index.ts文件
import { getAppEnvConfig } from mars/hooks/setting/envexport const useGlobSetting (): Readonlyany {const setting getAppEnvConfig()return setting
}四、修改package.json文件build命令
1、安装cross-env和esno
yarn add cross-env -D
yarn add esno -D 或
npm i cross-env -D
npm i esno -D1、修改build命令增加 esno ./build/script/postBuild.ts
build: cross-env npm run lint vite build esno ./build/script/postBuild.ts,五、测试命令
在命令行执行下面的语句可以测试生成_app.config.js文件
yarn esno ./build/script/postBuild.ts以上操作就能生成外部配置并加载了使用时在开发环境、演示环境、生产环境部署修改_app.config.js中对应的api地址即可