vue2配置-环境变量-响应式-proxy-mock
# 前言:
在vue2中大多数vue项目都是通过vue-cli 脚手架进行搭建的,那么针对vue-cli脚手架的配置及认知也是比较重要的技术点之一。
vue-cli脚手架的原理:就是一套通过webpack+vue搭建出来的一套公共的项目目录和基础配置搞定的项目
自定义常见Vue-cli配置如下:跨域代理配置proxy 全局环境变量 响应式布局postcss与rem配置 等
vue-cli 自定义配置文件介绍官网:https://cli.vuejs.org/zh/config/#vue-config-js
# 1.全局环境变量
全局环境变量常用于 package.json 的 项目启动命令配置 中进行使用
{
"scripts":{
"serve": "vue-cli-service serve",
"build": "vue-cli-service build"
}
}
2
3
4
5
6
# 1.1 环境:
vue2项目的环境一共有三种: development(开发环境) test(测试环境) production(生产环境)
你可以在你的项目根目录中放置下列文件来指定环境变量:
.env # 在所有的环境中被载入
.env.local # 在所有的环境中被载入,但会被 git 忽略
.env.[mode] # 只在指定的模式中被载入 mode:development || test || production
.env.[mode].local # 只在指定的模式中被载入,但会被 git 忽略
2
3
4
请注意,只有 NODE_ENV
,BASE_URL
和以 VUE_APP_
开头的变量将通过 webpack.DefinePlugin
静态地嵌入到客户端侧的代码中。
除了 VUE_APP_*
变量之外,在你的应用代码中始终可用的还有两个特殊的变量:
NODE_ENV
- 会是"development"
、"production"
或"test"
中的一个。具体的值取决于应用运行的模式 (opens new window)。BASE_URL
- 会和vue.config.js
中的publicPath
选项相符,即你的应用会部署到的基础路径。
# 1.2 本地环境与 线上不同的变量值 案例
.env.development
一个环境文件只包含环境变量的“键=值”对:
NODE_ENV='development'
VUE_APP_Server= 'http://localhost:8099/api'
2
.env.production
NODE_ENV='production'
VUE_APP_Server= 'http://www.gotang.cn:3000'
2
package.json
{
"scripts":{
"serve": "vue-cli-service serve --mode development",
"build": "vue-cli-service build --mode production"
}
}
2
3
4
5
6
配置好上述文件之后,使用不同的命令 就可以 拿到不同的变量值
运行 yarn serve
const url = process.env.VUE_APP_Server //http://127.0.0.1:8099/api
运行 yarn build
const url = process.env.VUE_APP_Server //http://www.gotang.cn:5000
# 2.proxy 本地代理解决跨域问题
proxy 代理主要是通过 篡改本地浏览器的访问接口时的 服务器地址前缀 达到欺骗本地浏览器的 CORS验证,绕过CORS 验证的一种方式,proxy 代理只能解决本地开发过程中,浏览器与服务器之间的跨域,上线时一般都是通过 Nginx 做反向代理实现 和proxy 相似的功能和作用
proxy 代理是 webpack的 插件 : webpack-devserve 插件的功能,所以需要覆盖部分webpack 配置
在vue-cli 项目中,webpack的配置文件被隐藏起来了,如果需要重新webpack的配置的话,vue-cli 项目提供了
vue.config.js
配置文件来重新 已经定义好的webpack 配置。
# 2.1 同源策略
浏览器为了客户端的网页安全考虑,对所有发送的ajax 请求都进行同源的限制,也就是说在浏览器中发送ajax 接口请求必须满足:客户端(前端)与服务端(后端) 是同源的才可以。
# 什么是同源?
同源即在互联网中完全相同的请求来源,特指前后端的url访问地址:
协议相同: 前后端必须一致 (都是http 或者 都是htpps)
域名/IP相同
端口号相同
# 什么是跨域?
前后端的地址只要不满足同源,就会报跨域 CORS 错误。
在互联网的世界中,目前大多数的项目都是 前后端分离项目 ,前后端分离的项目上线时,前端和后端项目是分开上线的,必然至少有端口号 是不相同的,所以只要是 前后端分离开发的项目 都会有跨域的问题
# 2.2 解决跨域的方案有哪些?
- 远古时代操作:jsonp
在jquery 时代可以通过
$.ajax({method:'jsonp'})
代替get请求的跨域缺陷:只能解决get请求的跨域,解决不了post
$.ajax({
method:'jsonp',
url:'请求地址?key=val&key1',
success:function(res){
console.log(res) //返回数据
}
})
2
3
4
5
6
7
- 后端放行请求头,不验证CORS 请求来源
后端不论是 java php go python go rust nodejs 哪一个 都可以在最开始的地方放开浏览器请求头 CORS 限制
案例:nodejs 的express 框架
//设置允许跨域访问该服务.
app.all('*', function (req, res, next) {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Headers', 'Content-Type');
res.header('Access-Control-Allow-Methods', '*');
res.header('Content-Type', 'application/json;charset=utf-8');
next();
});
2
3
4
5
6
7
8
- 运维上线 Nginx 反向代理
server {
listen 8094; #监听端口
server_name localhost;
location / {
root html;#文件根目录
index index.html index.htm;#默认起始页
}
2
3
4
5
6
7
8
# 2.3 利用webapck 本地代理 解决跨域
vue-cli 项目的webpack 配置重写 需要在vue.config.js 中
vue.congfig.js 可配置项 官网:https://cli.vuejs.org/zh/guide/webpack.html
一般情况下:proxy 跨域处理 都需要搭配 env环境变量解决
# 假设访问的接口文档如下:
请求地址:http://127.0.0.1:5000/users/checkLogin
请求方式:post
请求参数:(测试账号:admin 密码:admin)
特殊说明:
该接口上线之后访问地址:http://115.159.153.85:5000/users/checkLogin
参数 类型 是否必填 参数说明 account String 是 账号 password String 是 密码
# 2.4.进行本地代理配置
本地代理配置 到 vue.config.js 中
module.exports = {
devServer: {
proxy: {
'/api': { //接口地址 以 api开头的都走下面的配置
target: 'http://127.0.0.1:5000', //代理目标地址为后端服务器地址
ws: true, //是否支持 websocket 请求 支持
changeOrigin: true, //是否启用跨域
pathRewrite: {
'^/api':'' //发送请求时自动去掉开头
},
}
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
本地开发环境启动时 自动运行的环境
env环境文件: .env.development
VUE_APP_Server:为代理的接口开头
NODE_ENV='development'
VUE_APP_Server= '/api'
2
线上生产环境 不需要代理直接写全路径
env环境文件: .env.production
NODE_ENV='production'
VUE_APP_Server= 'http://115.159.153.85:5000'
2
# 2.5 axios 使用并发送请求
- 全局封装axios request.js
import axios from 'axios'
// 通过全局配置文件载入变量,并根据当前环境 载入变量的值
axios.defaults.baseURL = process.env.VUE_APP_Server
//其他axios 配置
export default axios
2
3
4
5
6
- 页面使用
axios.post('/users/checkLogin',{account:'admin',password:'admin'})
.then(res=>{
//后端返回数据
console.log(res)
})
2
3
4
5
# 3.postcss+rem配置 响应式布局
响应式布局是 数据大屏的兼容方案之一,在写数据大屏项目时,可以利用postcss 与rem 去完成大屏幕的兼容处理
项目环境:
node 16.1.0
yarn
vue/cli@4.x --手动配置创建项目 (vue2.x less vue-router vuex ..)
- 插件安装
amfe-flexible 来根据屏幕动态改变根元素font-size
postcss-pxtorem 把代码中px转为rem 【注:最新版的转换rem插件有bug】
npm i amfe-flexible postcss-pxtorem@5.1.1 -D
或
yarn add amfe-flexible postcss-pxtorem@5.1.1 -D
2
3
- main.js 导入根据屏幕宽度变化 修改html、body的fontSize的插件
import 'amfe-flexible'
- 在vue.config.js 中配置
module.exports = {
css: {
loaderOptions: {
postcss: {
plugins: [
require("autoprefixer")({
// 配置使用 autoprefixer
overrideBrowserslist: ["last 15 versions"]
}),
require("postcss-pxtorem")({
rootValue: 75, // 换算的基数 如果设计图宽度 750px 那么750px==10rem
// 忽略转换正则匹配项。插件会转化所有的样式的px。比如引入了三方UI,也会被转化。目前我使用 selectorBlackList字段,来过滤
// 如果个别地方不想转化px。可以简单的使用大写的 PX 或 Px 。
selectorBlackList: ["ig"],
propList: ["*"],
//排除三方UI库中的 样式兼容
exclude: /node_modules/
})
]
}
}
}
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
- 测试
<template>
<div>
<div class="box"></div>
</div>
</template>
<script>
export default {
}
</script>
<style lang="less" scoped>
.box{
width: 750px; //设计图纸宽度如果为750px 那么这里写750px 就 拉满宽度 在所有的设备屏幕上都可以动态的铺满全屏
height: 300px;
background-color: red;
}
</style>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 4.postcss+vw 配置 响应式布局
- 安装插件
yarn add postcss-px-to-viewport -D
或
npm i postcss-px-to-viewport -D
2
3
- vueconfig.js 配置 vue-cli 4.x
module.exports = {
css: {
loaderOptions: {
postcss: {
plugins: [
require("postcss-px-to-viewport")({
unitToConvert: "px", // 需要转换的单位,默认为"px"
viewportWidth: 750, // 视窗的宽度,对应移动端设计稿的宽度,一般是375
unitPrecision: 3, // 单位转换后保留的精度
propList: [ // 能转化为vw的属性列表
"*"
],
viewportUnit: "vw", // 希望使用的视口单位
fontViewportUnit: "vw", // 字体使用的视口单位
selectorBlackList: [], // 需要忽略的CSS选择器,不会转为视口单位,使用原有的px等单位。
minPixelValue: 1, // 设置最小的转换数值,如果为1的话,只有大于1的值会被转换
mediaQuery: false, // 媒体查询里的单位是否需要转换单位
replace: true, // 是否直接更换属性值,而不添加备用属性
exclude: /(\/|\\)(node_modules)(\/|\\)/, // 忽略某些文件夹下的文件或特定文件,例如 'node_modules' 下的文件
})
]
}
}
}
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
- vueconfig.js 配置 vue-cli5.x
const { defineConfig } = require("@vue/cli-service");
module.exports = defineConfig({
transpileDependencies: true,
css: {
loaderOptions: {
postcss: {
postcssOptions:{
plugins: [
require("postcss-px-to-viewport")({
unitToConvert: "px", // 需要转换的单位,默认为"px"
viewportWidth: 750, // 视窗的宽度,对应移动端设计稿的宽度,一般是375
unitPrecision: 3, // 单位转换后保留的精度
propList: [
// 能转化为vw的属性列表
"*",
],
viewportUnit: "vw", // 希望使用的视口单位
fontViewportUnit: "vw", // 字体使用的视口单位
selectorBlackList: [], // 需要忽略的CSS选择器,不会转为视口单位,使用原有的px等单位。
minPixelValue: 1, // 设置最小的转换数值,如果为1的话,只有大于1的值会被转换
mediaQuery: false, // 媒体查询里的单位是否需要转换单位
replace: true, // 是否直接更换属性值,而不添加备用属性
exclude: /(\/|\\)(node_modules)(\/|\\)/, // 忽略某些文件夹下的文件或特定文件,例如 'node_modules' 下的文件
}),
],
}
},
},
},
});
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
- 测试
<template>
<div>
<div class="box"></div>
</div>
</template>
<script>
export default {
}
</script>
<style lang="less" scoped>
.box{
width: 750px; //铺满屏幕
height: 750px;
background-color: red;
}
</style>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 5.本地 mock数据
mockjs 作用:生成随机数据,拦截 Ajax 请求
目的:很多时候前端开发页面的过程中,后端的接口并没有写好,这个时候需要前端自己定义接口及接口的返回数据的结构体,这个时候就需要用到mock数据,有了mock接口之后,前端就像是有完整的后端一样,等待后端接口开发完成之后,前端就直接将 请求的地址切换到后端服务器就可以无缝切换接口的服务了。
市场:目前市场上mock 大概分为两类:在线mock 网站 本地项目中进行mock 【中大型项目中一般都是使用本地mock 】
官网链接:http://mockjs.com/
# 5.1 安装 插件
yarn add axios mockjs
或
npm i axios mockjs
2
3
# 5.2 通过json数据 模拟拦截接口
- 创建json文件 src/mock/goodsList.json
{
"code":200,
"data":[
{"title":"小米12Pro","price":3400},
{"title":"华为mete 50","price":3666.66},
{"title":"oppo xxx","price":3100},
{"title":"vivo xxx","price":2600},
{"title":"一加 11Pro","price":4100}
]
}
2
3
4
5
6
7
8
9
10
- 使用mock 拦截接口请求,并返回json数据 src/mock/mockServer.js
//导入mockjs
import Mock from 'mockjs'
// 导入json 数据
import goodsList from './goodsList.json'
// 拦截接口 返回mock的数据
Mock.mock('/goods/list',goodsList)
2
3
4
5
6
7
8
9
10
- 在main.js 中导入 mock接口拦截文件
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
// 导入mock接口的拦截
import '@/mock/mockServer.js'
Vue.config.productionTip = false
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
- 组件中调用接口
<script>
import axios from 'axios';
export default {
created() {
axios.get('/goods/list').then(res=>{
console.log(res);
})
}
}
</script>
2
3
4
5
6
7
8
9
10
# 5.3 高级mock规则自动生成数据
- 拦截接口设置:src/mock/mockServer.js
//导入mockjs
import Mock from 'mockjs'
// 导入json 数据
import goodsList from './goodsList.json'
// 拦截接口 返回mock数据
Mock.mock('/goods/list',goodsList)
// 拦截接口,返回mock快速生成批量数据
Mock.mock('/users/list','get',{
code:0,
msg:'获取成功',
data:{
// 生成十个如下格式的数据
'list|10': [
{
'id|+1': 1, // 数字从当前数开始依次 +1
'age|18-40': 20, // 年龄为18-40之间的随机数字
'sex|1': ['男', '女'], // 性别是数组中随机的一个
name: '@cname', // 名字为随机中文名字
email: '@email', // 随机邮箱
isShow: '@boolean', // 随机获取boolean值
},
]
}
})
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
- 测试接口
import axios from 'axios';
export default {
created() {
axios.get('/users/list').then(res=>{
console.log(res);
})
}
}
2
3
4
5
6
7
8
9