–读《谁说前端不需要懂-Nginx反向代理与负载均衡》有感
读了上文发现内容虽然还是挺好的,但看完,为啥要懂nginx呀,负载均衡和前端哪里有什么半毛钱关系了,没说清楚呀。
当然这个面向前端做个科普文让大家多知道一项只是还是不错的,文章拉到最后面看了下作者的使用场景举例说起个 host 给让产品走查。 这不就是起个webserver 容器么,和反向代理么?
这篇内容很热,结合最近聊天群里总是有人问起,我想前端还有很多人想知道这方面知识的,所以在这里也科普下,常用的代理方式有哪些。
招式一、 使用 http-server 模块进行代理
熟悉 nodejs 的朋友应该知道有个非常好和强大的工具模块 http-server 这是一枚小火箭能帮助你直冲云霄,使用方式如下:
首先需要安装 nodejs (对于nodejs 合格的前端应该都安装上了吧?这里就不复述了)。
安装全局模块
npm install http-server -g
然后到你需要运行展示的 html 资源目录执行
http-server -P http://www.your-backend.com/api
http://www.your-backend.com/api 是你后端反向代理的接口地址,你需要修改成你自己的。
然后你就可以使用 http://localhost:8080 进行访问了(如果 8080 端口不被占用掉的话,若占用了你可以 -p 指定其他端口 ),是不是超级 easy? 更多参数可以查询官方文档 http-server。
招式二、使用 webpack 配置代理
webpack 对于前端来说是个强大的工具, 除了能够帮助你打包和启动调试服务器外, 代理的功能也值得你了解下。 惯例上官网资料文档地址
最简方式:
module.exports = {
//...
devServer: {
proxy: {
'/api': 'http://localhost:3000'
}
}
};
上述配置将自动把 /api 这一地址的访问转请求到 http://localhost:3000 从而起到了代理的作用。
如果你的规则需要去掉 api 前缀,你可以使用重写地址的方式。
module.exports = {
//...
devServer: {
proxy: {
'/api': {
target: 'http://localhost:3000',
pathRewrite: {'^/api' : ''}
}
}
}
};
你可能还遇到 https 的安全问题触发未验证的证书错误, 则你可以简单的加上 secure: false 来处理
module.exports = {
//...
devServer: {
proxy: {
'/api': {
target: 'https://other-server.example.com',
secure: false
}
}
}
};
有时你不想代理所有的请求。可以基于一个函数的返回值绕过代理。 在函数中你可以访问请求体、响应体和代理选项。必须返回 false 或路径,来跳过代理请求。 例如:对于浏览器请求,你想要提供一个 HTML 页面,但是对于 API 请求则保持代理。你可以这样做:
proxy: {
"/api": {
target: "http://localhost:3000",
bypass: function(req, res, proxyOptions) {
if (req.headers.accept.indexOf("html") !== -1) {
console.log("Skipping proxy for browser request.");
return "/index.html";
}
}
}
}
多个路径的代理
proxy: [{
context: ["/auth", "/api"],
target: "http://localhost:3000",
}]
总之 webpack 提供了多种灵活的方式, 相信大多时候都能满足到你到要求。
招式三、使用 nodejs 的 node-http-proxy 模块来处理
node-http-proxy 提供了一个可以编程模式的代理环境,如果你有很特殊的需求如session、cookie 已绑定的域处理成其他的域什么,或是内容还要转换处理等,你可以用这个方式来处理复杂的 hacker.
如增加特殊请求头;
var http = require('http'),
httpProxy = require('http-proxy');
var proxy = httpProxy.createProxyServer({});
proxy.on('proxyReq', function(proxyReq, req, res, options) {
proxyReq.setHeader('X-Special-Proxy-Header', 'foobar');
});
var server = http.createServer(function(req, res) {
// You can define here your custom logic to handle the request
// and then proxy the request.
proxy.web(req, res, {
target: 'http://127.0.0.1:5060'
});
});
console.log("listening on port 5050")
server.listen(5050);
招式四、使用框架自带代理方式如 angular 的 proxy.
angular 的 proxy 写法形式和 webpack 基本一样, 你需要一份如下的配置文件 proxy.conf.json 我的开源项目 typerx采用的就是这种方式
{
"/api": {
"target": "http://localhost:5400/",
"secure": false
},
"/user": {
"target": "http://localhost:5400/",
"secure": false
},
"/uploads": {
"target": "http://localhost:5400/",
"secure": false
}
}
配置完成之后使用 proxy-config 参数指定 proxy.conf.json 即可调用代理配置
ng serve --proxy-config proxy.conf.json
其他更多方式 , 如果你看完更多方式是不是觉得和 webpack 是一样的呢,实际上他就是 webpack 哈?
招式五、实际上这个不是代理,但是也能解决你的跨域问题。
open -n /Applications/Google\ Chrome.app/ --args --disable-web-security --user-data-dir=/Users/your/path/
还有个方式当然就是 nginx 啦
你可以继续了解他 谁说前端不需要懂-Nginx反向代理与负载均衡
就是觉得招式12345太麻烦,所以才用的Nginx…
http-server 不是最简单么?
还是用nginx反向代理最方便
线上部署也能用web-pack,angular-cli 这类脚手架来起服务吗?这些一般只能在开发环境上使用吧。
@GGBond1989 http-server 是真的零配置 , nginx 可以零配置么?
@qichangjun webpack , angular-cli 是在开发环境用的好不好, nginx 实际上是生产环境用的,开发环境真的没那么需要。
去懂一个nginx有什么坏处?
技多不压身,当然我也很喜欢你这种对比着学习的精神
@qinkangwu 再次重申不否认 nginx 有价值,在服务端 nginx 是容器之王。 只是在使用 nginx 之前,我想说其他方式是不是更应该掌握?
我现在所有的单页站点都是通过nginx代理出去的。每个单页应用站点占用一个端口。但是会通过nginx代理到80端口。然后通过相对/xxxx/来区分每个站点。还有就是调用别人API的时候可能会出现跨域。可以通过nginx的反向代理配置来解决。我觉得nginx也挺方便的一个conf文件可以干很多事。 不过楼主提到那个几个在开发环境很有用。也需要掌握。
@vellengs 已修改,另外,nginx在本地做开发时确实是没必要的,但真正部署到服务器上还是少不了
你们项目开发完都不用部署到线上环境的吗(╹▽╹)
前端不能只是前端,项目部署到线上还是需要用到nginx,你说的这些平时都是开发用到
@wangchaoduo 部署到线上,如果这样说,是不是还该会点后端哈,恭喜你加入全栈。
@vellengs 很难过在这里再一次看到全栈成为一个贬义词,顺便提问
- 你们开发完不需要发布吗?
- 新项目第一次发布不需要你们自己配环境吗?
@wangchaoduo 我有贬义全栈吗? 发布是运维的职责好不,即使一般的开发环境也是后端搭建或者相关技术负责搭建,这些都非前端本职工作,当然能力可以能者多劳谁也开心呀。
我觉得前端很有必要懂nginx
招式一
nginx 配置
worker_processes 1;
events {
worker_connections 1024;
}
http {
server {
listen 80 default_server;
location / {
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_pass http://127.0.0.1:3333;
}
}
}
两者 header 对比
// http-server
{
"accept": "*/*",
"user-agent": "curl/7.54.0",
"host": "127.0.0.1:3332",
"connection": "close"
}
// nginx
{
"host": "xxxx",
"x-forwarded-for": "127.0.0.1",
"connection": "close",
"user-agent": "curl/7.54.0",
"accept": "*/*"
}
招式二
使用 pathRewrite 的情况
nginx 配置
worker_processes 1;
events {
worker_connections 1024;
}
http {
server {
listen 80 default_server;
location / {
rewrite ^/api/(.*)$ /$1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_pass http://127.0.0.1:3333;
}
}
}
两者 header 对比
// webpack
{
"accept": "*/*",
"user-agent": "curl/7.54.0",
"host": "127.0.0.1:3332",
"connection": "close"
}
// nginx
{
"host": "xxxx",
"x-forwarded-for": "127.0.0.1",
"connection": "close",
"user-agent": "curl/7.54.0",
"accept": "*/*"
}
招式三
自定义 header 的情况
nginx 配置
worker_processes 1;
events {
worker_connections 1024;
}
http {
server {
listen 80 default_server;
location / {
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header x-special-proxy-header foobar;
proxy_pass http://127.0.0.1:3333;
}
}
}
两者 header 对比
// node-http-proxy
{
"accept": "*/*",
"user-agent": "curl/7.54.0",
"host": "xxxx",
"connection": "close",
"x-special-proxy-header": "foobar"
}
// nginx
{
"host": "xxxx",
"x-forwarded-for": "127.0.0.1",
"x-special-proxy-header": "foobar",
"connection": "close",
"user-agent": "curl/7.54.0",
"accept": "*/*"
}
招式四、招式五太麻烦就略了吧。。
综上
nginx 总共改变了两处
rewrite ^/api/(.*)$ /$1;
proxy_set_header x-special-proxy-header foobar;
剩下了
- 了解上面那些工具的时间
- 写工具代码的时间 ( 如果有的话 )
安全又好用,又跟生产环境一致,为啥不用呢。。
讲道理配置这种东西,厚脸皮找运维要一份不就得了。。
写完才发现 7 个月前的帖子了。。