前端“智能”静态资源管理 - Onebox - 博客园

前端“智能”静态资源管理

  模块化/组件化开发,仅仅描述了一种开发理念,也可以认为是一种开发规范,倘若你认可这规范,对它的分治策略产生了共鸣,那我们就可以继续聊聊它的具体实现了。

  很明显,模块化/组件化开发之后,我们最终要解决的,就是模块/组件加载的技术问题。然而前端与客户端GUI软件有一个很大的不同:

前端是一种远程部署,运行时增量下载的GUI软件

  前端应用没有安装过程,其所需程序资源都部署在远程服务器,用户使用浏览器访问不同的页面来加载不同的资源,随着页面访问的增加,渐进式的将整个程序下载到本地运行,“增量下载”是前端在工程上有别于客户端GUI软件的根本原因。

  上图展示了一款界面繁多功能丰富的应用,如果采用Web实现,相信也是不小的体量,如果用户第一次访问页面就强制其加载全站静态资源再展示,相信会有很多用户因为失去耐心而流失。根据“增量”的原则,我们应该精心规划每个页面的资源加载策略,使得用户无论访问哪个页面都能按需加载页面所需资源,没访问过的无需加载,访问过的可以缓存复用,最终带来流畅的应用体验。

  这正是Web应用“免安装”的魅力所在。

  由“增量”原则引申出的前端优化技巧几乎成为了性能优化的核心,有加载相关的按需加载、延迟加载、预加载、请求合并等策略;有缓存相关的浏览器缓存利用,缓存更新、缓存共享、非覆盖式发布等方案;还有复杂的BigRender、BigPipe、Quickling、PageCache等技术。这些优化方案无不围绕着如何将增量原则做到极致而展开。

所以我觉得:

前端开发最迫切需要做好的就是在基础架构中贯彻增量原则。

  相信这种贯彻不会随着时间的推移而改变,在可预见的未来,无论在HTTP1.x还是HTTP2.0时代,无论在ES5亦或者ES6/7时代,无论是AMD/CommonJS/UMD亦或者ES6 module时代,无论端内技术如何变迁,我们都有足够充分的理由要做好前端程序资源的增量加载。

  我觉得是在其基础架构中缺少这样一种“智能”的资源加载方案。没有这样的方案,很难将前端应用的规模发展到第四阶段,很难实现落地前面介绍的那种组件化开发方案,也很难让多方合作高效率的完成一项大型应用的开发,并保证其最终运行性能良好。在第四阶段,我们需要强大的工程化手段来管理”玩具般简单“的前端开发。

  在我的印象中,Facebook是这方面探索的伟大先驱之一,早在2010年的Velocity China大会上,来自Facebook的David Wei博士就为业界展示了他们令人惊艳的静态网页资源管理和优化技术。

David Wei博士在当年的交流会上提到过一些关于Facebook的一些产品数据:

Facebook整站有10000+个静态资源;

每个静态资源都有可能被翻译成超过100种语言版本;

每种资源又会针对浏览器生成3种不同的版本;

要针对不同带宽的用户做5种不同的打包方法;

有3、4个不同的用户组,用于小批次体验新的产品功能;

还要考虑不同的送达方法,可以直接送达,或者通过iframe的方式提升资源并行加载的速度;

静态资源的压缩和非压缩状态可切换,用于调试和定位线上问题

  这是一个状态爆炸的问题,将所有状态乘起来,整个网站的资源组合方式会达到几百万种之多(去重之后统计大概有300万种组合方式)。支撑这么大规模前端项目运行的底层架构正是魏博士在那次演讲中分享的Static Resource Management System(静态资源管理系统),用以解决Facebook项目中有关前端工程的3D问题(Development,Deployment,Debugging)。

  那段时间 FIS 项目正好遇到瓶颈,当时的FIS还是一个用php写的task-based构建工具,那时候对于前端工程的认知度很低,觉得前端构建不就是几个压缩优化校验打包任务的组合吗,写好流程调度,就针对不同需求写插件呗,看似非常简单。但当我们支撑越来越多的业务团队,接触到各种不同的业务场景时,我们深刻的感受到task-based工具的粗糙,团队每天疲于根据各种业务场景编写各种打包插件,构建逻辑异常复杂,隐隐看到不可控的迹象。

  我们很快意识到把基础架构放到构建工具中实现是一件很愚蠢的事,试图依靠构建工具实现各种优化策略使得构建变成了一个巨大的黑盒,一旦发生问题,定位起来非常困难,而且每种业务场景都有不同的优化需求,构建工具只能通过静态分析来优化加载,具有很大的局限性,单页面/多页面/PC端/移动端/前端渲染/后端渲染/多语言/多皮肤/高级优化等等资源加载问题,总不能给每个都写一套工具吧,更何况这些问题彼此之间还可以有多种组合应用,工具根本写不过来。

  Facebook的做法无疑为我们亮起了一盏明灯,不过可惜它并不开源(不是技术封锁,而是这个系统依赖FB体系中的其他方面,通用性不强,开源意义不大),我们只能尝试挖掘相关信息,网上对它的完整介绍还是非常非常少,分析facebook的前端代码也没有太多收获,后来无意中发现了facebook使用的项目管理工具phabricator中的一个静态管理方案Celerity,以及相关的说明,看它的描述很像是Facebook静态资源管理系统的一个mini版!

  简单看过整个系统之后发现原理并不复杂(小而美的典范),它是通过一个小工具扫描所有静态资源,生成一张资源表,然后有一个PHP实现的资源管理框架(Celerity)提供了资源加载接口,替代了传统的script/link等静态的资源加载标签,最终通过查表来加载资源。

虽然没有真正看过FB的那套系统,但眼前的这个小小的框架给了当时的我们足够多的启示:

静态资源管理系统 = 资源表 + 资源加载框架

  多么优雅的实现啊!

  资源表是一份数据文件(比如JSON),是项目中所有静态资源(主要是JS和CSS)的构建信息记录,通过构建工具扫描项目源码生成,是一种k-v结构的数据,以每个资源的id为key,记录了资源的类别、部署路径、依赖关系、打包合并等内容,比如:

{

"a.js": {

"url": "/static/js/a.5f100fa.js",

"dep": [ "b.js", "a.css" ]

},

"a.css": {

"url": "/static/css/a.63cf374.css",

"dep": [ "button.css" ]

},

"b.js": {

"url": "/static/js/b.97193bf.js"

},

"button.css": {

"url": "/static/css/button.de33108.js"

}

}

  而资源加载框架则提供一些资源引用的API,让开发者根据id来引用资源,替代静态的script/link标签来收集、去重、按需加载资源。调用这些接口时,框架通过查表来查找资源的各项信息,并递归查找其依赖的资源的信息,然后我们可以在这个过程中实现各种性能优化算法来“智能”加载资源。

  根据业务场景的不同,加载框架可以在浏览器中用JS实现,也可以是后端模板引擎中用服务端语言实现,甚至二者的组合,不一而足。

  这种设计很快被验证具有足够的灵活性,能够完美支撑不同团队不同技术规范下的性能优化需求,前面提到的按需加载、延迟加载、预加载、请求合并、文件指纹、CDN部署、Bigpipe、Quickling、BigRender、首屏CSS内嵌、HTTP 2.0服务端推送等等性能优化手段都可以很容易的在这种架构上实现,甚至可以根据性能日志自动进行优化(Facebook已实现)。

  因为有了资源表,我们可以很方便的控制资源加载,通过各种手段在运行时计算页面的资源使用情况,从而获得最佳加载性能。无论是前端渲染的单页面应用,还是后端渲染的多页面应用,这种方法都同样适用。

  此外,它还很巧妙的约束了构建工具的职责——只生成资源表。资源表是非常通用的数据结构,无论什么业务场景,其业务代码最终都可以被扫描为相同结构的表数据,并标记资源间的依赖关系,有了表之后我们只需根据不同的业务场景定制不同的资源加载框架就行了,从此彻底告别一个团队维护一套工具的时代!!!

恩,如你所见,虽然彻底告别了一个团队一套工具的时代,但似乎又进入了一个团队一套框架的时代。其实还是有差别的,因为框架具有很大的灵活性,而且不那么黑盒,采用框架实现资源管理相比构建更容易调试、定位和升级变更。

  深耕静态资源加载框架可以带来许多收益,而且有足够的灵活性和健壮性面向未来的技术变革,这个我们留作后话。

  本文来自http://github.com/fouber/blog,著作权属于原作者@前端农名工。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/248937.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【转】几张图看懂列式存储

几张图看懂列式存储 转载于:https://www.cnblogs.com/apeway/p/10870211.html

hive -e和hive -f的区别(转)

大家都知道,hive -f 后面指定的是一个文件,然后文件里面直接写sql,就可以运行hive的sql,hive -e 后面是直接用双引号拼接hivesql,然后就可以执行命令。 但是,有这么一个东西,我的sql当中有一个s…

我们是如何做好前端工程化和静态资源管理 - 無雄 - 博客园

我们是如何做好前端工程化和静态资源管理 随着互联网的发展,我们的业务也日益变得更加复杂且多样化起来,前端工程师也不再只是做简单的页面开发这么简单,我们需要面对的十分复杂的系统性问题,例如,业务愈来愈复杂&…

Mybatis-plus之RowBounds实现分页查询

物理分页和逻辑分页 物理分页:直接从数据库中拿出我们需要的数据,例如在Mysql中使用limit。 逻辑分页:从数据库中拿出所有符合要求的数据,然后再从这些数据中拿到我们需要的分页数据。 优缺点 物理分页每次都要访问数据库&#xf…

常见的6种JavaScript设计模式

常见的6种JavaScript设计模式 构造函数模式 /*** 构造一个动物的函数 */ function Animal(name, color){this.name name;this.color color;this.getName function(){return this.name;} } // 实例一个对象 var cat new Animal(猫, 白色); console.log( cat.getName() );工…

峰度(Kurtosis)和偏度(Skewness)

峰度(Kurtosis) 定义峰度又称峰态系数,表征概率密度分布曲线在平均值处峰值高低的特征数,即是描述总体中所有取值分布形态陡缓程度的统计量。直观看来,峰度反映了峰部的尖度。这个统计量需要与正态分布相比较。 公式定…

1.27

测试程序提出问题并解决转载于:https://www.cnblogs.com/JustinTimberlake/p/10028870.html

javascript设计模式系列 - LukeLin - 博客园

javascript设计模式系列 创建型: 1.抽象工厂模式(Abstract Factory) 2.构建者模式(Builder) 3.工厂方法模式(Factory Method) 4.原型模式(Prototype) 5.单例模式&a…

多功能嵌入式解码软件(2)

多功能嵌入式解码软件(2) 验证类库 通信协议 下面进行一个示例: 下位机需要向上位机发送3中数据帧,数据帧以功能码来识别,每种数据帧的协议如下3个表格所示,上位机需要把这些数据按照协议解码出来&#xff…

vue项目如何打包扔向服务器 - Hi-Sen - 博客园

当我们将 vue 项目完成后,面临的就是如何将项目进行打包上线,放到服务器中。我使用的是 vue-cli(simple) 脚手架,所以就讲一下如何将项目进行打包,并放到 tomcat 上。 如果是 vue-cli (非 simple 脚手架…

MySQL备份与恢复-mysqldump备份与恢复

这片博文主要用来介绍MySQL的备份与恢复: MySQL的备份形式可以分为如下几种: 热备----即不停机备份冷备----需要关闭MySQL,然后备份其数据文件。(停机备份一般是直接拷贝其datadir目录)温备----在线备份,对…

第六次实训作业异常处理

第六次实训作业异常处理 编写一个类ExceptionTest,在main方法中使用try-catch-finally语句结构实现:在try语句块中,编写两个数相除操作,相除的两个操作数要求程序运行时用户输入;在catch语句块中,捕获被0除…

k8s学习笔记-调度之Affinity

Kubernetes中的调度策略可以大致分为两种 一种是全局的调度策略,要在启动调度器时配置,包括kubernetes调度器自带的各种predicates和priorities算法,具体可以参看上一篇文章; 另一种是运行时调度策略,包括nodeAffinity…

vue-cli webpack配置分析 - chenBright - SegmentFault 思否

相信vue使用者对vue-cli都不会陌生,甚至可以说,很熟悉了,但对其webpack的配置可能知之甚少吧。 过完年回来后,我接手了公司的新项目。新项目是一个spa。很自然,我就想到了vue-cli脚手架了,当时研究一下它的…

[Xcode 实际操作]六、媒体与动画-(6)使用UIBlurEffect给图片添加模糊效果

目录:[Swift]Xcode实际操作 本文将演示如何给图像添加模糊效果。 在项目导航区,打开视图控制器的代码文件【ViewController.swift】 1 import UIKit2 3 class ViewController: UIViewController {4 5 override func viewDidLoad() {6 super.…

MapReduce编程实践

一、MapReduce编程思想 学些MapRedcue主要是学习它的编程思想,在MR的编程模型中,主要思想是把对数据的运算流程分成map和reduce两个阶段: Map阶段:读取原始数据,形成key-value数据(map方法)。即…

webpack基础+webpack配置文件常用配置项介绍+webpack-dev-server - QxQstar - 博客园

一.webpack基础 1.在项目中生成package.json:在项目根目录中输入npm init,根据提示输入相应信息。(也可以不生成package.json文件,但是package.json是很有用的,所有建议生成) 2.安装webpaack a.在全局中安装…

(十)

空转载于:https://www.cnblogs.com/shanae/p/10034479.html

编译原理--NFA/DFA

现成的, 讲义: https://www.cnblogs.com/AndyEvans/p/10240790.html https://www.cnblogs.com/AndyEvans/p/10241031.html 一个例子, 写得非常好. 一下子就全明白了, 尤其是像我这种没有听过编译原理课程的人. https://blog.csdn.net/tyler_download/article/details/53139240 …

Python中pass的用法

空语句 do nothing保证格式完整保证语义完整以if语句为例,在c或c/java中: if(true); //do nothingelse{ //do something}对应于python就要这样写: if true: pass #do nothingelse: #do something 1 pass语句在函数中的作用当你在编写一个程序…