原创

uniapp加载环境变量

温馨提示:
本文最后更新于 2023年08月28日,已超过 315 天没有更新。若文章内的图片失效(无法正常加载),请留言反馈或直接联系我

一、环境变量与编译方式

1.CLI编译

也就是:vue-cli-service的打包方式
我的理解:内核还是webpack,但是额外增加了一些处理,尤其是环境变量的处理。
注意:vue-cli-service只有三种环境,我之前以为可以自定义,其实不可以。
参考官方文档:https://cli.vuejs.org/zh/guide/mode-and-env.html#环境变量
这里明确说了:
想要了解解析环境文件规则的细节,请参考 dotenv。
vue-cli-service使用dotenv解析.env文件之后,使用@vue/cli-service/lib/util/resolveClientEnv.js

复制代码const prefixRE = /^VUE_APP_/  

module.exports = function resolveClientEnv (options, raw) {  
  const env = {}  
  Object.keys(process.env).forEach(key => {  
    if (prefixRE.test(key) || key === 'NODE_ENV') {  
      env[key] = process.env[key]  
    }  
  })  
  env.BASE_URL = options.publicPath  

  if (raw) {  
    return env  
  }  

  for (const key in env) {  
    env[key] = JSON.stringify(env[key])  
  }  
  return {  
    'process.env': env  
  }  
}  

过滤了一部分key,不是APP_VUE*这个开头的全局变量就会被过滤掉,此外还保留了NODE_ENV

通常来说,我们都是在项目的根目录下面执行vue-cli-service,所以默认的环境变量文件.env也是在根目录下面。

2.HBuilderX编译

HBuilderX的编译时,也是使用的webpack。但是HBuilderX的编译,是没有处理根目录下的.env文件的。

二、解决方案

1.使HBuilderX也能自动加载.env文件

在根目录下的vue.config.js(如果没有就创建一个)

复制代码const webpack = require('webpack')  
const dotenv = require('dotenv')  

module.exports = {  
  chainWebpack: config => {  
    config  
      .plugin('define')  
      .tap(args => {  
        //console.log(args)  

        const config = getEnvsByDot()  
        //console.log(config)  
        // 将自定义的环境变量塞入配置中  
                //这里有个格式转化时的字符串的坑  
        //'"http://127.0.0.1:8088/"' //这种没问题  
        //'http://127.0.0.1:8088/' //这种就报错了!  
        Object.keys(config).forEach(key => {  
            if(typeof config[key] == "string"){  
                config[key] = '"'+config[key]+'"'  
            }  
            args[0]['process.env'][key] = config[key]  

        })  
        //args[0]['process.env'] = Object.assign(args[0]['process.env'],config)  
        console.log(args)  
        return args  
      })  
  }  
}  

/**  
 * 从.env中获取  
 * 使用了dotenv依赖  
 * 模仿vue-cli-service,不是APP_VUE*这个开头的全局变量就会被过滤掉  
 */  
function getEnvsByDot(){  
    const prefixRE = /^VUE_APP_/  
    let dotEnvs = {}  
    //1.先加载通用环境变量  
    const envPath0 = __dirname+'/.env'  
    const dotEnvsConfig0 = dotenv.config({path:envPath0})  
    console.log(dotEnvsConfig0)  

    if(!dotEnvsConfig0.error){  
        Object.keys(dotEnvsConfig0.parsed).forEach(key => {  
          if (prefixRE.test(key) ) {  
            dotEnvs[key] = dotEnvsConfig0.parsed[key]  
          }  
        })  
    }  
    //2.再加载专属环境变量  
    let env='local'  
    if (process.env.NODE_ENV === 'development') {  
        env='dev'  
    } else if (process.env.NODE_ENV === 'production') {  
        env='prod'  
    }else{  
        env=process.env.NODE_ENV  
    }  

    const envPath = __dirname+'/.env.'+env  
    const dotEnvsConfig = dotenv.config({path:envPath})  
    console.log(dotEnvsConfig)  
    if(!dotEnvsConfig.error){  
        Object.keys(dotEnvsConfig.parsed).forEach(key => {  
          if (prefixRE.test(key) ) {  
            dotEnvs[key] = dotEnvsConfig.parsed[key]  
          }  
        })  
    }  

    return dotEnvs  
}

当然,你也可以不过滤VUE_APP_前缀,自由的使用环境变量,自己注意不要产生与系统自带变量名的冲突就好了。
这个方法,应该足够让.env文件在HBuilderX下的使用与cli一样舒服了。但也带来一个问题,如果你这个项目同时使用cli编译的话,可能会导致.env被加载两次。当然了一般来说,由于两种方式创建的项目的文件夹结构不一样,所以可能你不会遇到既是用cli又是用HBuilderX编译的情况。

2.用yaml文件编译

其实yaml文件类型这几年在配置文件上用得挺多的,好读好写。
同样是在根目录下的vue.config.js(如果没有就创建一个)

复制代码const webpack = require('webpack')  
const YAML = require('yaml')  
const fs = require('fs')  

module.exports = {  
  chainWebpack: config => {  
    config  
      .plugin('define')  
      .tap(args => {  
        console.log(args)  

        const config = getEnvsByYaml()  
        console.log(config)  
        // 将自定义的环境变量塞入配置中  
        args[0]['process.env'] = Object.assign(args[0]['process.env'],config)  
        console.log(args)  
        return args  
      })  
  }  
}  

/**  
 * 从env文件中读取配置:  
 * 1.要获取文件绝对路径,因为相对路径是相对于编译器的,而不是项目的根目录。使用了__dirname。  
 * 2.使用了yaml格式。  
 */  
function getEnvsByYaml(){  
    //1.先加载通用环境变量  
    const prefixRE = /^VUE_APP_/  
    let yamlEnvs = {}  
    let config0 = {}  
    try{  
        const envYaml0 = fs.readFileSync(__dirname+'/.env.yaml','utf8')  
        config0 = YAML.parse(envYaml0)  
    }catch(e){  
        console.log(e)  
    }  
    // console.log(config0)  
    Object.keys(config0).forEach(key => {  
      if (prefixRE.test(key) ) {  
        yamlEnvs[key] = config0[key]  
      }  
    })  

    //2.再加载专属环境变量  
    let env='local'  
    if (process.env.NODE_ENV === 'development') {  
        env='dev'  
    } else if (process.env.NODE_ENV === 'production') {  
        env='prod'  
    }else{  
        env=process.env.NODE_ENV  
    }  

    let config = {}  
    try{  
        const envYaml = fs.readFileSync(__dirname+'/.env.'+env+'.yaml','utf8')  
        config = YAML.parse(envYaml)  
    }catch(e){  
        console.log(e)  
    }  
    // console.log(config)  
    Object.keys(config).forEach(key => {  
      if (prefixRE.test(key) ) {  
        yamlEnvs[key] = config[key]  
      }  
    })  

    return yamlEnvs  
}

3.vue2和vue3加载变量和读取变量的方式

//vue2  页面加载process.envconst dotenv = require("dotenv")const webpack = require("webpack")

module.exports = {
	chainWebpack: config => {
	    config
			.plugin('define')
			.tap(args => {
				var configs;
				if (process.env.NODE_ENV == 'development') {
					configs = dotenv.config({path:__dirname+'/.env.development'})
				} else {
					configs = dotenv.config({path:__dirname+'/.env'})
				}
				Object.keys(configs.parsed).forEach(item=>{
					args[0]['process.env'][item] = '"'+configs.parsed[item]+'"'
				})
				return args
			})
		
	}
}
//vue3   页面加载import.meta.env
import {
	defineConfig
} from 'vite';
import uni from '@dcloudio/vite-plugin-uni';
import YAML from 'yaml'
import fs from 'fs'

let buffer = fs.readFileSync(__dirname+'/config.yaml', 'utf8');
let config = YAML.parse(buffer);
let define = {}
for(let i in config['http']){
	define['import.meta.env.'+i.toUpperCase()] = JSON.stringify(config['http'][i])
}
export default defineConfig({
	plugins: [
		uni()
	],
	define: define
});
正文到此结束
该篇文章的评论功能已被站长关闭