关于Vue项目打包后白屏问题的处理步骤(涉及跨域配置跨域)
首先说明,白屏问题基本上是路径错误,而作为基础的baseURL
,在 .env +axios +跨域+ router都有涉及,所以可能会有点乱,我尽量写的详细点。
同上篇一样,网上讲解Vue打包后白屏的文章,数不胜数,但是,总感觉那么书面化,反而有时候解决不了自己的问题,很蓝瘦。
我感觉坑应该被我踩完了把???所以明目张胆的出来炫耀下我的战果[/坏笑]
大概分为几个步骤(因为我也不知道是几个,所以干脆带过啦)
1、路由的模式
2、打包配置没有写对(.env文件的应用)
3、vue.config.js的相关配置
配置:cli3,webpack,Vue-router
1、路由
一般在本机运行没什么问题的话,不会一上来就报请求的错误,但是由于Vue是单页面应用,如果路由或者路径配置,任何一个错的话,都不行。我在路由用的是路由懒加载。
懒加载简单来说就是延迟加载或按需加载,即在需要的时候的时候进行加载。
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
const routes = [
{
path:'/login',
component:()=>import('../views/login/Login.vue'),
meta: {
keepAlive: false
}
},
]
const router = new VueRouter({
routes
})
export default router
主要是下面的路由模式。什么都不写,代表默认为hash。如果打包上线的话,你选择的是
history
模式。那么你可能要做一些其他的配置。我懒。。没搞,有兴趣的到时候整出来@我一下[/滑稽]
这个文章说的就挺好的,就是hash
丑点,其他都挺好→前端路由的两种模式
const router = new VueRouter({
routes
})
const router = new VueRouter({
//mode:'history',//history设置
routes
});
注意!不知道其他各位存在这个问题不,上面的第二张图,我把history模式已经注释了,但是上机依然不行。必须删掉,变成第一张的形式,才会生效。所以如果你们什么办法都试了,还是不可以的话,建议删掉注释试一试
另外附上当点击重复路由,报错
in promise
的错误,重写路由的方法。适用于vue-router@3.0 版本以上
感谢来自于【似朝朝我心】:
Vue CLI3 - 项目中报错Error: Avoided redundant navigation to current location: “/xxx”的解决方案。
import VueRouter from 'vue-router'
Vue.use(VueRouter)
const originalPush = VueRouter.prototype.push
VueRouter.prototype.push = function push (location) {
return originalPush.call(this, location).catch(err => err)
}
2、打包配置
这里就说到我在上一篇博文(axios封装)里面提到的 .env 文件,这里引用两篇文章
高配版 → 构建基础篇 3:env 文件与环境设置
低配版 →.env 文件配置详解
感谢【狂野的心跳】、【CEZLZ】
下面是我的项目结构,.env.development
和.env.production
是和src同级
以下是我的文件中的内容
NODE_ENV = 'development'
VUE_APP_BASE_API = '/api'
NODE_ENV = 'production'
VUE_APP_BASE_API = 'http://000.0.000.00/Lazy33/'
第一个是开发环境,当我们去
run dev
的时候,路径的某一部分就会换成/api
,然后router
会识别,去进行跳转,至于是哪个部分替换。下面的跨域配置中我也会讲到。
第二个就是生产环境,当你执行run build
的时候,同理会换成一个地址。这个地址就是后端接口的baseURL
3、vue.config.js的相关配置
说明:由于我是cli3搭建的环境,这个文件是手动创建的,首先贴出全貌:
module.exports = {
publicPath: process.env.NODE_ENV === 'production'
? './'
: '/' ,
devServer: {
open: true, //项目启动完毕之后是否自动打开浏览器页面;
host: 'localhost', //配置对应主机名;
port: 8081, //项目端口号;
https: false, // https协议
//以上的ip和端口是我们本机的;下面为需要跨域的
proxy: {//配置跨域
'/api': {
target: 'http://000.0.000.00/Lazy33/',//后台接口的baseURL
ws: true, //是否跨域
changOrigin: true,//允许跨域
secure: false,
pathRewrite: {
'^/api': ''//请求的时候使用这个api就可以
}
}
},
}
}
1、方法是Nginx代理跨域
2、原理就是偷梁换柱,既然我去请求的时候是localhost:8081 ,那么我把前面换成后端的地址不就可以了?
3、需要后端设置Access-Control-Allow-Origin
全部允许(这个别问我,不会)
以下进行解释
1、第二行可以参考我上面发的低配版,讲的是使用
process.env.NODE_ENV
来进行访问,下面两江行是一个三元运算符去判断的:(关系表达式) ? 条件为真执行的内容 : 条件为假执行的内容
如果生产环境,那么地址就是./
至于为什么是/
和./
是影响vue打包后dist文件夹里面的index.html
里面的css的href地址,以及js的src地址,如下图。图一是./
图二是/
图一:
图二:
所以你的css,js找不到了,肯定要白屏。而且自己项目上线后,某个依赖的img不显示,那么也是和这个基础路径的配置有关系
上面是这个dist的文件夹的目录结构,如果白屏了话,第一时间就是看href 的路径指向是否正确
2、跨域具体起作用的是这部分
proxy: {//配置跨域
'/api': {
target: 'http://000.0.000.00/Lazy33/',//后台接口的baseURL
ws: true, //是否跨域
changOrigin: true,//允许跨域
secure: false,
pathRewrite: {
'^/api': ''//请求的时候使用这个api就可以
}
}
},
让我们直接看最后一行,意思是请求的时候,你直接写上/api
,到时候,请求的baseURL
就会换成第3行,你写的后端的接口位置,到时候都自己人了,还讲什么跨不跨呢?
注意了,这个/api
是不是看着很眼熟,
接下来我要串一下
首先,我们拿到项目的第一步,是封装网络请求,看看后端给的测试接口是否可以连通。当然,为了简洁,后端接口重复的地方,也就是
baseURL
,我们可以加到公共地址部分,比如我在上一篇文章写的:
axios.defaults.baseURL = process.env.VUE_APP_BASE_API; //配置接口地址根目录(打包以及开发配置)
其实这里我的baseURL
应该写为
axios.defaults.baseURL = 'http://000.0.000.00/Lazy33/';
然后我把这个base地址换到了.env.production
里面,然后我的axios
就引用下.env里面的就可以,
调通好axios封装,生产环境配置,那么接下来自然是配置开发环境,开发环境就会用到跨域了,正如上面所讲,我吧后端base地址简写成了
/api
,所以在.env.development
里面写的是’/api’ .这样不论是打包,还是开发环境,都可以顺利访问到接口地址
NODE_ENV = 'development'
VUE_APP_BASE_API = '/api'
现在有一个请求,http://000.0.000.00/Lazy33/login ,我在vue组件页面的methods里面写请求,参数url就只用写/login就可以了,然后,会到axios封装里面
1、dev(开发)情况下,会加上"/api"
,那么这个api,又到了vue.config.js里面,api其实是被我包装好的后端base路径'http://000.0.000.00/Lazy33/'
那么这个请求发出去的其实是localhost:8081
去请求http://000.0.000.00/Lazy33/login
的,然后我跨域代理,把本机换成了http://000.0.000.00/Lazy33
,这样请求肯定不会产生跨域,自家人嘛~
2、那生产环境下。由于.env.production
被我换成了'http://000.0.000.00/Lazy33/'
,之后这个请求就变成了
'http://000.0.000.00/Lazy33/'
去请求'http://000.0.000.00/Lazy33/login'