关于前端部署后,出现一些跨域问题和页面出现404的问题汇总:
开发时态由webpack-dev-server开启的服务器,可以看做是nginx静态服务器理解(做的事是一样的);做两件事1. 提供index.html静态资源, 2.对请求接口进行代理转发。 区别:webpack-dev-server是在内存总处理的即(webpack没有打包成为资源)。而nginx是将打包后的真实资源进行了部署(打包后将dist,赋值到指定的配置目录即可)
情况1:静态服务器可以做代理转发
开发环境:
- 静态资源
开启服务为localhost:3000 --> dev-server返回index.html --> 浏览器解析执行。
- 数据资源服务 www.app1.com
浏览器解析执行html后 --> 执行js中的ajax请求,接口为 '/news/info'
常见操作1.开发时填写完整的地址 http://www.app1.com/news/info
localhost:3000
www.app1.com
两者存在跨域问题
常见操作2.开发时请求地址为 /news/info
localhost:3000/news/info(由于没有写具体的主机和端口号,浏览器会自动使用地址栏的)
请求不到数据
- 引入代理proxy
静态资源不受影响
数据接口api中,如果接口中匹配到 "/news/",浏览器会自动拼接主机地址[即静态资源部署服务地址]/news/info 会被代理到 www.app1.com/news/info , 服务端间的请求是不存在跨域问题的。
// 具体配置详见webpack https://webpack.js.org/configuration/dev-server/#devserverproxy
devServer: {
host: "0.0.0.0",
port: port,
open: true,
proxy: {
"/news/": {
target: `http://www.app1.com`,
changeOrigin: true,
},
},
disableHostCheck: true,
},
生成环境(打包后):
部署到www.app1.com (部署,就是将打包后的资源文件,放置在服务器指定的配置路径下)
静态资源
访问www.app1.con --> 静态服务器,将打包后的 html文件返回 --> 浏览器展示没问题。
数据资源 www.data.com/news
浏览器解析执行html后 --> 执行js中的ajax请求,接口为 '/news/info' , 即会访问 www.app.com/news/info, 此时就需要nginx进行proxy代理配置:
server {
listen 80; // 端口
server_name http://www.app1.com;
# 具体的nginx的代理规则,自行搜索文章视频学习; 这里仅仅说明.
location /news {
proxy: http://www.data.com // 数据服务地址
}
}
有关 publicPah 的配置场景
一个大型项目,分为不同板块进行开发。例如:新闻板块、游戏板块等在同一个静态资源服务器地址的不同路径下:
新闻板块: www.app1.com/news 资源包放置在news文件下 游戏板块: www.app1.com/games 资源包放置在games文件下
server {
listen 80;
server_name www.app1.com;
# 配置新闻板块
location /news {
alias /news; # 这里的路径请根据你的实际资源包存放路径修改
index index.html;
try_files $uri $uri/ /news/index.html;
}
# 配置游戏板块
location /games {
alias /games; # 这里的路径请根据你的实际资源包存放路径修改
index index.html;
try_files $uri $uri/ /games/index.html;
}
# 处理其他请求(例如网站根目录的请求)
location / {
root /root;
index index.html;
try_files $uri $uri/ /index.html;
}
error_page 404 /404.html;
location = /404.html {
root /var/www/html;
}
}
如果不配置 publicPath
默认配置 '/', html中生成的静态文件引入如下
经webpack打包之后,html如下:
...
<link ref="/css/xxxx.css">
...
那么,
1.当访问新闻板块 http://www/app1.com/news, 静态服务返回html
2.解析执行到 <link ref="/css/xxxx.css"> 就会请求 www.app1.com/css/xxxx.css(浏览器会自动拼接),此时路径在nginx端, 没有匹配到 news 前缀, 它进入到 / 即root文件下, 但root下并不是我们存放新闻模块的文件路径. 即可能不存在报 404.
解决问题
利用publicPath,例如: 新闻板块 publicPath:'news'
经webpack打包之后,html如下:
...
<link ref="/news/css/xxxx.css">
<script src="/news/js/xxxx.js"> </script>
...
那么,
1.当访问新闻板块 http://www/app1.com/news, 静态服务返回html
2.解析执行到 <link ref="/news/css/xxxx.css"> 就会请求 www.app1.com/news/css/xxxx.css(浏览器会自动拼接),那么就被nginx配置news匹配到, 从news文件路径下找资源css/xxxx.css, 是我们存放新闻模块的地方,存在并且返回.
影响问题2
publicPath配置后, 影响打包资源存放路径, 那么进而影响访问资源的路由, 找不到显示自定义404页面
publicpath 默认为 / 时, 资源就在 nginx 配置 / 对应的资源路径下, 路由为 /create 访问创建页. publicpath 改变为 /news后, 资源被换到 /news 对应的资源路径下, 要想访问到, 必须加前缀 /news+路由 即 /news/create. 但原始路由运行时路径可是 /create 故此时路由配置中不存在 /news/create. 故回报404.
因此, 必须同时修改route的初识配置选项:
router配置对象中 base: '/news'(可以使用前面说的process.env.BASE_URL), 告诉路由我们的基地址是news。给路由配置, 统一添加 news 前缀.
情况2:静态服务器由于某种原因,不允许代理转发
静态资源服务:www.app1.com
测试数据服务:www.testserver.com
生产数据服务:www.prodserver.com
在开发中,接口地址为 /info
-
使用前面的方式,开发时proxy,没有问题因为可以代理。但是打包之后,静态服务不做代理,那么这种就必然会重载跨域问题。(不可行)
-
只能将地址写死在接口里面 开发中很少这样
2.1 需要解决跨域问题:需要解决跨域问题(jsonp、cros、服务器端设为支持跨域), 后端帮忙处理.
2.2 维护性问题 / 资源地址暴露安全问题,往往这种情况很少出现.
2.3 如果时第三方开放平台, 后端无法接入/公开; 为了提高维护性, 使用环境变量, 如下 第6 :
//利用环境变量。参考:https://cli.vuejs.org/zh/guide/mode-and-env.html#%E6%A8%A1%E5%BC%8F
1. 只有node环境下有process, 为什么在代码中写入process.env.xxx 开发环境和生产环境即打包后执行不报错呢?
答案:vue-cli基于webpack, 利用webpack.definePlugin插件,在打包过程中扫描代码中的 process.env.xxx 进行了value值得替换。
2. 是如何做到的呢,vuecli中介绍,使用了dotenv插件。
想要了解解析环境文件规则的细节,请参考 [dotenv](https://github.com/motdotla/dotenv#rules)。我们也使用 [dotenv-expand](https://github.com/motdotla/dotenv-expand) 来实现变量扩展 (Vue CLI 3.5+ 支持)。
3. 配置文件中的process是读取,因为配置文件是在webpack打包过程直接参与运行的(node环境)。
4. 环境变量说明:
process.env.NODE_ENV 不要改动脚手架内部在控制NODE_ENV的变化
process.env.BASE_URL 也不要随意改动,与publicPath相关联,读取配置文件执行中,将publicPath赋值为它。
process.VUE_APP_* 可以根据开发需求自行定义的环境变量
用于定义环境变量的文件:参阅vue-cli
.env
.env.production 定义VUE_APP_SERVERURL = www.prodserver.com
.env.devolpment 定义VUE_APP_SERVERURL = www.testserver.com
5. 环境文件加载优先级
5.1 为一个特定模式准备的环境文件 (例如 `.env.production`) 将会比一般的环境文件 (例如 `.env`) 拥有更高的优先级。
5.2 此外,Vue CLI 启动时已经存在的环境变量拥有最高优先级,并不会被 `.env` 文件覆写。
5.3 `.env` 环境文件是通过运行 `vue-cli-service` 命令载入的,因此环境文件发生变化,你需要重启服务。
6. 解决上面的问题:
定义两个环境文件
.env.production 文件 定义VUE_APP_SERVERURL = www.prodserver.com
.env.devolpment 文件 定义VUE_APP_SERVERURL = www.testserver.com
在axios中,将 baseUrl:VUE_APP_SERVERURL 即可。以及其他使用的地方用 VUE_APP_SERVERURL 替换。
下班!