首页
webpack-dev-server 跨域请求数据的问题

最近重构移动端的页面,完全实现了前后端分离。开发的时候,前端用webpack-dev-server服务器来部署,后端还是之前的php后台。在进行ajax请求的时候,发现出现跨域的问题,在网上找了一些解决方案:

1. 使用 jsonp 实现跨域请求

我们移动端是用zepto来替代jquery,实现jsonp比较简单。$.ajax方法将dataType换成jsonp,加个jsonpCallback参数就ok了。
自己封装了一个方法,开发环境用jsonp,正式环境用json
constant.js

export default{
    ENVIRONMENT: 'development',
}

utils.js

import Constant from './constant';
export default {
    //ajax请求,默认是get请求,开发环境通过jsonp实现跨域
    request(params) {
        const ajax_data_type = Constant.ENVIRONMENT == 'development' ? 'jsonp' : 'json';
        const default_params = {
            type: 'GET',
            dataType: ajax_data_type
        };
        if (Constant.ENVIRONMENT == 'development') {
            //加上时间戳和随机数保证jsonpCallback参数的唯一性
            const callback_handler = "jsonpHandler_" + new Date().getTime() + Math.floor(Math.random() * 1000000);
            params.jsonpCallback = callback_handler;
        }
        $.each(default_params, function (key, val) {
            if (!params[key]) {
                params[key] = val;
            }
        });
        $.ajax(params);
    }
};

然后需要请求api的时候,调用这个方法就可以了

const params = {
    url: Constant.API_URL + '/board_list/getBoardLists',
    success: (json_return_data) => {
        if (json_return_data.succeed == true) {}
    }
};
Tool.request(params);

接下来,后台返回的数据格式也需要改一下。这里加了个分支,如果是开发环境,用jsonp须得到前台传过来的$callback参数,将需要返回的数据包装成一个方法

private function ajax_return_msg_to_view($info , $succeed) {
    ob_start();
    $this->output->set_header('Content-Type: application/json; charset=utf-8');
	$return_value = array(
        'succeed' => $succeed ,
        'message' => $info
    );	
    echo json_encode($return_value);
    $output = ob_get_contents();
    ob_end_clean();
    if ($this->isMobile && ENVIRONMENT == "development") {
        $callback = $_GET["callback"];
        echo $callback . "(" . $output . ")";
    } else {
        echo $output;
    }
}

到这里get请求是没有问题的,可是post的话,这样做就只能呵呵了。也找到了一些跨域post的解决方法,但觉得继续深入下去,有点违背初衷了。为了一个开发环境,写这么多冗余的代码有必要吗,其实一开始就弄错了方向。

2. 配置 webpack-dev-server 的 proxy

webpack-dev-server是可以配置 proxy 代理的,用来代理某些请求。如它文档中所述,对于同一域下的前后端分离项目是非常有用的。

image_1einsvr611gujm4g18u01t6s1kg19.png-23.7kB

所以,我们首先得在 webpack.config.js 中配置 devServerhost 值与后端 api 的域一致。比如:后端 api 的地址为 http://test.com:80,我们可以配置为 http://test.com:8080

然后,配置 proxy,设置要转发的请求。这里配置了两个转发请求:

  1. /api的请求使用 pathRewrite 做了重写,比如我的移动端地址为:http://test.com:8080,相当于把http://test.com:8080/api/getXXX转发到了http://test.com:80/getXXX

  2. /avatar相当于把http://test.com:8080/avatar/a.jpg转发到了http://test.com:80/avatar/a.jpg,这样就可以访问服务器的图片了

    devServer: {
        proxy: {
            '/api': {
                target: 'http://test.com:80',
                secure: false,
                changeOrigin: true,
                pathRewrite: {'^/api': ''}
            },
            '/avatar': {
                target: 'http://test.com:80',
                secure: false,
                changeOrigin: true
            }
        }
    },

package.json

"scripts": {
    "dev": "webpack-dev-server -d --progress --colors --inline --hot --port 8080",
  },

然后在请求的方法中,直接使用 json 就可以了。比如:

const url = '/navbar/getMobileNotifications';
$.get(url, (json_return_data)=> {
    if (json_return_data.succeed == false) return;
    const data = json_return_data.message;
    this.loadNotificationList(data);
}, 'json');