跨域

前后端分离开发免不了涉及跨域问题,今天就来说一说它。

当然,这只是我个人的理解,如有错误,欢迎指正

开发环境下的跨域

在Vue中解决跨域:

在前端项目根目录新建 vue.config.js

module.exports = {
  publicPath: process.env.NODE_ENV === 'production' ? './' : '/',
  devServer: {
    proxy: {
      '/api': {
        target: 'http://api.server.com',
        changeOrigin: true,
        ws: true,
        pathRewrite: {
          '^/api': ''
        }
      }
    }
  }
};

什么意思呢,简单来说就是当请求路径中包含 /api 的时候,就把该请求代理到 http://api.server.com
不明白?举个例子:
假如我要访问 http://api.server.com 去获取某话题,

axios.get("http://api.server.com/topic/233")

假设你的域名是 server.com,别看只少了 api ,浏览器就是不让你过,是不是很气?
这就是浏览器的同源策略导致的,也就是跨域问题的根源。
但是!nodejs是没有跨域问题的,于是利用这一点,让nodejs去获取数据不就可以了吗?
希望你不要问nodejs是啥,这个我真的解释不了……
话题转回来,上面的 proxy 配置就是告诉node,当访问路径中有 /api 这个字符串时你就把它接管下来,然后去访问 http://api.server.com 获取数据,然后再把数据给浏览器,Ok,跨域问题解决了!鼓掌~

总的来说就是,浏览器访问

axios.get("http://server.com/api/topic/233")

node发现有 api 便接管请求,转而去访问 http://api.server.com/topic/233,获得数据后返回给浏览器。
聪明的你或许会问了,路径中的 api 去哪了?
是的,它被吃了,具体来说是被 pathRewrite 给吃了……

说点题外话,我们在开发的时候,访问路径一般是 http://localhost:8080/api/topic/233,问题是打包的时候我们需要把路径换成 http://server.com/api/topic/233,毕竟你的域名不可能是localhost, 手动去换不太现实,我们要配置 webpack 让它开发时用 localhost,发布时用 server.com

在前端项目根目录建立
.env.development(开发环境)

// 开发环境下配置
module.exports = { 
  NODE_ENV = 'development'
  VUE_APP_BASE_API = 'http://localhost:8080'
  VUE_APP_VERSION = '0.0.2'
}

.env.production(生产环境)

// 生产环境下配置
module.exports = { 
  NODE_ENV = 'production'
  VUE_APP_BASE_API = 'http://server.com'
  VUE_APP_VERSION = '0.0.1'
}

简单说一下使用方法(有机会的话细说):
建立 utils/http.js文件

import axios from 'axios';
// 创建axios实例
var instance = axios.create({
    baseURL: process.env.VUE_APP_BASE_API,
    timeout: 1000 * 12
});
export default instance;
import axios from '@/utils/http';
axios.get("/api/topic/233")

这样,webpack就会自动判断该使用哪个域名了。

线上问题

当你开发好项目,发布到线上后,你会发现之前用的接口全都报错了,why?
我们来捋一下……
由于生产环境没有nodejs为我们代理访问,那么浏览器就会直接去访问接口
http://xxx.com/api/topic/233
我们的前端页面自然是没有这个地址的,因为实际的地址是
http://api.xxx.com/topic/233
那么怎么办呢?
这里就轮到了Nginx的登场了。

目前我们的服务器配置了两个服务,一个是前端页面,一个是api服务,我们需要修改一下前端页面的nginx配置,让它能够代理转发我们的路径。
先上配置:

server {
    listen       80;
    server_name  xxx.com;

    root   /usr/share/nginx/www/html;
    index  index.php index.html index.htm;
    location /api/ {
        proxy_pass http://api.xxx.com/;
    }
}

注意到 proxy_pass http://api.xxx.com/; 这一行没有?
这样就能把 http://xxx.com/api/topic/233 代理到 http://api.xxx.com/topic/233

注:
server.com 是开发时使用的域名,xxx.com 是购买的域名
域名的最后一定要有 / ,具体的区别见 nginx的proxy_pass路径转发规则浅析

目录:
从零开始搭建网站环境(php-yaf nginx mariadb)第一章
从零开始搭建网站环境(php-yaf nginx mariadb)第二章
从零开始搭建网站环境(php-yaf nginx mariadb)第三章
从零开始搭建网站环境(php-yaf nginx mariadb)番外篇——跨域


zeronofreya
192 声望3 粉丝