什么是跨域?
https://www.guobao0730.com/babel/
一个URL地址由 协议(https://) + 域名(www.guobao0730.com) + 端口号(443) + 资源地址(babel) 组成,当协议、域名、端口号中任意一个发生改变的时候,就会被当做是不同的源,这时候就会触发跨域的问题。
浏览器的安全策略规定当前域名的js不允许访问其它域的地址,核心原因是XMLHttpRequest 不支持跨域请求。
怎么解决跨域的问题?
跨域的错误提示:


大致意思是表示XMLHttpRequest这个对象不支持跨域的请求
既然不支持,那么就找一个支持的对象,比如img、audio、video、link标签,它们的特点如下:
1、上述标签都支持跨域请求,
2、通过GET请求的方式可以将数据传递出去,
3、无法接受到服务器返回的数据。
通过script标签来实现跨域的请求,该标签的特点如下:
1、支持跨域请求
2、通过GET请求的方式可以将数据传递出去
3、 当服务器返回一个js表达式(var data = { “state”:200,”msg”:”请求成功”,”data”:”用户不存在” })时,可以正常获取服务器返回的数据,该种方式就相当于通过script标签引入一个外部的js文件一样,当通过load事件监听到外部js文件加载完毕以后,使用外部js文件中的data对象即可获取数据。
开发环境
Vue 2 和 Vue 3解决跨域的问题可以参见:https://blog.csdn.net/yuanlaijike/article/details/80522621
注意:
在dev开发模式下使用的webpack的proxy可以解决跨域的问题,但是这种方式在生产环境下不能使用,在生产环境中需要使用nginx 进行反向代理。其实原理都一样,都是通过搭建一个中转服务器转发请求进行规避跨域的问题。
生产环境
方式一:
通过nginx 反向代理来解决生产环境下网络请求
如果当前是生产模式,那么前端通过proxy(代理)解决跨域的同时,在nginx中需要进行反向代理,具体需要在nginx.conf文件中进行如下配置:
server { listen 9527; server_name localhost; client_max_body_size 20M; #charset koi8-r; #access_log logs/host.access.log main; root /usr/local/nginx/html/dsep/dist; index index.html index.html; # prod-api 是代理的名称 location /prod-api/ { proxy_redirect off; proxy_pass http://172.16.1.19:8080/; } #error_page 404 /404.html; # redirect server error pages to the static page /50x.html # error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } # proxy the PHP scripts to Apache listening on 127.0.0.1:80 # #location ~ \.php$ { # proxy_pass http://127.0.0.1; #} # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 # #location ~ \.php$ { # root html; # fastcgi_pass 127.0.0.1:9000; # fastcgi_index index.php; # fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; # include fastcgi_params; #} # deny access to .htaccess files, if Apache's document root # concurs with nginx's one # #location ~ /\.ht { # deny all; #} }
其中 prod-api 表示代理的名称,http://172.16.1.19:8080/ 是代理路径的真实地址。
例如:代理路径为:/prod-api ,真实的服务器地址为:http://172.16.1.19:8080 ,如下代码
# just a flag ENV = 'production' # base api VUE_APP_BASE_API = '/prod-api' # 发布环境下的服务器请求地址 VUE_APP_BASE_URL = 'http://172.16.1.19:8080'

那么反向代理需如下配置,这里注意需要将 /prid-api 改为 prod-api ,真实地址后面添加 /
# prod-api 是代理的名称
location /prod-api/ {
proxy_redirect off;
proxy_pass http://172.16.1.19:8080/;
}

方式二:
根据开发环境的不同设置前端是否需要进行代理,如下代码:
request.js (axios二次封装文件)
const service = axios.create({
baseURL: process.env.NODE_ENV === 'development' ? process.env.VUE_APP_BASE_API : process.env.VUE_APP_BASE_URL, // 开发环境进行代理,否则不需要
withCredentials: true,
timeout: 50000
})
vue.config.js文件
const developmentProxy = { [process.env.VUE_APP_BASE_API]: { target: process.env.VUE_APP_BASE_URL, changeOrigin: true, pathRewrite: { ['^' + process.env.VUE_APP_BASE_API]: '' } } } // 开发环境下请求数据时需要代理,正式环境不需要 const proxy = process.env.NODE_ENV === 'development' ? developmentProxy : {} module.exports = { publicPath: './', outputDir: 'dist', assetsDir: 'static', lintOnSave: process.env.NODE_ENV === 'development', productionSourceMap: false, devServer: { port: port, open: true, overlay: { warnings: false, errors: true }, proxy: proxy }, configureWebpack: { name: name, resolve: { alias: { '@': resolve('src') } } }, chainWebpack(config) { config.plugins.delete('preload') // TODO: need test config.plugins.delete('prefetch') // TODO: need test // set preserveWhitespace config.module .rule('vue') .use('vue-loader') .loader('vue-loader') .tap(options => { options.compilerOptions.preserveWhitespace = true return options }) .end() config // https://webpack.js.org/configuration/devtool/#development .when(process.env.NODE_ENV === 'development', config => config.devtool('cheap-source-map') ) config .when(process.env.NODE_ENV !== 'development', config => { config .plugin('ScriptExtHtmlWebpackPlugin') .after('html') .use('script-ext-html-webpack-plugin', [{ // `runtime` must same as runtimeChunk name. default is `runtime` inline: /runtime\..*\.js$/ }]) .end() config .optimization.splitChunks({ chunks: 'all', cacheGroups: { libs: { name: 'chunk-libs', test: /[\\/]node_modules[\\/]/, priority: 10, chunks: 'initial' // only package third parties that are initially dependent }, elementUI: { name: 'chunk-elementUI', // split elementUI into a single package priority: 20, // the weight needs to be larger than libs and app or it will be packaged into libs or app test: /[\\/]node_modules[\\/]_?element-ui(.*)/ // in order to adapt to cnpm }, commons: { name: 'chunk-commons', test: resolve('src/components'), // can customize your rules minChunks: 3, // minimum common number priority: 5, reuseExistingChunk: true } } }) config.optimization.runtimeChunk('single') } ) } }
.env.development文件如下:
NODE_ENV='development'
# must start with VUE_APP_
VUE_APP_ENV = 'development'
VUE_APP_BASE_API = '/dev-api'
#base url http://kykjbyg.lxygm.com/ http://wfbyg.hbkykj.cn
VUE_APP_BASE_URL = 'http://wfbyg.hbkykj.cn'
#appid
VUE_APP_WECHAT_APPID='wxcee7b521765291ad'
VUE_CLI_BABEL_TRANSPILE_MODULES = true
.env.production 文件如下:
NODE_ENV='production'
# must start with VUE_APP_
VUE_APP_ENV = 'production'
VUE_APP_BASE_API = '/prod-api'
#base url
VUE_APP_BASE_URL = 'http://wfbyg.hbkykj.cn'
#appid
VUE_APP_WECHAT_APPID='wxcee7b521765291ad'