查看原文
其他

【第408期】Nginx能为前端开发带来什么?

黎腾 前端早读课 2019-10-10

前言

Nginx这个词在服务端中很常见,但在前端中能解决什么问题呢?今天就来分享分享这个应用。


刚好昨天跟一个同事在聊这个他们遇到的问题,前端做完后的页面不通过服务端(也就是静态页)直接发布上去,连页面上的链接都不需要程序员修改,但页面中又会涉及到一些静态资源的引用,那办法就是在页面上都写死定好的请求地址了。那么问题来了,在开发环境下如何搞?回归到平常我们代理调试页面,除了charles,fiddle之外,今天的主角也是可以的。


正文从这开始~

Nginx,一名网红(网络服务器红人…),就算没有自传和回忆录,争着介绍它的花边新闻也该有吧。

后来找到仅有的一两本书籍,也直接深入到“源码剖析”的阶段。写得并不十分满意,况且我还不需要这些。
后来发现了原因,大概是因为“使用太简单了,都不值得出书”。
是的,Nginx把纷繁复杂的功能,浓缩成一份简单的配置,极易上手。
当它呈现到你面前时,感觉独具匠心。


Nginx与NodeJs

(这里的标题有点歧义。此处的NodeJs,皆引申为NodeJs所搭建的服务器。)

有人说,作为一名前端,我的真爱是NodeJs。
同时也认同,抛去性能之类的比较,单纯从实现的角度,NodeJs编写的服务器也能实现Nginx的各种功能。

这些我都赞成,但使用Nginx并不意味着抛弃NodeJs。事实上,它们并不冲突,还可以在一起愉快的玩耍。

在业内,这样的模型已很常见:资源转发,反向代理,静态资源处理,负载均衡,这些事情扔给Nginx来处理,只是几行配置的事情;同时在上游,让NodeJs去处理它最擅长的I/O等事情。

合理分配各自擅长的事情,这样的思路,同样可以运用于前端开发中。

以前用NodeJs几百行实现的服务器功能,在npm与github的海洋里花尽心思去寻找的模块,也许在Nginx里是一条成熟的配置。它能帮其分担很多事情,节约了成本。


场景一:环境切换

前端开发中,经常面临多个部署环境切换的问题。
我们通常用配hosts的方式去实现。更优化些,我们将机器的服务绑定了不同的域名:比如正式环境是a.qq.com,测试环境是test.a.qq.com。

然而在拓展性和易用性方面,还不足够好。
而Nginx作为反向代理,就很容易处理资源转发的问题。


思路很简单:

读取请求里的cookie,如果键名host_id有值,则代理到这个IP地址;

如果没有,则代理到默认的正式环境(此处举例为1.1.1.1);


那接下来的事情,就是怎样用最简便的方式,把IP种在cookie里?

我们应用了nginx-http-footer-filter模块,html文件经过代理时,都注入了一小段js代码。

这段代码,会帮我们展示小菜单,点击某个环境时,则将IP种到cookie里,同时刷新页面,让Nginx完成环境切换。


切换环境,如今只需点击一次。


场景二:SourceMap

在线上环境调试Js代码是件麻烦的事情,因为目前合格的前端部署,代码都应经过压缩。性能问题是优化了,debug可不怎么方便。

而SourceMap正好可以解决此问题。

在最新的各版本浏览器里,如果满足:

1)压缩后的js文件后面有//# sourceMappingURL=xxx.map格式的注释

2)浏览器能正常访问到sourceMappingURL


那么,就能把压缩过的代码还原。要实现这样的功能,就必须:

1)现网环境不带以上形式的注释,同时访问不到sourceMap(安全性考虑)

2)测试环境带注释,能访问sourceMap

这样的模型,用反向代理+内容纂改的思路再合适不过。


每次构建编译时,我们会把sourceMap文件存放到一台机器(举例为1.1.1.1),命名为js文件名后加.map后缀。随后,使用Nginx,通过这几行配置就能把此功能实现:


只要经过代理,在chrome里,我们能看到每份被压缩过的js文件,都有一个对应的源码文件。

你可以直接使用它来做打断点之类的操作,大大的提升了调试质量。


场景三:内容纂改

其实在以上两个场景里,都涉及了“内容纂改”。
无论是说“纂改”还是“劫持”,大家的印象都不是什么好事情,但另一方面,他们又可以让事情有趣起来。


统一介绍下,Nginx涉及纂改的模块有:

1)nginx_http_footer_filter:往文件的底部添加文字,可包含Nginx的内置变量;

2)nginx_http_addition_module:从一个url去读取内容,将之添加到文件的头部或顶部;

3)nginx_http_sub_module:替换字符


除去上面两种场景,合理运用这些模块对应的配置,可以做出许多小工具,这是很有想象力的事情。


单单针对移动web前端开发,就可以实现:

1)将weinre脚本插入到html里,让移动web调试更加便捷。

2)移动web经常用到localStorage优化首屏,但debug时又会受到干扰,通过一个按钮很方便的清除本地缓存。

3)手机APP内嵌页面,很难将其网址分享给另一个人。通过一个按钮就能生成url对应的二维码等


场景四:本地映射

在Windows下的前端抓包调试,Fiddler+Willow的能力毋庸置疑。
而脱离了.NET体系的Linux和Mac,即使有一些代替工具,但某些方面还是略显不足。


比如:线上接口映射到本地文件。
想到Fiddler的本质也是一个代理,而开启一个有这样能力的Nginx服务,并不是太难的事情。

而且,我们可以做得更灵活,比如:

1)同时支持慢速调试

2)同时支持目录层级映射

3)同时支持正则匹配

4)JSON返回的数据有可能是变化的(比如分页时候),同时支持动态数据


这些场景,只运用到Nginx里的“rewrite规则”。
从参考的文档可以大致看到,rewrite规则非常灵活,能完成各种场景的转发。

最简单的模型中,我们把所有带cgi-bin路径的请求,rewite到本地的一个服务,同时带上请求的所有参数,
仅需这三行配置即可:


后续的事情,可以在本地创建一个cgi-bin文件夹,在里面放置需要映射的文本,并开启服务到8080端口即可。


场景五:移动侧调试

Fiddler 有一个勾选项 Allow remotecomputers to connect,并可以指定 listen port 可以使得手机/其它终端通过将本机设为代理而访问本机环境,与 hosts 配合会很实用。

这个功能,用Nginx也很容易做到。
通过 default_server 作为代理,手机终端通过设置网络代理为本机IP和相应的 listen port,从而可以访问本机的 Web 服务。

其中也是用到了ngx_http_proxy_module模块的配置:


边角料

除去特定场景,Nginx的一些配置也跟前端息息相关。以下简单罗列,作为边角材料。

1.nginx_http_concat
资源合并,处理CDN combo。例如通过这样的方式http://example.com/??style1.css,style2.css,foo/style3.css访问合并后的资源。

2.ngx_http_image_filter_module
图片处理。提供图片缩放,jpg压缩,旋转等特性。

3.适配PC与移动web
总体可运用ngx_http_proxy_module,去实现路径转发。判断平台类型的Nginx配置,在开源项目detectmobilebrowsers中可以找到。


后记

学习Nginx,我本身只是出于开开眼界的目的。而的确发现了一些很有启发性的特质。
于前端开发,无论线上线下,熟练掌握基本配置,可以做出许多提高效率的工具。
但既然是工具,熟手就好。

比如Fiddler直观,但Nginx更底层,更灵活,应当按照实际选择即可。

话说回来,后来心情有些惆怅。
想起之前,我用NodeJs写过一个八百行的本地调试服务,如今更习惯用Nginx的几行配置。
不过我又想,既然我已经花了时间去写,为什么还要花时间去用?!

心情又好起来了。(等等有什么不对,管它呢…)


后语

昨天早上我还特意去豆瓣看了下,有没关于Nginx相关的书,还真有一本关于介绍这块的,只能感叹互联网随便一个点就是一本书的节奏。


关于本文

作者:@imweb黎腾

来源:imweb社区


长按图片识别图中二维码


    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存