使用webpack-dev-server设置反向代理解决前端跨域问题
webpack-dev-server是一个小型的Node.js Express
服务器,它使用webpack-dev-middleware
来服务于webpack的包,除此自外,它还有一个通过Sock.js来连接到服务器的微型运行时.
我们来看一下下面的配置文件(webpack.config.js
)
var path = require("path"); module.exports = { entry:{ app:["./app/main.js"] }, output:{ path:path.resolve(__dirname,"build"), publicPath:"/assets/", filename:"bundle.js" } }
这里你将你的源文件放在app
文件夹下,并通过webpack
将其打包到build
文件夹下的bundle.js
中.
注意:webpack-dev-server
是一个独立的NPM包,你可以通过npm install webpack-dev-server
来安装它.
基本目录
webpack-dev-server默认会以当前目录为基本目录,除非你制定它.
webpack-dev-server --content-base build/
上述命令是在命令行中执行的,它将build
目录作为根目录.有一点需要注意的是:webpack-dev-server生成的包并没有放在你的真实目录中,而是放在了内存中.
我们在基本目录下新建一个index.html
文件,然后在浏览器中输入http://localhost:8080
访问.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <script src="assets/bundle.js"></script> </body> </html>
webpack-dev-server启动proxy代理
代理配置
webpack-dev-server使用http-proxy-middleware去把请求代理到一个外部的服务器,配置的样例如下:
//配置服务器 devServer: { historyApiFallback: true, hot: true, inline: true, contentBase: "./app", port: 8090, proxy: { "/api": { target: 'http://localhost:8888', pathRewrite: {'^/api' : ''}, changeOrigin: true } }, },
这种代理在很多情况下是很重要的,比如你可以把一些静态文件通过本地的服务器加载,而一些API请求全部通过一个远程的服务器来完成。还有一个情景就是在两个独立的服务器之间进行请求分割,如一个服务器负责授权而另外一个服务应用本身。
pathRewrite: 对于代理的请求可以通过提供一个函数来重写,这个函数可以查看或者改变http请求。下面的例子就会重写HTTP请求,其主要作用就是移除URL前面的/api部分。
绕开代理
通过一个函数的返回值可以视情况的绕开一个代理。这个函数可以查看http请求和响应以及一些代理的选项。它必须返回要么是false要么是一个URL的path,这个path将会用于处理请求而不是使用原来代理的方式完成。下面的例子的配置将会忽略来自于浏览器的HTTP请求,他和historyApiFallback配置类似。浏览器请求可以像往常一样接收到HTML文件,但是API请求将会被代理到另外的服务器:
proxy: { '/some/path': { target: 'https://other-server.example.com', secure: false, bypass: function(req, res, proxyOptions) { if (req.headers.accept.indexOf('html') !== -1) { console.log('Skipping proxy for browser request.'); return '/index.html'; } } } }
代理本地虚拟主机
http-proxy-middleware会预解析本地hostname成为localhost,你可以使用下面的配置来修改这种默认行为:
var server = new webpackDevServer(compiler, { quiet: false, stats: { colors: true }, proxy: { "/api": { "target": { "host": "action-js.dev", "protocol": 'http:', "port": 80 }, ignorePath: true, changeOrigin: true, secure: false } } }); server.listen(8080);
贴入我自己项目的webpack.config.js配置:
var webpack = require('webpack'); var path = require('path'); var ExtractTextPlugin = require('extract-text-webpack-plugin'); //抽取CSS文件插件 var OpenBrowserPlugin = require('open-browser-webpack-plugin'); //自动打开浏览器插件 var ROOT_PATH = path.resolve(__dirname); var BUILD_PATH = path.resolve(ROOT_PATH, 'build'); var APP_PATH = path.resolve(ROOT_PATH, 'app'); module.exports = { //配置服务器 devServer: { historyApiFallback: true, hot: true, inline: true, contentBase: "./app", port: 8090, proxy: { "/api": { target: 'http://localhost:8888', pathRewrite: {'^/api' : ''}, changeOrigin: true } }, }, //配置入口, 支持多入口 entry: { page: ROOT_PATH + '/app/src/router/router.jsx', vendors: ['react', 'react-dom', 'react-router', 'mobx'] //第三方库和框架 }, output: { // path: "dist", publicPath: 'dist', filename: 'js/bundle.js' }, module: { loaders: [ { test: /\.css$/, loader: ExtractTextPlugin.extract({ fallback: 'style-loader', use: 'css-loader' })//此处不用loader,改为use }, { test: /\.less$/, loader: ExtractTextPlugin.extract('css-loader!less-loader') }, { test: /\.js[x]?$/, exclude: /node_modules/, loader: 'babel-loader' }, { test: /\.(png|jpg)$/, loader: 'url-loader?limit=8192&name=img/[name].[ext]' }, { test: /\.(woff|woff2|eot|ttf|svg)(\?.*$|$)/, loader: 'url-loader' } ] }, resolve: { extensions: [' ', '.js', '.jsx'] }, plugins: [ new webpack.optimize.CommonsChunkPlugin({ 'name': 'vendors', 'filename': 'js/vendors.js' }), new ExtractTextPlugin("css/bundle.css"), // 如需jquery请解锁 // new webpack.ProvidePlugin({ $: "jquery" }), new webpack.HotModuleReplacementPlugin(), new OpenBrowserPlugin({ url: 'http://localhost:8090/gallery' }) ] }
总结: 如有疑问请参考官方文档 https://doc.webpack-china.org/concepts/
-------------------------------------------
特此声明:所有评论和私信都会在第一时间回复。也欢迎朋友们指正错误,共同进步!
如果觉得这篇文章对你有小小的帮助的话,记得在右下角点个“推荐”哦,博主在此感谢!
个性签名:好记性不如勤随笔,好随笔还请多关注!