首页vns威尼斯城官网登入 › 传输层面的从来都是优化的核心点,页面内CSS文件会阻塞渲染

传输层面的从来都是优化的核心点,页面内CSS文件会阻塞渲染

资源加载

解决冗余便抛开了历史的包袱,是前端优化的第一步也是比较难的一步,但模块拆分也将全站分成了很多小的模块,载入的资源分散会增加请求数;如果全部合并,会导致首屏加载不需要的资源,也会导致下一个页面不能使用缓存,如何做出合理的入口资源加载规则,如何合理的善用缓存,是前端优化的第二步。

经过几次性能优化对比,得出了一个较优的首屏资源加载方案:


核心框架层:mvc骨架、异步模块加载器(require&seajs)、工具库(zepto、underscore、延迟加载)、数据请求模块、核心依赖UI(header组件消息类组件)

② 业务公共模块:入口文件(require配置,初始化工作、业务公共模块)

③ 独立的page.js资源(包含template、css),会按需加载独立UI资源

④ 全局css资源

图片 1

这里如果追求极致,libs.js、main.css与main.js可以选择合并,划分结束后便可以决定静态资源缓存策略了。

MD5时代

为了解决以上问题我们开始使用md5码的方式为静态资源命名:

<script type="text/javascript" src="libs_md5_1234.js"></script>

每次框架更新便不做文件覆盖,直接生成一个唯一的文件名做增量发布,这个时候如果框架先发布,待业务发布时便已经存在了最新的代码;当业务先发布框架没有新的时,便继续沿用老的文件,一切都很美好,虽然业务开发偶尔会抱怨每次都要向框架拿MD5映射,直到框架一次BUG发生。

Hybrid载入

如果是Hybrid的话,情况有所不同,需要将公共资源打包至native中,业务类就不要打包了,否则native会越来越大。

 

localstorage缓存

也会有团队将静态资源缓存至localstorage中,以期做离线应用,但是我一般用它存json数据,没有做过静态资源的存储,想要尝试的朋友一定要做好资源更新的策略,然后localstorage的读写也有一定损耗,不支持的情况还需要做降级处理,这里便不多介绍。

localstorage缓存

也会有团队将静态资源缓存至localstorage中,以期做离线应用,但是我一般用它存json数据,没有做过静态资源的存储,想要尝试的朋友一定要做好资源更新的策略,然后localstorage的读写也有一定损耗,不支持的情况还需要做降级处理,这里便不多介绍。


浏览器缓存可用时会使用缓存资源,这个时候可以避免请求体的传输,对性能有极大提高

时间戳更新

只要服务器配置,浏览器本身便具有缓存机制,如果要使用浏览器机制作缓存,势必关心一个何时更新资源问题,我们一般是这样做的:

<script type="text/javascript"
src="libs.js?t=20151025"></script>

1
<script type="text/javascript" src="libs.js?t=20151025"></script>

每次框架更新便不做文件覆盖,直接生成一个唯一的文件名做增量发布,这个时候如果框架先发布,待业务发布时便已经存在了最新的代码;当业务先发布框架没有新的时,便继续沿用老的文件,一切都很美好,虽然业务开发偶尔会抱怨每次都要向框架拿MD5映射,直到框架一次BUG发生。

消灭冗余

我们这里做的第一个事情便是消除优化路上第一个拦路虎:代码冗余(做代码精简),单从一个页面的加载来说,他需要以下资源:

① 框架MVC骨架模块&框架级别CSS

② UI组件(header组件、日历、弹出层、消息框......)

③ 业务HTML骨架

④ 业务CSS

⑤ 业务Javascript代码

⑥ 服务接口服务

因为产品&视觉会经常折腾全站样式加之UI的灵活性,UI最容易产生冗余的模块。

构建工具

要完成前端工程化,少不了工程化工具,requireJS与grunt的出现,改变了业界前端代码的编写习惯,同时他们也是推动前端工程化的一个基础。

requireJS是一伟大的模块加载器,他的出现让javascript制作多人维护的大型项目变成了事实;grunt是一款javascript构建工具,主要完成压缩、合并、图片压缩合并等一系列工作,后续又出了yeoman、Gulp、webpack等构建工具。

这里这里要记住一件事情,我们的目的是完成前端工程化,无论什么模块加载器或者构建工具,都是为了帮助我们完成目的,工具不重要,目的与思想才重要,所以在完成工程化前讨论哪个加载器好,哪种构建工具好是舍本逐末的。

 

 

 

 

 

 

 

 

 

 

 

 

其它工程化的体现

又比如,前端模板是将html文件解析为function函数,这一步骤完全可以在发布阶段,将html模板转换为function函数,免去了生产环境的大量正则替换,效率高还省电;

然后ajax接口数据的缓存也直接在数据请求底层做掉,让业务轻松实现接口数据缓存;

而一些html压缩、预加载技术、延迟加载技术等优化点便不一一展开……

CSS Sprite

由于现代浏览器的与解析机制,在拿到一个页面的时候马上会分析其静态资源,然后开线程做下载,这个时候反而会影响首屏渲染,如图(模拟2G):

图片 2

图片 3

如果做fake页优化的话,便需要将样式也做异步载入,这样document载入结束便能渲染页面,2G情况都能3S内可见页面,大大避免白屏时间,而后面的单个背景图片便是需要解决的工程问题。

CSS Sprite旨在降低请求数,但是与去处冗余问题一样,半年后一个CSS
Sprite资源反而不好维护,容易烂掉,grunt有一插件支持将图片自动合并为CSS
Sprite,而他也会自动替换页面中的背景地址,只需要按规则操作即可。

PS:其它构建工具也会有,各位自己找下吧

CSS Sprite构建工具:

正确的使用该工具便可以使业务开发摆脱图片合并带来的痛苦,当然一些弊端需要去克服,比如在小屏手机使用小屏背景,大屏手机使用大屏背景的处理办法

MD5时代

为了解决以上问题我们开始使用md5码的方式为静态资源命名:

<script type="text/javascript" src="libs_md5_1234.js"></script>

 

每次框架更新便不做文件覆盖,直接生成一个唯一的文件名做增量发布,这个时候如果框架先发布,待业务发布时便已经存在了最新的代码;当业务先发布框架没有新的时,便继续沿用老的文件,一切都很美好,虽然业务开发偶尔会抱怨每次都要向框架拿MD5映射,直到框架一次BUG发生。

 

渲染优化

当请求资源落地后便是浏览器的渲染工作了,每一次操作皆可能引起浏览器的重绘,在PC浏览器上,渲染对性能影响不大,但因为配置原因,渲染对移动端性能的影响却非常大,错误的操作可能导致滚动迟钝、动画卡帧,大大降低用户体验。

减少重绘、减少回流降低渲染带来的耗损基本人尽皆知了,但是引起重绘的操作何其多,每次重绘的操作又何其微观:

① 页面滚动

② javascript交互

③ 动画

④ 内容变化

⑤ 属性计算(求元素的高宽)

……

与请求优化不同的是,一些请求是可以避免的,但是重绘基本是不可避免的,而如果一个页面卡了,这么多可能引起重绘的操作,如何定位到渲染瓶颈在何处,如何减少这种大消耗的性能影响是真正应该关心的问题。

服务器资源合并

之前与淘宝的一些朋友做过交流,发现他们居然做到了零散资源在服务器端做合并的地步了......这方面我们还是望洋兴叹吧

传输层面:减少请求数,降低请求量
执行层面:减少重绘&回流

拆分页面

一个PC业务页面,其模块是很复杂的,这个时候可以将之分为多个模块:

图片 4

一经拆分后,页面便是由业务组件组成,只需要关注各个业务组件的开发,然后在主控制器中组装业务组件,这样主控制器对页面的控制力度会增加。

业务组件一般重用性较低,会产生模块间的业务耦合,还会对业务数据产生依赖,但是主体仍然是HTML&CSS&Javascript,这部分代码也是经常导致冗余的,如果能按模块拆分,可以很好的控制这一问题发生:

图片 5

按照上述的做法现在的加载规则是:

① 公共样式文件

② 框架文件,业务入口文件

③ 入口文件,异步加载业务模块,模块内再异步加载其它资源

这样下来业务开发时便不需要引用样式文件,可以最大限度的提升首屏载入速度;需要关注的一点是,当异步拉取模块时,内部的CSS加载需要一个规则避免对其它模块的影响,因为模块都带有样式属性,页面回流、页面闪烁问题需要关注。

一个实际的例子是,这里点击出发后的城市列表便是一个完整的业务组件,城市选择的资源是在点击后才会发生请求,而业务组件内部又会细分小模块,再细分的资源控制由实际业务情况决定,过于细分也会导致理解和代码编写难度上升:

图片 6图片 7

demo演示地址,代码地址

如果哪天需求方需要用新的城市选择组件,便可以直接重新开发,让业务之间使用最新的城市列表即可,因为是独立的资源,所以老的也是可以使用的。

只要能做到UI级别的拆分与页面业务组件的拆分,便能很好的应付样式升级的需求,这方面冗余只要能避过,其它冗余问题便不是问题了,有两个规范最好遵守:

JavaScript

1 避免使用全局的业务类样式,就算他建议你使用 2 避免不通过接口直接操作DOM

1
2
1 避免使用全局的业务类样式,就算他建议你使用
2 避免不通过接口直接操作DOM

冗余是首屏载入速度最大的拦路虎,是历史形成的包袱,只要能消除冗余,便能在后面的路走的更顺畅,这种组件化编程的方法也能让网站后续的维护更加简单。

拆分页面

一个PC业务页面,其模块是很复杂的,这个时候可以将之分为多个模块:

图片 8

一经拆分后,页面便是由业务组件组成,只需要关注各个业务组件的开发,然后在主控制器中组装业务组件,这样主控制器对页面的控制力度会增加。

业务组件一般重用性较低,会产生模块间的业务耦合,还会对业务数据产生依赖,但是主体仍然是HTML&CSS&Javascript,这部分代码也是经常导致冗余的,如果能按模块拆分,可以很好的控制这一问题发生:

图片 9

按照上述的做法现在的加载规则是:

① 公共样式文件

② 框架文件,业务入口文件

③ 入口文件,异步加载业务模块,模块内再异步加载其它资源

这样下来业务开发时便不需要引用样式文件,可以最大限度的提升首屏载入速度;需要关注的一点是,当异步拉取模块时,内部的CSS加载需要一个规则避免对其它模块的影响,因为模块都带有样式属性,页面回流、页面闪烁问题需要关注。

一个实际的例子是,这里点击出发后的城市列表便是一个完整的业务组件,城市选择的资源是在点击后才会发生请求,而业务组件内部又会细分小模块,再细分的资源控制由实际业务情况决定,过于细分也会导致理解和代码编写难度上升:

图片 10

图片 11

demo演示地址,代码地址

如果哪天需求方需要用新的城市选择组件,便可以直接重新开发,让业务之间使用最新的城市列表即可,因为是独立的资源,所以老的也是可以使用的。

只要能做到UI级别的拆分与页面业务组件的拆分,便能很好的应付样式升级的需求,这方面冗余只要能避过,其它冗余问题便不是问题了,有两个规范最好遵守:

1 避免使用全局的业务类样式,就算他建议你使用
2 避免不通过接口直接操作DOM

冗余是首屏载入速度最大的拦路虎,是历史形成的包袱,只要能消除冗余,便能在后面的路走的更顺畅,这种组件化编程的方法也能让网站后续的维护更加简单。

降低请求量

① 开启GZip

② 优化静态资源,jQuery->Zepto、阉割IScroll、去除冗余代码

③ 图片无损压缩

④ 图片延迟加载

⑤ 减少Cookie携带

 

很多时候,我们也会采用类似“时间换空间、空间换时间”的做法,比如:


缓存为王,对更新较缓慢的资源&接口做缓存(浏览器缓存、localsorage、application
cache这个坑多)

② 按需加载,先加载主要资源,其余资源延迟加载,对非首屏资源滚动加载


fake页技术,将页面最初需要显示Html&Css内联,在页面所需资源加载结束前至少可看,理想情况是index.html下载结束即展示(2G
5S内)

④ CDN

 

从工程的角度来看,上述优化点半数以上是重复的,一般在发布时候就直接使用项目构建工具做掉了,还有一些只是简单的服务器配置,开发时不需要关注。

可以看到,我们所做的优化都是在减少请求数,降低请求量,减小传输时的耗时,或者通过一个策略,优先加载首屏渲染所需资源,而后再加载交互所需资源(比如点击时候再加载UI组件),Hybrid
APP这方面应该尽可能多的将公共静态资源放在native中,比如第三方库,框架,UI甚至城市列表这种常用业务数据。

 

工程化&前端优化

所谓工程化,可以简单认为是将框架的职责拓宽再拓宽,主旨是帮业务团队更好的完成需求,工程化会预测一些常碰到的问题,将之扼杀在摇篮,而这种路径是可重用的,是具有可持续性的,比如第一个优化去除冗余,是在多次去除冗余代码,思考冗余出现的原因而最终思考得出的一个避免冗余的方案,前端工程化需要考虑以下问题:

重复工作;如通用的流程控制机制,可扩展的UI组件、灵活的工具方法
重复优化;如降低框架层面升级带给业务团队的耗损、帮助业务在无感知情况下做掉大部分优化(比如打包压缩什么的)
开发效率;如帮助业务团队写可维护的代码、让业务团队方便的调试代码(比如Hybrid调试)

1
2
3
重复工作;如通用的流程控制机制,可扩展的UI组件、灵活的工具方法
重复优化;如降低框架层面升级带给业务团队的耗损、帮助业务在无感知情况下做掉大部分优化(比如打包压缩什么的)
开发效率;如帮助业务团队写可维护的代码、让业务团队方便的调试代码(比如Hybrid调试)

其它工程化的体现

又比如,前端模板是将html文件解析为function函数,这一步骤完全可以在发布阶段,将html模板转换为function函数,免去了生产环境的大量正则替换,效率高还省电;

然后ajax接口数据的缓存也直接在数据请求底层做掉,让业务轻松实现接口数据缓存;

而一些html压缩、预加载技术、延迟加载技术等优化点便不一一展开......

 

结语

今天我们站在工程化的层面总结了前几次性能优化的一些方法,以期在后续的项目开发中能直接绕过这些性能的问题。

前端优化仅仅是前端工程化中的一环,结合之前的代码开发效率探讨(【组件化开发】前端进阶篇之如何编写可维护可升级的代码),后续我们会在前端工具的制作使用、前端监控等环节做更多的工作,期望更大的提升前端开发的效率,推动前端工程化的进程。

本文关联的代码:

1 赞 6 收藏 2
评论

图片 12

结语

今天我们站在工程化的层面总结了前几次性能优化的一些方法,以期在后续的项目开发中能直接绕过这些性能的问题。

前端优化仅仅是前端工程化中的一环,结合之前的代码开发效率探讨(【组件化开发】前端进阶篇之如何编写可维护可升级的代码),后续我们会在前端工具的制作使用、前端监控等环节做更多的工作,期望更大的提升前端开发的效率,推动前端工程化的进程。

这段时间对项目做了一次整体的优化,全站有了20%左右的提升(本来载入速度已经1.2S左...

localstorage缓存

也会有团队将静态资源缓存至localstorage中,以期做离线应用,但是我一般用它存json数据,没有做过静态资源的存储,想要尝试的朋友一定要做好资源更新的策略,然后localstorage的读写也有一定损耗,不支持的情况还需要做降级处理,这里便不多介绍。

CSS Sprite

由于现代浏览器的与解析机制,在拿到一个页面的时候马上会分析其静态资源,然后开线程做下载,这个时候反而会影响首屏渲染,如图(模拟2G):

图片 13

图片 14

如果做fake页优化的话,便需要将样式也做异步载入,这样document载入结束便能渲染页面,2G情况都能3S内可见页面,大大避免白屏时间,而后面的单个背景图片便是需要解决的工程问题。

CSS Sprite旨在降低请求数,但是与去处冗余问题一样,半年后一个CSS
Sprite资源反而不好维护,容易烂掉,grunt有一插件支持将图片自动合并为CSS
Sprite,而他也会自动替换页面中的背景地址,只需要按规则操作即可。

PS:其它构建工具也会有,各位自己找下吧

CSS Sprite构建工具:

正确的使用该工具便可以使业务开发摆脱图片合并带来的痛苦,当然一些弊端需要去克服,比如在小屏手机使用小屏背景,大屏手机使用大屏背景的处理办法

UI组成

项目之初,分层较好的团队会有一个公共的CSS文件(main.css),一个业务CSS文件,main.css包含公共的CSS,并且会包含所有的UI的样式:

图片 15

半年后业务频道增,UI组件需求一多便容易膨胀,弊端马上便暴露出来了,最初main.css可能只有10K,但是不出半年就会膨胀至100K,而每个业务频道一开始便需要加载这100K的样式文件页面,但是其中多数的UI样式是首屏加载用不到的。

所以比较好的做法是,main.css只包含最核心的样式,理想情况是什么业务样式功能皆不要提供,各个UI组件的样式打包至UI中按需加载:

图片 16

如此UI拆分后,main.css总是处于最基础的样式部分,而UI使用时按需加载,就算出现两个相同组件也不会导致多下载资源。

seed.js时代

突然一天框架发现一个全局性BUG,并且马上做出了修复,业务团队也马上发布上线,但这种事情出现第二次、第三次框架这边便压力大了,这个时候框架层面希望业务只需要引用一个不带缓存的seed.js,seed.js要怎么加载是他自己的事情:

<script type="text/javascript" src="seed.js"></script>

//seed.js需要按需加载的资源
<script src="libs_md5.js"></script>
<script src="main_md5.js"></script>

当然,由于js加载是顺序是不可控的,我们需要为seed.js实现一个最简单的顺序加载模块,映射什么的由构建工具完成,每次做覆盖发布即可,这样做的缺点是额外增加一个seed.js的文件,并且要承担模块加载代码的下载量。

转载本站文章请注明出处:vns威尼斯城官网登入 http://www.tiec-ccpittj.com/?p=4237

上一篇:

下一篇:

相关文章