工程化解决前端开发和部署优化的综合问题

今天想跟大家探讨一下如何工程化解决前端开发和部署优化的综合问题;

很多童鞋把前端定义为,切图,html,css,最终扔给服务端

就像这样:


用编辑器写好代码,无需编译,本地预览,确认OK,传到服务器,so easy啊有木有。


然后我们现在来访问页面,查看页面网络请求,就像下面这样:


请求成功啦,返回200,好开心啊。然后就完了吗?


作为一个有节操的程序员这是远远还不够的。

就比如a.css,每次用户访问页面都要重新加载,极其影响性能和浪费带宽,所以我们希望最好这样:


利用304,让浏览器使用本地缓存。

但,这样也就够了吗?

当然不行!304叫协商缓存,还是要和服务器通信一次,我们的优化级别是变态级,所以必须彻底灭掉这个请求,变成这样:


强制浏览器使用本地缓存(cache-control/expires),不要和服务器通信。

好了,请求方面的优化已经达到变态级别,那问题来了:你都不让浏览器发资源请求了,这缓存咋更新?

很好,相信有人想到了办法:通过更新页面中引用的资源路径,让浏览器主动放弃缓存,加载新资源。像这样:


下次上线,把链接地址改成新的版本不就行了。现在村赞和其他项目都是这样做的啊。

OK,问题解决了么?!当然没有!对于变态级的优化,思考这种情况:


页面引用了3个css,而某次上线只改了其中的a.css,如果所有链接都更新版本,就会导致b.css,c.css的缓存也失效,那岂不是又有浪费了?!

。。。

。。。

重新开启变态模式,我们不难发现,要解决这种问题,必须让url的修改与文件内容关联,也就是说,只有文件内容变化,才会导致相应url的变更,从而实现文件级别的精确缓存控制。

什么东西与文件内容相关呢?那就是利用数据摘要算法获取文件hash,hash值与文件内容一一对应,这样内容发生变化hash值也跟着变。好了,我们把url改成文件的hash值:



这回再有文件修改,就只更新那个文件对应的url了,想到这里貌似很完美了。你觉得这就够了么?

当我要更新静态资源的时候,同时也会更新html中的引用吧,就好像这样:


这次发布,同时改了页面结构和样式,也更新了静态资源对应的url地址,现在要发布代码上线,你来告诉我,是先上线页面,还是先上线静态资源?

先部署页面,再部署资源:在二者部署的时间间隔内,如果有用户访问页面,就会在新的页面结构中加载旧的资源,并且把这个旧版本的资源当做新版本缓存起来,其结果就是:用户访问到了一个样式错乱的页面,除非手动刷新,否则在资源缓存过期之前,页面会一直执行错误。

先部署资源,再部署页面:在部署时间间隔之内,有缓存的用户访问正常;但没缓存或者缓存过期的用就会出现旧版本页面加载新版本资源的情况,导致页面错误,但当页面完成部署,这部分用户再次访问页面又会恢复正常了。

以上得出的结果就是:先部署谁都不成!都会导致部署过程中发生页面错乱的问题。

折中一下等到半夜访问量低的时候偷偷上线,先上静态资源,再部署页面,看起来问题少一些。

但是,对于变态级的优化程度,没有这样的“绝对低峰期”,只有“相对低峰期”。所以为了稳定的服务,还得继续追求极致啊!

要解决这个问题也不难,就是实现 非覆盖式发布。





看上图,用文件的hash值来对资源文件进行重命名,把hash值放到资源文件发布路径中,这样,内容有修改的资源就变成了一个新的文件发布到线上,不会覆盖已有的资源文件。上线过程中,先全量部署静态资源,再灰度部署页面,整个问题就比较完美的解决了。

要注意的是,静态资源的缓存控制要求在前端所有静态资源加载的位置都要做这样的处理 。js、css自不必说,还要包括js、css文件中引用的资源路径,从而形成级联的hash变化,大概示意图就是:


大概的意思就是,一旦图片发生变化,那么引用该图片的js/css(hash)也要跟着变,同时引用js/css的页面也要跟着变。


讲到这,可能你会觉得终于可以完美解决了吧。

还早呢,例举,怎么配合后端写代码,无限膨胀的文件如何维护,垃圾如何清理,资源加载,请求合并,前端框架等等。

总之,这是一个工程问题。前路漫漫。。

以上借鉴了百度,facebook,知乎张云龙等前端优化思路。

妈妈,我再也不玩前端了。。。。5555

。。。

请看下一回《前端架构之模块化开发》

评论  表情