判断不同环境区别打包并重定向至指定资源
前言,假设我们有一个PC页面,在不考虑响应式更改样式的情况下我们希望移植到手机上应该怎么做呢,我们可以使用postcss-px-to-viewport
插件去将px转换成vw,以此到达响应式的目的。但是如果是这种情况就会出现一个很尴尬的情况,因为这样代码产物就会有两套,一个是使用px单位的,一套是使用vw单位的,当然你也可以全部都使用vw作为单位。不过也可能会出现像我这样的情况——PC端不希望用vw,因为可能会导致一些别的问题出现。
一、在vite.config.js中获取参数来判断是否需要转vw
首先我们得理清思路,确定我们有什么以及需要什么这样才能决定我们需要怎么做。首先我们拥有两套代码,我们希望PC端显示的时候使用的是原本的px,在手机端使用的是vw,想做到这一步我们得使用postcss-px-to-viewport
插件去打包。当然也不是盲目的将插件导入并使用,因为我们需要根据情况来决定打包的时候是否需要该插件。
如何决定是否需要使用该插件
这里我们其实不需要判断的很复杂,因为打包成什么样是我们决定的,所以我们这里可以使用命令行参数来判断是否使用插件打包。Vite的命令行参数官网给出了示例https://cn.vitejs.dev/guide/env-and-mode#node-env-and-modes。但是我在实际使用的过程中其实是会报错的:
"demo": "NODE_ENV=development vite build",
在执行上面的脚本命令后控制台会提示错误**‘NODE_ENV’ 不是内部或外部命令,也不是可运行的程序或批处理文件。**
这里其实是因为windows的原因,
NODE_ENV=development
在windows环境下会报错,需要改为set NODE_ENV=production
,为了解决这个差异,可以使用cross-env
跨平台的设置和使用环境变量。
那这种方式不行我们换一种方式试试,该用如下命令:
vite build --custom_variable pc
这个时候会提示Unknown option --custom_variable
,说明Vite并不支持这个选项,那我们换一个选项试试
"demo": "vite build --mode pc",
这个时候就可以了,我们可以在vite.config.js
中得到这个变量
defineConfig(({ command, mode }) => {
console.log('mode',mode); // mode pc
return {
// vite 配置
};
});
但是这样的话会占用mode
属性值,一般mode是用来判断开发环境和生产环境的,如果我们需要使用该参数也不是不行,不过一般搭配.env.[mode]
文件食用更佳。
这里我单纯需要一个参数而已,不太希望写这种配置,于是我查阅了一下,大概有三种方式可以实现传参。
1.使用node的process.env变量
procss.env是node.js提供的一个变量,我们可以在这个对象上去设置属性。
"test": "set USE_MODE=pc && vite build",
这样我们就在procss.env
这个对象上设置了一个叫USE_MODE的属性。
因为这个对象是node提供的,所以这个变量只能在vite.config.js中去使用
// vite.config.js
console.log(process.env.USE_MODE); //pc
2.通过.env文件自定义环境变量
Vite内置了dotenv
库,这个库会自动读取.env文件。
.env # 所有情况下都会加载
.env.[mode] # 只在指定模式下加载
一般来说我们会有两个.env文件.env.development
和.env.production
,如果我们没有显性的去指明mode,那么在执行dev
命令时会读取.env.development
,而在build的时候会读取.env.production
文件。
如果我们要使用这些值需要用到Vite提供的 import.meta.env 对象,这个对象有五个默认值:
import.meta.env.MODE: {string} 应用运行的模式。
import. meta.env.BASE_URL: {string} 部署应用时的基本 URL。他由base配置项决定。
import. meta.env.PROD: {boolean} 应用是否运行在生产环境。
import. meta.env.DEV: {boolean} 应用是否运行在开发环境 (永远与 import.meta.env.PROD相反)。
import.meta.env.SSR: {boolean} 应用是否运行在 server 上。
我们可以在文件中去自定义环境变量
# .env.development
VITE_TEST=developData
然后我们就可以在页面中使用这个变量了
// main.js
console.log(import.meta.env.VITE_TEST) //developData
如果项目中除了上面两个文件外还有.env
文件,那么Vite也会读取.env
定义的变量,但是此时.env
的优先级较低,如果有冲突的变量名则会以当前模式的env文件定义的内容为准。
# .env.development
VITE_TEST=developData
# .env
VITE_TEST=baseData
// main.js
console.log(import.meta.env.VITE_TEST) //developData
3.使用define自定义全局变量
在Webpack和Vite中都有这种定义全局变量的设置,比如在Vite中使用的是define选项
let a = 123;
export default defineConfig({
define: {
__APP_VERSION__: JSON.stringify('v1.0.0'),
__API_URL__: 'window.__backend_api_url',
CUSTOM_DATA: JSON.stringify("test"),
CUSTOM_VALUE: a,
},
})
在使用的时候我们直接只用这个全局变量就可以了:
console.log("__CUSTOM_DATA", CUSTOM_DATA); // test
需要注意的是Vite 使用 esbuild define 来进行替换,因此值的表达式必须是一个包含 JSON 可序列化值(null、boolean、number、string、array 或 object)或单一标识符的字符串。对于非字符串值,Vite 将自动使用
JSON.stringify
将其转换为字符串。
也就是说define定义的值应该是一个表达式或者一个变量,如果直接使用字面量的值或者常量是会报错的:
export default defineConfig({
define: {
CUSTOM_DATA: "test",
},
})
// test is not defined
通过第一种和第三种方式结合,我们就可以创建一个全局都可以使用的环境变量
// vite.config.js
export default defineConfig({
define: {
NODE_ENV: JSON.stringify(process.env.USE_MODE)
},
})
// main.js
console.log("USE_MODE", USE_MODE); // pc
二、根据指令来判断是否应用plugin
在第一步我们可通过创建并使用对应的脚本指令可以在Vite打包得到一个变量来判断是否需要将px转成vw,那么我们就可以以此为根据来决定是否需要使用postcss-px-to-viewport
插件。
因为这是一个postcss
插件,所以我们在Vite(Vite3)中的css选项配置即可:
// vite.config.js
const postcssPlugins = [];
// 如果不是PC模式则我们需要将px转换成vw
if (process.env.USE_MODE !== "pc") {
const my_pxtovw = pxtovw({
unitToConvert: "px", // 要转化的单位
viewportWidth: 1920, // UI设计稿的宽度
unitPrecision: 6, // 转换后的精度,即小数点位数
propList: ["*"], // 指定转换的css属性的单位,*代表全部css属性的单位都进行转换
viewportUnit: "vw", // 指定需要转换成的视窗单位,默认vw
fontViewportUnit: "vw", // 指定字体需要转换成的视窗单位,默认vw
selectorBlackList: ["keep-px"], // 指定不转换为视窗单位的类名前缀,
minPixelValue: 1, // 默认值1,小于或等于1px则不进行转换
mediaQuery: true, // 是否在媒体查询的css代码中也进行转换,默认false
replace: true, // 是否转换后直接更换属性值
exclude: [/^node_modules(?!\/element-plus).*/], //忽略除element-plus之外的node_modules
landscape: false, // 是否处理横屏情况
});
postcssPlugins.push(my_pxtovw);
}
export default defineConfig({
plugins: [vue()],
server: {
port: 3000,
},
css: {
postcss: {
plugins: postcssPlugins,
},
},
});
该插件的使用方式可以看这个文档:postcss-px-to-viewport/README_CN.md at master · evrone/postcss-px-to-viewport · GitHub
这样我们就可以根据不同的命令来判断是否在打包的时候是否启用postcss-px-to-viewport
插件
三、根据环境判断请求地址
如果线上部署了两套代码,需要前端根据用户当前的请求环境来判断指向哪套资源,那我们就需要做一些处理。
假设项目部署地址分别为www.test.com/pc
和www.test.com/mobile
,则我们应该在页面一开始的时候就去判断应该指向什么地址,我们可以创建一个js在最开始的时候加载去判断,也可以直接在main.js去写,这里根据实际情况选择。
// main.js
function isMobile() {
return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
}
// 因为默认走的PC 所以只需要在手机端跳转即可
if (isMobile() && window.location.href.includes('pc')) {
window.location.href = 'www.test.com/mobile';
}
本文参考连接
vite中环境变量的使用与配置(非常详细) - 掘金 (juejin.cn)
NODE_ENV到底是个什么玩意?? - 简书 (jianshu.com)