线上前端静态资源代理到本地的几种方式

前言

我是一个小前端,前段时间开始支持集团监控平台业务。
当我拉下代码,开启本地服务,出现了一大堆请求错误。
原因是:本地的host是127.0.0.1,而接口调用的是线上数据
接口的host和平台url的host都是x.alibaba-inc.com。
怎么办?我要跨域。。
直接修改hosts是不行的,使用http的withCredentials为真,导致允许跨域的源必须是本地,会导致监控平台对外提供的接口出现问题。
。。。
然后我请教了@绘萌师兄,师兄提出可以把线上资源代理到本地。
OK,怎么把线上资源代理到本地呢?
经过一番折腾,我总结出如下四种方式。

方式

1、抓包类工具

常用的抓包工具有Wireshark、Fiddler、Charles。
这里我拿Charles举例子,把线上资源代理到本地叫本地文件映射。
菜单路径:Tools -> Map Local
与本地文件映射对应的叫远程映射文件映射,远程映射文件映射将路径映射到其他服务器上,而本地映射则映射到本地磁盘上。

线上前端静态资源代理到本地的几种方式_第1张图片

Map From 设置好线上文件 A 的相关信息,Map To 里选择本地资源,请求文件 A 时,就会返回指定的本地文件。
图中我把日常前端所有资源都代理到本地了。

2、浏览器插件

Chrome的相关插件:Proxy SwitchySharp、ReRes
Firefox的相关插件:FoxyProxy、Autoproxy

试一把:
线上前端静态资源代理到本地的几种方式_第2张图片

本地修改代码,发现线上完全同步了,完美!

传送门:
Proxy SwitchySharp
ReRes
FoxyProxy
Autoproxy

3、Nginx

原理:使用nginx反向代理,起localhost的http服务,本地代理层拦截静态资源请求,并返回本地的静态资源;放过数据请求,将数据请求代理成线上真实的地址。
首先,要理清楚前端的静态资源请求和数据请求。然后对nginx.conf进行配置。到这一步,我们已经能接触到线上,但是线上访问有跨域限制,所以需要绑定host,使得到线上的请求的不受跨域限制。

配置文件内容如下:

user root;
worker_processes  4;

pid        logs/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       mime.types;
    default_type  application/octet-stream;

    sendfile        on;

    keepalive_timeout  65;

    server {
        listen       80;
        server_name  x.alibaba-inc.com;
        # 拦截并返回本地的静态资源
        location ~ ^/modules.*\.(html|htm|gif|jpg|jpeg|bmp|png|ico|txt|js|css)$ 
        {# 拦截并返回本地的静态资源
            root /Users/feiyu/Documents/xflush/xflush-burning/app;
        }  
        location ~ ^/bower_components.*\.(html|htm|gif|jpg|jpeg|bmp|png|ico|txt|js|css)$ 
        {
            root /Users/feiyu/Documents/xflush/xflush-burning;
        } 

        location ~ .*\.(html|htm|gif|jpg|jpeg|bmp|png|ico|txt|js|css)$ 
        {
            root /Users/feiyu/Documents/xflush/xflush-burning/app;
        } 
        # 放过的数据请求,该资源为服务器端提供
        location = /env.js {
            proxy_pass http://100.67.99.11;
        }
        # 放过的数据请求,该资源为服务器端提供
        location = /tenants.js {
            proxy_pass http://100.67.99.11;
        }
        # 放过的数据请求,此处为ajax请求的数据
        location / {
            proxy_pass http://100.67.99.11;
        }

    }


}

4、Nodejs

完成该项功能的是 http-proxy 包。下载、安装请键入:

    npm install http-proxy  

在使用这个之前要做的是对请求类型的一些判断,即请求Js/css/jpg等这些文件时,返回的response信息类型是什么,于是有了下面的代码:

var getContentType = function(ext){
    var contentType = '';
    switch(ext){
        case ".html":
            contentType= "text/html";
            break;
        case ".js":
            contentType="text/javascript";
            break;
        case ".css":
            contentType="text/css";
            break;
        case ".gif":
            contentType="image/gif";
            break;
        case ".jpg":
            contentType="image/jpeg";
            break;
        case ".png":
            contentType="image/png";
            break;
        case ".ico":
            contentType="image/icon";
            break;
        default:
            contentType="application/octet-stream";
    }

    return contentType;
};

接着是代理代码:

/*
    http-proxy 
*/
var http = require('http')
    ,httpProxy = require('http-proxy')  //http-proxy
    ,proxy = httpProxy.createProxyServer({})
    ,fs = require('fs')
    ,path = require('path')
    ,getConType = require('./content-type')//自己定义  根据后缀转换Content-Type
;


var server = http.createServer(function(req, res) {
    var _url = req.url //获取请求的url
        ,_file
        ,_localPath
        ,_localFile
        ,_ext
        ,_stream 
    ;
    //eg://g-assets.daily.taobao.net/ais-fed/sunfire/1.0.0/vendor.js
    if(_url.indexOf('//g-assets.daily.taobao.net/ais-fed/sunfire/1.0.0/')>-1){

        _ext = path.extname(_file); // 文件扩展
        //vendor.js
        _file = _url.replace('//g-assets.daily.taobao.net/ais-fed/sunfire/1.0.0/','');
        //转换成本地路径
        _localPath = '/Users/feiyu/Documents/xflush/sunfire/build/';
        _localFile = _localPath+_file;

        //判断文件是否存在
        if(fs.existsSync(_localFile)){//如果文件存在
            res.writeHead(200, {"Content-Type": getConType(_ext) });

            _stream = fs.createReadStream(_localFile, {flags : "r", encoding : null});//只读模式 读取文件内容
            _stream.on('error',function(){//如果读取错误 返回404
                res.writeHead(404, {"Content-Type": "text/html"});
                res.end("

404 Read Error

"
); }); _stream.pipe(res);//连接文件流和http返回流的管道,用于返回实际Web内容 _stream.on('end',function(){ _stream = null; }) }else{//返回404错误 res.writeHead(404, {"Content-Type": "text/html"}); res.end("

404 Not Found

"
); } }else{ proxy.web(req, res, { target: 'x.alibaba-inc.com' }); } }); console.log("listening on port 80") server.listen(80);

总结来说,实现反向代理的静态资源分离,首先是判断request来判断是否请求静态文件,如果是请求静态文件,就找到项目下的具体文件,直接用fs读取,如果不是请求静态文件那么就用proxy.web来请求实际服务器。最后别忘了绑定host。

另外给一个anyproxy的传送门,它是用nodejs写的,提供web版界面,可以观测请求情况,还具有开放接口,允许用户进行充分的自定义。

anyproxy

总结

其实都是为了解决问题,只是方式不同,大家爱用哪个用哪个哈~

最后,我想感谢@谷童@季真@笑斌三位同学!
谷童做为最初的引导老师;
季真教我如何配置nginx;
笑斌帮我review nodejs代码。

你可能感兴趣的:(Web_解决方案)