Vue+Flask前后端分离部署踩坑总结

前端后端
技术栈Vue + Element UIFlask
部署方式静态文件打包dist上传CDN使用uwsgi部署在一台服务器上,在内网内使用IP:port访问

最终解决方案

在这里插入图片描述

遇到问题及解决方案:

1. 上传后渲染有问题,全部为文本样式

页面表现如下图
在这里插入图片描述
原因为请求CDNcss文件的响应头中content-type错误,被指定成了text/plain,应指定为正确的css格式如下图
在这里插入图片描述
在上传CDN时需要对文件类型指定正确,且CDN保证响应文件请求时在响应头中携带正确的content-type,同理html也应注意文件类型

files = [
            ('file', ('xxx.css', open('{path_to_css_file}', 'rb'), 'text/css'))
        ]

2. axios访问后端API

由于后端服务部署在其他地方(http://10.111.152.165:10000/),CDN(https://cdn.xxx.com)需要访问非本地资源,如果不做处理,axios请求接口时使用的host仍为CDN域名,则会404。需要在axios公共配置中配置baseURL,找到引入axiosaxios.js文件,增加如下配置:

// axios.js

const config = {
  baseURL: process.env.baseURL || "http://10.111.152.165:10000/",
  timeout: 60 * 1000, // Timeout
};

3. CDN域名下请求后端API带来跨域问题

浏览器从一个域名的网页去请求另一个域名的资源时,域名、端口、协议任一不同,都是跨域。在前后端分离的模式下,前后端的域名是不一致的,此时就会发生跨域访问问题。跨域问题出于浏览器的同源策略限制。浏览器错误如下两图
在这里插入图片描述
在这里插入图片描述

跨域请求又可以分为简单请求非简单请求,简单请求不会发送OPTIONS预检请求,非简单请求会首先发送OPTIONS预检请求,详细过程请移步CORS详解

解决方案:

  • 前端:添加跨域请求头Origin,可在axios.js全局axios配置处进行配置
// axios.js

axios.defaults.headers.common['Origin'] ='https://cdn.xxx.com'; //CDN域名
  • 后端:配合前端添加跨域响应头,即给响应头添加以下三个header
Access-Control-Allow-Credentials: true
Access-Control-Allow-Methods: GET, PUT, POST, DELETE, HEAD, OPTIONS
Access-Control-Allow-Origin: https://cdn.xxx.com

可以做成全局方式,安装flask-cors插件,在create_app时配置

# __init__.py

from flask import Flask
from flask_cors import *
def create_app(config_name):
    app = Flask(__name__)

    # 读取项目配置信息
    app.config.from_object(config)

    # 允许跨域请求
    CORS(app, supports_credentials=True)

    ...

本地调试或临时处理跨域问题时,可给Chrome安装Allow CORS: Access-Control-Allow-Origin插件,它相当于一个代理,可以给浏览器收到的响应添加跨域头部
在这里插入图片描述

4. HTTPS资源混合HTTP请求

Chrome浏览器不允许在https协议的页面里请求http的资源,由于后端使用的是HTTP协议,而前端CDN使用HTTPS协议,带来Chrome浏览器HTTPS站点内访问HTTP资源的报错(block:mixed-content),如下两图
在这里插入图片描述
在这里插入图片描述
解决方案:

  • 前端:前端index.html文件中添加如下代码,可将HTTP请求转换为HTTPS请求
<!-- index.html -->

<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">
  • 后端:需要同步修改为HTTPS协议,引入SSL,申请公司可用的证书,或使用OpenSSL自己生成自签证书(自签证书需要每次操作浏览器信任,不是最终的办法),运行方式加上ssl_context,Flask启动方式如下:
# manager.py

app.run(host='0.0.0.0',port=5000,ssl_context=('./server.crt','./server.key'))

----------------------------------------------第二阶段更新---------------------------------------------

最终前后端分离部署架构方案如最上图所示,增加使用公司自研Proxy代理层,由其负责与SSO的交互,增加接入网关,避免HTTPS和HTTP的资源混合请求问题。由于接入了Proxy平台,上述第四个踩坑点不存在了,继续记录该方案下的实现要点及踩坑点。

5. 接入层各项配置关系
Proxy配置,既然使用了代理,不可避免需要在前端进行代理配置,其原理为将请求发送到代理服务器上,有代理服务器进一步通过网关请求后端API,则需要按其代理平台和网关要求进行相关配置,如:

  1. 申请后端域名访问,并CNAME域名解析到网关域名
  2. 在sentry上为后端服务注册app_id
  3. 在Proxy Admin上注册后端的app_id及其域名

这里值得注意的是,后端服务不再需要去SSO管理平台配置回调了,实际上与SSO的交互完全是以Proxy服务的身份进行的,不需要再配置后端服务的SSO回调。

做好管理配置后,还要进行代码上的配置和修改

  • axios.js配置proxy
// axios.js
const config = {
  baseURL: "https://proxy.xxx.com", // 配置为Proxy的Host
  headers: {
    "Content-Type": "application/json", // 使用json格式
    "Access-Control-Allow-Origin": "*", // 允许跨域
    "X-proxy-app-id": 111111, // proxy自定义头,被访问后端的app_id
    "X-proxy-domain": "backend.xxx.com", // proxy自定义头,被访问后端的域名
  },
  timeout: 60 * 1000, // Timeout
  withCredentials: true, // Check cross-site Access-Control
};
  • axios.js 401 goto login page
//axios.js
if (status == 401) { // Proxy检测未登陆返回401,我们捕获改状态请求login
      // Goto login page
      window.location = `https://proxy.xxx.com/login?appId=111111&redirectUrl=${window.location.href}`;
      // 在Proxy的实现中会帮我们做SSO,成功后重定向到我们传入的redirectUrl,这里用window.location.href表示当前页
}
  • logout in Header.vue
// 在Proxy的实现中,logout直接与SSO交互,做登出操作
<a href="https://proxy.xxx.com/logout?appId=111111">
  • App.vue
    前端页面在右上角具有展示用户name的功能,会在访问页面时获取登录用户信息,此处的/profile与/login、/logout一样,为Proxy特殊接口,Proxy会去请求SSO的/profile接口获取用户数据,而不会去找后端的该接口
const { status, data = {} } = await window.axios("/profile");

6. Vue-CLI NODE_ENV 环境变量

直接将dist静态文件上传到CDN使用,由于没有node层,会使用Vue-cli构建前端环境,Vue-CLI会将process.env.NODE_ENV环境变量设置为development,详见Vue-CLI官网。所以我们需要自己去实现根据host获取环境变量。

// utils/index.js
export const getEnvByHost = () => {
  let env = window.location.host.match(/localhost|127.0.0.1|dev|test|stg/);
  if (env && env.length) {
    env = env[0];
    if (env === "127.0.0.1" || env === "localhost") env = "dev";
  }
  if (!env) env = "prod";
  return env;
};

export default {
  getEnvByHost,
};

7. 浏览器无痕模式

该部署方案下,浏览器使用无痕模式关闭 阻止第三方 Cookie,否则SSO不能注入cookie,导致不能正常跳转,其表现为循环跳转SSO登录

8. Vue href 拼接

// configs为全局参数
<a :href="configs.proxyService + '/logout?appId=' + configs.APP_ID">{{ $t("HEADER.LOGOUT") }}</a>
  • 1
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
很抱歉,我是一名语言模型AI,我没有源代码或者程序开发能力。但是,我可以为您提供一些有关VueFlask前后端分离框架的信息。 VueFlask是两个非常流行的开源框架,Vue是一个用于构建用户界面的渐进式框架,Flask是一个轻量级的Python Web框架。前后端分离框架是将前端和后端作为两个独立的应用程序开发,通过API进行通信并交互的一种开发模式。 在VueFlask前后端分离框架中,通常使用Vue作为前端框架,Flask作为后端框架。前端使用Vue开发用户界面,后端使用Flask开发API接口,并通过HTTP请求进行通信。通常,前端使用Axios或Fetch等库进行HTTP请求,后端使用Flask的路由和视图函数进行处理并返回响应数据。 以下是基于VueFlask前后端分离框架的通用目录结构: ``` ├── app/ │ ├── static/ │ ├── templates/ │ ├── __init__.py │ ├── models.py │ ├── views.py │ └── ... ├── frontend/ │ ├── public/ │ ├── src/ │ ├── package.json │ ├── webpack.config.js │ └── ... ├── .gitignore ├── README.md ├── requirements.txt └── ... ``` 其中,`app/`目录包含后端Flask应用程序的代码,`frontend/`目录包含前端Vue应用程序的代码。`static/`目录包含静态文件,如CSS和JavaScript文件,`templates/`目录包含Flask模板文件。`__init__.py`是Flask应用程序的入口文件,`models.py`包含数据库模型,`views.py`包含Flask路由和视图函数。 `public/`目录包含前端应用程序的静态文件,`src/`目录包含Vue组件和路由,`package.json`包含前端应用程序的依赖项和配置,`webpack.config.js`包含前端应用程序的构建配置。 `requirements.txt`包含Python依赖项,`.gitignore`包含Git版本控制的忽略文件列表,`README.md`包含项目说明和文档。 您可以在GitHub等代码托管平台上找到许多基于VueFlask前后端分离框架的源代码,例如`flask-vuejs-template`、`flask-vue-spa`等。这些框架通常包含一个完整的示例应用程序,您可以通过它们了解如何使用VueFlask构建前后端分离框架。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值