如何解决vite.config.js代理配置失效问题?
问题描述:一个前后端分离项目,前端为vue3+vite5+uniapp项目,
后端接口为http://47.93.153.78:8080/code,微信小程序中可以访问的到,但是H5中会显示跨域问题
Access to XMLHttpRequest at 'http://47.93.153.78:8080/code' from origin 'http://localhost:7001' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
然后我这边去做代理配置, 其中proxy替换VITE_APP_BASE_API (/dev-api) 没有生效,找了半天没找到原因,求助大佬帮忙看一下
import { defineConfig } from 'vite'
import uni from '@dcloudio/vite-plugin-uni'
import { loadEnv } from 'vite'
import path from 'node:path'
import UnoCSS from 'unocss/vite'
import dayjs from 'dayjs'
import svgLoader from 'vite-svg-loader'
// 打包后,会在根目录下生成一个 stats.html文件
import { visualizer } from 'rollup-plugin-visualizer'
// 通过监听文件修改,自动重启 vite 服务 最常用的场景就是监听 vite.config.js 和 .env.development 文件,修改 vite 配置文件和环境配置文件,是需要重启 vite 才会生效
import ViteRestart from 'vite-plugin-restart'
import AutoImport from 'unplugin-auto-import/vite'
import VueSetupExtend from 'vite-plugin-vue-setup-extend'
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
import viteCompression from 'vite-plugin-compression'
// import ViteImagemin from 'vite-plugin-imagemin'
import autoprefixer from 'autoprefixer'
import UniPages from '@uni-helper/vite-plugin-uni-pages'
import UniLayouts from '@uni-helper/vite-plugin-uni-layouts'
// 自定义插件方法
const htmlPlugin = () => {
return {
name: 'html-transform',
transFormIndexHtml(html) {
return html.replace('%BUILD_DATE%', dayjs().format(''))
},
}
}
// unplugin-vue-components uniapp 不支持,uniapp 使用easycom的方式自动引入组件,不需要这个vite插件
export default ({ mode }) => {
// mode区分生产环境还是开发环境
// process.cwd() 获取当前文件的目录和地址
// loadEnv 返回当前环境env文件中额外定义的变量
const env = loadEnv(mode, path.resolve(process.cwd()))
console.log(env)
return defineConfig({
plugins: [
UniPages({
exclude: ['**/components/**/**.*'],
routeBlockLang: 'json5', // 虽然设了默认值,但是vue文件还是要加上 lang="json5", 这样才能很好地格式化
homePage: 'pages/home-page/index',
subPackages: ['src/pages-sub'], // 这是个数组,可以写多个
}),
UniLayouts(),
// UniXXX 需要在 Uni 之前引入
uni(),
// 在 Vite 驱动的 uni-app 上使用基于文件的路由系统。
UnoCSS(),
htmlPlugin(),
svgLoader(),
// 打包分析插件 打包后,会在根目录下生成一个 stats.html文件
visualizer(),
ViteRestart({
// 修改vite.config.ts 不用手动重启vite就能生效
restart: ['vite.config.ts'],
}),
// vue3等插件hooks自动引入
// 支持vue, vue-router, vue-i18n, @vueuse/head, @vueuse/core等自动引入
AutoImport({
imports: ['vue'],
// 可以选择auto-import.d.ts生成的位置,使用ts建议设置为src/auto-import.d.ts
dts: 'src/auto-import.d.ts',
}),
// 在使用setup语法糖的时候没办法直接为组件定义name,需要使用两个script标签来完成
// 使用vite-plugin-vue-setup-extend
// <script lang="ts" setup name="自定义name">
VueSetupExtend(),
createSvgIconsPlugin({
// 指定svg图标 保存的文件夹路径,
iconDirs: [path.resolve(process.cwd(), 'src/assets/svg')],
// 指定symbolId格式
symbolId: 'icon-[dir]-[name]',
}),
// 会多出一些.gz文件,如xxx.js.gz,这里默认是不会删除xxx.js文件的,如果想删除也可以增加配置
// vite-plugin-compression是一个基于Vite的插件,用于gzip或Brotli压缩你的资源,从而减少页面的加载时间和网络带宽,提高用户访问速度和体验。
viteCompression(),
],
css: {
postcss: {
plugins: [
// 前端开发中,为兼容所有浏览器,部分CSS属性需要加上不同的浏览器前缀
autoprefixer({
// 指定目标浏览器
overrideBrowserslist: ['> 1%', 'last 2 versions'],
}),
],
},
},
resolve: {
// 配置路径别名
alias: {
'@': path.join(process.cwd(), './src'),
},
},
server: {
// host: '0.0.0.0',
// hmr: true,
port: 7001,
cors: true,
open: true,
// 自定义代理规则
proxy: {
[env.VITE_APP_BASE_API]: {
target: 'http://47.93.153.78:8080', // 目标服务器的URL
changeOrigin: true,
rewrite: (path) => {
console.log('path-------------------------------------', path)
return path.replace(new RegExp(`^${env.VITE_APP_BASE_API}`), '')
},
bypass(req, res, options: any) {
const proxyURL = options.target + options.rewrite(req.url)
console.log('proxyURL', proxyURL)
req.headers['x-req-proxyURL'] = proxyURL // 设置未生效
res.setHeader('x-req-proxyURL', proxyURL) // 设置响应头可以看到
},
},
},
},
build: {
// 处理清除console的插件
minify: 'terser',
terserOptions: {
compress: {
drop_console: env.VITE_DELETE_CONSOLE === 'true',
drop_debugger: env.VITE_DELETE_CONSOLE === 'true',
},
},
},
})
}
这部分是env的配置
# 变量必须以VITE_为前缀才能暴露给外部获取
NODE_ENV = 'development'
VITE_SERVER_BASEURL = 'http://47.93.153.78:8080'
VITE_APP_BASE_API = '/dev-api'
# 是否去除console 和 debugger
VITE_DELETE_CONSOLE = false
这部分是request配置
import { useUserStore } from '@/store'
import type { UserInfo } from '@/typings'
// console.log('useUserStore:', useUserStore)
type Data<T> = {
code: number
msg: string
data: T
}
// 请求基地址
export const baseUrl = import.meta.env.VITE_SERVER_BASEURL
export const baseUrlCors = import.meta.env.VITE_APP_BASE_API
// 拦截器配置
const httpInterceptor = {
// 拦截器触发
invoke(options: UniApp.RequestOptions) {
const headers = options?.headers || {}
const params = options?.params || {}
// 1. 非http开头的请求地址需要拼接地址
if (!options.url?.startsWith('http')) {
options.url = baseUrl + baseUrlCors + options.url
}
// 携带参数
if (Object.keys(params).length) {
let carryParams = '?'
Object.keys(params).forEach((item, index) => {
carryParams += `&${item}=${params[item]}`
})
options.url += carryParams
}
// 2. 请求超时
options.timeout = 10000 // 10s
// 3. 添加小程序请求头标识
options.header = {
platform: 'mp-weixin', // 可选值与uniapp定义的平台一致, 告诉后台来源
...options.header,
}
// 4. 添加token请求头标识
const userStore = useUserStore()
const token = userStore.token
if (token) {
options.header.Authorization = `Bearer ${token}`
}
if (typeof headers.isToken === 'boolean' && !headers?.isToken) {
delete options.header.Authorization
}
},
}
// 拦截request请求
uni.addInterceptor('request', httpInterceptor)
// 拦截uploadFile文件上传
uni.addInterceptor('uploadFile', httpInterceptor)
const http = <T>(options: UniApp.RequestOptions) => {
// 返回Promise对象
return new Promise<Data<T>>((resolve, reject) => {
uni.request({
...options,
// 响应成功
success(res) {
if ((res.data as Data<T>).code > 200 && res.statusCode === 200) {
uni.showToast({
icon: 'none',
title: (res.data as Data<T>).msg || '请求错误',
})
reject(res)
}
// 状态码 2xx 参考axios的设计
else if (res.statusCode >= 200 && res.statusCode < 300) {
// 2.1 提取核心数据res.data
resolve(res.data as Data<T>)
} else if (res.statusCode === 401) {
// 401错误 -> 清理用户信息, 跳转到登录页
const userStore = useUserStore()
userStore.logout()
uni.navigateTo({
url: '/pages/login/login',
})
setTimeout(() => {
uni.showToast({
icon: 'none',
title: '登陆过期',
})
})
reject(res)
} else {
// 其他状态码 -> 根据后端错误信息轻提示
uni.showToast({
icon: 'none',
title: (res.data as Data<T>).msg || '请求错误',
})
reject(res)
}
},
// 响应失败
fail(err) {
uni.showToast({
icon: 'none',
title: '网络错误, 换个网络试试',
})
reject(err)
},
})
})
}
export default http
request
请求H5
的时候 不要添加baseUrl
代理配置代理的是本地请求,你添加了
baseUrl
就不会被本地服务代理了