前端打包若何在削减恳求数与操纵并行下载之间找到更优解?
那能够是一个脑洞很大的问题,优化到极限是所有法式员的抱负,但我觉得其实不现实,也无需要。
我履历过的一些公司和计划
群众点评网:那是2013年,点评网的前端手艺还算是比力前沿的。我们有异步的模块加载器
kaelzhang/neuron · GitHub,有私有的保证理计划
Cortex · GitHub。我们几位手艺的抱负主义者,Kael +1 小马哥我们屡次开会讨论前端模块化,前端加载器,前端性能优化的问题。比力抱负的计划是:
代码全数 CommonJS 模块化;
接纳 语义化版本 2.0.0尺度,
线上异步加载模块;
办事器按照各类页面临模块的需求情况通过算法合理的 combo 那些返回给模块加载器。
和题主的设法比力附近。固然不太确定,但 1、2、3 我们是完成了,4 也许永久不会实现。我2013年已经去职,而 Kael、+1 不久前已经去职。翻翻点评页面上的代码(
群众点评网_美食,生活,优惠券,团购右键查看源码)还有昔时抱负的陈迹:
combo 的设置装备摆设输出:
<script> var __loaderCombo = { //http://www.dpfile.com/combos/~s~j~app~promo~placeholder.js,~s~j~app~main~placeholder.js,~s~j~app~main~mbox.js,~s~j~app~promo~mbox.js,~s~j~app~main~biz~mkt.js,~s~j~app~main~bulletin.js,~s~j~app~main~mkt.js,~s~j~app~main~tg-content.js,~lib~1.0~storage~local.js,~lib~1.0~storage~local-expire.js,~lib~1.0~mvp~tpl.js,~lib~1.0~dom~dimension.js,~lib~1.0~suggest.js,~lib~1.0~io~ajax.js,~lib~1.0~io~jsonp.js,~lib~1.0~util~cookie.js,~lib~1.0~util~queue.js,~lib~1.0~util~json.js,~lib~1.0~event~multi.js,~lib~1.0~event~live.js,~lib~1.0~switch~core.js,~lib~1.0~switch~conf.js,~lib~1.0~switch~tabswitch.js,~lib~1.0~switch~carousel.js,~lib~1.0~switch~autoplay.js,~lib~1.0~fx~tween.js,~lib~1.0~fx~easing.js,~lib~1.0~fx~css.js,~lib~1.0~fx~core.js/8b8f8f355aeac43833c8c3ce9c141175,8b8f8f355aeac43833c8c3ce9c141175,e57178e2684d3f7b36e0cc50abdeb01a,755028a19cabfa057e417a7718ededc2,61103b741ca56b4712da46f5556f3907,350a5fe49af6ab08f1307d8c26ff343d,334ea339327782c798b62b8a7916da33,fb0922bab163860af76cebf35fcf2ac6,8602861a2c191a9959f183138c097790,463c113fe9572f1ce5acbbff67710250,681c5b24a9a215968286adb35ea9a1b4,f12f839642deedcc2ef8e2235f146031,ea3b7ce0b29712205015c66468da7d85,85362489ccceac3fc3303ec569dd2b74,08440f9945a0f99cbbcadce7d5b140bf,afe6182c4f181e2d419ebec8c0026a69,f000da58a69731e4d966b79f319a973f,e54951fd409a1f2680a457e395b90dc1,7820a44330e04c9718005bfa97e80bc8,649a5074e678c2ca97609ade4c68ad5f,577271a07070095dc9c4398c1056b735,643e258aedf04b4bd5919ded8263191b,9aedd735203bac14d3da0420f278ee8b,4f1cd478d938e4ece4b5a6cb53b83b02,bb9c320f46054d5277a3aea90fd37747,97c9a39afa1a5d4bee3a0cfe8d5989f3,7e42281ab447ebdb115a133cc38cf03d,183b08c14447afc24ea8435a7500e020,d322a81f5d82047eb2b98912fe53c609.js: [ /s/j/app/promo/placeholder.js, /s/j/app/main/placeholder.js, /s/j/app/main/mbox.js, /s/j/app/promo/mbox.js, /s/j/app/main/biz/mkt.js, /s/j/app/main/bulletin.js, /s/j/app/main/mkt.js, /s/j/app/main/tg-content.js, /lib/1.0/storage/local.js, /lib/1.0/storage/local-expire.js, /lib/1.0/mvp/tpl.js, /lib/1.0/dom/dimension.js, /lib/1.0/suggest.js, /lib/1.0/io/ajax.js, /lib/1.0/io/jsonp.js, /lib/1.0/util/cookie.js, /lib/1.0/util/queue.js, /lib/1.0/util/json.js, /lib/1.0/event/multi.js, /lib/1.0/event/live.js, /lib/1.0/switch/core.js, /lib/1.0/switch/conf.js, /lib/1.0/switch/tabswitch.js, /lib/1.0/switch/carousel.js, /lib/1.0/switch/autoplay.js, /lib/1.0/fx/tween.js, /lib/1.0/fx/easing.js, /lib/1.0/fx/css.js, /lib/1.0/fx/core.js ], //http://www.dpfile.com/combos/~s~j~app~index~city.js,~s~j~app~main~datepicker~superdatepicker.js,~s~j~app~main~datepicker~supercalendar.js,~s~j~app~main~datepicker~calendarmodel.js/10e567965240627f31adeb03a0b5bb9d,d401bfe3cb080f56d3dd5477496085ce,d8f8da0738a40c79c6a6033059fc4f8a,f06dc4c4bf7930ab9e2d04b347c43684.js: [ /s/j/app/index/city.js, /s/j/app/main/datepicker/superdatepicker.js, /s/j/app/main/datepicker/supercalendar.js, /s/j/app/main/datepicker/calendarmodel.js ], //http://www.dpfile.com/combos/~s~j~app~booking~common~datepicker~superdatepicker.js,~s~j~app~booking~common~datepicker~supercalendar.js,~s~j~app~booking~common~datepicker~calendarmodel.js,~s~j~app~booking~mainbookingplugin.js,~s~j~app~booking~reserveregion.js,~s~j~app~activity~vdperweekstarplugin.js,~s~j~app~hotel~index~hotel-shortcut.js,~s~j~app~main~app-2d.js/b3e3cb309221bc1b22a8840110270109,b5eee190bf95f12f9de6d7c22ac69122,f06dc4c4bf7930ab9e2d04b347c43684,1b1894cf4901ba0a3d9303a43b2977d4,9aa72d14ba3ca95811990f050e1bb11c,79cffb62b22c077b849431ba867e8b49,ab65fdf8fa47a417d9e87712210238df,eea8ab135c6a3be13b563abf9f3b706c.js: [ /s/j/app/booking/common/datepicker/superdatepicker.js, /s/j/app/booking/common/datepicker/supercalendar.js, /s/j/app/booking/common/datepicker/calendarmodel.js, /s/j/app/booking/mainbookingplugin.js, /s/j/app/booking/reserveregion.js, /s/j/app/activity/vdperweekstarplugin.js, /s/j/app/hotel/index/hotel-shortcut.js, /s/j/app/main/app-2d.js ] } </script>出名的 version.js :
http://www.dpfile.com/x_x/version.min.v1446634429846.js,看了一眼,那个文件已经大到吓人的地步!
Teambition:我 2013岁尾参加,大型 SPA 应用。整个应用利用 RequireJS AMD 模块化。当地开发时异步加载,超越500个小的资本文件,页面刷新出来可能要10s 以上。所以调试不断是痛点。然,关于线上运行时优化出格少,三个阶段:
全数打包成一个 JS 文件;分红两个 JS 文件,RequireJS 线上运行时 jrburke/almond · GitHub + 第三方依赖一个文件,营业代码一个文件;三个文件,刚刚又看了一下代码:<script src="https://dn-st.teambition.net/libs/bundle/js/index.97e98c88.js"></script> <script src="https://dn-st.teambition.net/teambition/js/deps.7a49b762.js"></script> <script src="https://dn-st.teambition.net/teambition/js/app.f7e98219.js"></script> 详细细节我已经不清晰了,但很可能 RequireJS 线上运行时 jrburke/almond · GitHub+ 必需尽快施行的代码。
陆金所:起首,那是三家公司里面相比照较粗拙比力无脑的计划。
<script type="text/javascript" src="//static.lufaxcdn.com/lufax-public/jquery/jquery.7ebf933b.js"></script> <script type="text/javascript" src="//static.lufaxcdn.com/lufax-components/lufax-components.726a6c1b.js"></script> <script type="text/javascript" src="//static.lufaxcdn.com/lufax-public/lufax-lib/lufax-lib.1413b941.js"></script> <script type="text/javascript" src="//static.lufaxcdn.com/lufax-public/lufax-public/lufax-public.972c53c4.js"></script> <!-- <script type="text/javascript" src="http://hq.sinajs.cn/list=s_sh000001"></script> --> <script type="text/javascript" src="https://static.lufaxcdn.com/home/index/8e0a02698e.index.min.js"></script> <script type="text/javascript" src="//static.lufaxcdn.com/lufax-public/statistic/statistic.69b37206.js"></script>一个页面中的 JavaScript 文件规划(CSS 也是类似,略去不表):
jQuery,对,我们根本上都仍是很根底的 jQuery 代码公共组件,接下来的三个都是,只是更具差别的用处和级别做了划分页面的营业 JavaScript:index.js其他一些统计组件
当然那是表象,那我们代码的背后有什么模块化吗?
代码文件都是用立即施行的函数表达式(Immediately-invoked function expression) 包裹的吗?不是!SeaJS RequireJS AMD CMD?不是!ES6 Module?不是!每个页面的营业代码根本上就是一个文件,接纳全局定名空间实现组件化。
备注:有两三个项目接纳 RequireJS,代码分模块开发的,但线上运行时并非异步加载,而是根据依赖关系,每个页面合并成一个零丁 js 文件(除去多个站点公用的部门);也就是说,在线上,两个页面间的 JS 文件里,有可能包罗了良多不异的代码。
那些计划间的比力:
点评网是三者中最牛逼,最抱负的。但做起的复杂度超乎想象,那也可能是目前还没有完全实现的原因。能够看看
天猫tmall.com--上天猫,就够了(kissy)、
付出宝 知拜托!(sea.js) 恰似都是那种气概的。
Teambition算是比力现实,SPA应用,比力与国际接轨的计划,究竟结果是 SPA 应用。但能够看到,是那三个网站中翻开速度最慢的。所有营业驱动的代码都在 JavaScript 中(HTML + 营业逻辑),有两种可选计划:
拆分为多个 SPA(保举那个)恰当做一些异步加载
陆金所:开发(模块化啥的底子不需要晓得,什么轮回依赖底子不会呈现)无脑,打包(grunt/gulp)无脑,拜候网页看看,慢么,也不慢。
一些概念和结论:
模块化开发是趋向:分而治之,是稳定的事理。无论是传统网页(点评网、陆金所等)仍是 SPA 应用,都需要借力模块化来连结代码的鲁棒性。解耦,独立,不会互相影响。
异步加载按需加载自己有点跑偏的:从 LAB.js 起头,各类各样的加载器都在逃求加载性能,异步加载。希望能够加快页面的加载速度。分模块加载,异步加载的益处其实并没有那么明显,模块太多,或者异步加载,整体的加载实现反而耽误。虽说 HTTP 2.0 能有效削减多个小文件加载消耗在收集上的时间,ES6 也原生供给
https://people.mozilla.org/~jorendorff/js-loaders/Loader.html的撑持,但究竟结果如今还没推广,效果也要现实利用才晓得。
合理分组,同步加载,用好阅读器缓存和 CDN 应该能够处理大部门问题:区分隔发运行时和线上运行时,开发时利用模块化,异步加载器大幅提拔开发体验。线上根据代码更新频度和感化合理分组,合并压缩代码,同步加载三到五个文件。设置装备摆设好静态办事器,利用 CDN,充实操纵阅读器缓存和 CDN,静态资本就不会是性能的瓶颈了。
再说一句,
任何不以场景为前提的设想都是耍地痞,任何太不实在际的抱负末将毁灭,任何想永存的手艺都是临时计划(来自 @玉伯 的回复)。Tags: