金沙国际官网_金沙国际平台登录

因为这个金沙国际官网_金沙国际平台登录网站与很多的大型澳门赌场都有合作,金沙国际官网_金沙国际平台登录尽职尽责,高效执行,保持好奇心,不断学习,追求卓越,点击进入金沙国际官网_金沙国际平台登录马上体验吧,所以现在也正式地开始了营业。

您的位置:金沙国际官网 > web前端 > 研究首屏时间,CSS代码重构与优化之路

研究首屏时间,CSS代码重构与优化之路

发布时间:2019-11-06 06:40编辑:web前端浏览(51)

    CSS代码重构与优化之路

    2016/01/05 · CSS · 1 评论 · 重构

    原文出处: @狼狼的蓝胖子   

    写CSS的同学们往往会体会到,随着项目规模的增加,项目中的CSS代码也会越来越多,如果没有及时对CSS代码进行维护,CSS代码不断会越来越多。CSS代码交错复杂,像一张庞大的蜘蛛网分布在网站的各个位置,你不知道修改这行代码会有什么影响,所以如果有修改或增加新功能时,开发人员往往不敢去删除旧的冗余的代码,而保险地增加新代码,最终的坏处就是项目中的CSS会越来越多,最终陷入无底洞。

    CSS或JS实现gif动态图片的停止与播放

    2015/12/06 · CSS, JavaScript · gif

    原文出处: 张鑫旭   

    一、屋外:寒风吹,雪花飘;屋内:空调吹,代码飘

    上午出去买菜,正好下雨了,还夹杂着冰珠子。鄙人大意,穿的是一件帅气但单薄的黄色大衣,立马冻成了中华田园犬。原本计划去钓鱼的,科科,作罢,上午在家看CCTV5 骑士队vs鹈鹕队,下午补动漫码代码做文章,好生惬意。

    图片 1

    对于习惯性刷微博的我,总时不时会看到类似下面的游戏:

    测测你和小白(白百何)有哪些共同点,戳开动图,最先看清的词是什么?ie浏览器的同学可以按esc键(或截屏),据说在哪个词暂停,哪个词就是你哦!图片 2

    图片 3

    OK, 这里出现一个浏览器特性,就是通过ESC快捷键,暂停gif的播放。据说FireFox浏览器以前也有,后来被干掉了,根据@紫云妃的说法是:

    是这样的,Firefox原来的表现是:在页面load事件完成,同时x按钮变成刷新按钮之后,esc仍然有几个作用,中断当前正在发送的ajax,websocket,停止gif,apng动画的播放.但这些功能太小众了,影响了普通用户的使用,可能不小心按了esc,结果ajax断了,网页出错了.所以Firefox20修改成:网页加载完成后,esc键完全失效.

    然而,这种隐晦的但似乎会影响正常功能的小技巧显然是无法实现真正意义上的gif动态图片的停止与播放的。一是兼容性,二是功能性,三是移动端没有ESC键。

    所以,如果我们遇到需要可以随时随地停止gif动态图片播放的需求的时候,就需要寻找其他的出路。好,寒冬里的暖身结束,开始进入正题~~

    研究首屏时间?你先要知道这几点细节

    2016/01/11 · CSS, JavaScript · 首屏

    原文出处: AlloyTeam   

    做移动web页面,受移动网络网速和终端性能影响,我们经常要关注首屏内容展示时间(以下简称首屏时间)这个指标,它衡量着我们的页面是否能在用户耐心消磨完之前展示出来,很大程度影响着用户的使用满意度。

    CSS代码重构的目的

    我们写CSS代码时,不仅仅只是完成页面设计的效果,还应该让CSS代码易于管理,维护。我们对CSS代码重构主要有两个目的:
    1、提高代码性能
    2、提高代码的可维护性

    二、gif图片自己可控前提下的方法一:多img资源控制处理

    假如说,我们希望暂停的gif是自己(开发人员)传上去的,不是用户可以随机上传不可控的gif. 我们可以这么处理,就是准备2套图片,一个是gif动态图片,还有一个是只有一帧的静止的图片。然后使用JS来回切换`的src`值为这两张图片地址就好了。

    此方法甚简单,我就不放实例了。

    img.src="animate.gif"; // 或者呈现的是 img.src="static.png";

    1
    2
    3
    img.src="animate.gif";
    // 或者呈现的是
    img.src="static.png";

    这个方法最大的优点就是兼容性强,所有浏览器都可以实现停止效果。然而,这种方法有个局限,就是,暂停时候呈现的图片永远是同一张。基本上可以说是停止,而不是暂停。

    那有没有什么方法可以真正意义上的暂停呢?还真有!

    怎么获取首屏时间呢?

    我们经常要先问自己:页面是怎么加载数据?

    A:加载完静态资源后通过ajax请求去后台获取数据,数据回来后渲染内容

    图片 4

     

    在每个点打上一个时间戳,首屏时间 = 点8 – 点1;

    B:使用后台直出,返回的html已经带上内容了

    图片 5

    此时首屏时间 = 点4 – 点1。

    注:1. 打了这么多个点,是因为当我们收集到首屏时间之后,要去分析到底是哪一段是性能瓶颈,哪一段还有优化空间,所以我们需要收集 点2 – 点1、点3 – 点1 ……这些时间以作分析;

    1. 打点1我们一般是在html文件head标签的开头打个时间戳;

    2. 在css文件加载前一般没有别的加载处理,所以打点1和打点2一般可以合并。

     

    到此我们就收集到首屏相关各种数据,可以做各种针对性优化。Wait!在你大刀阔斧优化前,你要了解一些细节,它们有利于你做更准确的分析和更细致的优化。

    提高代码性能

    提高CSS代码性能主要有两个点:
    1、提高页面的加载性能
    提高页面的加载性能,简单说就是减小CSS文件的大小,提高页面的加载速度,尽可以的利用http缓存
    2、提高CSS代码性能
    不同的CSS代码,浏览器对其解析的速度也是不一样的,如何提高浏览器解析CSS代码的速度也是我们要考虑的

    三、gif图片自己可控前提下的方法二:CSS3 animation控制

    也就是我们看到的gif效果并不是一个真正的gif图片,而是使用CSS3的animation属性控制形成的逐帧动态图片效果。我搜了下,@DO1路人乙有篇文章“css3-animation制作逐帧动画”专门介绍了这种技术。说穿了就是animation控制Sprites图片的background-position值模拟gif效果。

    例如,新版twitter的Like的效果,貌似就有使用该技术:
    图片 6

    使用CSS3 animation实现类gif效果的好处在于,图片可以无损,且我们可以很轻松地控制图片动画的暂停和播放,使用的是:animation-play-state: paused;这个声明。

    您可以狠狠地点击这里:使用CSS3 animation实现gif动图的暂停和播放demo

    点击demo页面的暂停按钮,您会发现,直接就停住了,如下截图示意,截自IE10浏览器:
    图片 7

    再次点击,就会在暂停画面之后继续播放了。从而实现了我们对动画图片的精确控制效果。

    此方法看上去完美,但是,1. IE10+等支持CSS3 animation的浏览器才行;2. 最大的问题是图片需要是自己控制,如果想控制用户上传的真正意义的gif图片,只能……望洋兴叹……………………吗?

    细节1:js后面的点 – js前面的点 ≠ js的加载时间

    图片 8

    JsEndTime – JsStartTime = js文件的加载时间,对吗?

    不对!明显地,这个等式忽略了js的执行时间。js执行代码是需要花费时间的,特别是做一些复杂的计算或频繁的dom操作,这个执行时间有时会达到几百毫秒。

    那么,JsEndTime – JsStartTime = js文件的加载执行时间?

    依然不对!因为CSS文件的加载执行带来了干扰。觉得很奇怪对吧,别急,我们来做个试验:我们找一个demo页面,在chrome里面打开,然后启动控制台,模拟低网速,让文件加载时间比较久:图片 9

    先在正常情况下收集 JsEndTime – JsStartTime 的时间,然后使用fiddler阻塞某一条css请求几秒钟:

    图片 10

    然后再恢复请求,拿到此时的 JsEndTime – JsStartTime 结果,会发现第一次的时间是几百毫秒将近1s,而第二次的时间低于100ms甚至接近为0(我的示例,时间视读者具体的js文件决定),两者的差距非常明显。

    这是什么原理?这就是我们常说的”加载是并行的,执行是串行的“的结果。html开始加载的时候,浏览器会将页面外联的css文件和js文件并行加载,如果一个文件还没回来,它后面的代码是不会执行的。刚刚我们的demo,我们阻塞了css文件几秒,此时js文件因为并行已经加载回来,但由于css文件阻塞住,所以后面 JsStartTime 的赋值语句是不执行的!当我们放开阻塞,此时才会运行到 JsStartTime 的赋值、js文件的解析、JsEndTime的赋值,由于大头时间加载早已完成,所以 JsEndTime 和 JsStartTime 的差值非常小。

     

    知道这个有何用?

    1. 别再把 JsEndTime – JsStartTime 的结果成为js文件的加载执行时间(除非你没有外联css文件),不然会被内行人取笑滴;
    2. css文件的阻塞会影响后面js代码的执行,自然也包括html代码的执行,即是说此时你的页面就是空白的。所以css文件尽量内联,你可以让构建工具帮你忙;
    3. 如果真想要知道js文件的加载时间,最正确的姿势是使用 Resource Timing API,不过这个API移动端只能在Android4.4及以上的版本拿到数据,也就在业务PV大的场景才够我们做分析用

    当然,那两个打点留着还是可以做分析用的。

     

    提高代码的可维护性

    提高CSS代码的可维护性主要是体现在下面几点:
    1、可重用性
    一般来说,一个项目的整体设计风格是一致的,页面中肯定有几个风格一致但有些许不同的模块,如何在尽可能多地重用CSS代码,尽可能少地增加新代码,这是CSS代码中非常重要的一点。如果CSS代码的重用性高,我们可能只需要写一些不一样的地方,对页面性能和可维护性、提高开发效率都有很大的帮助。

    2、可扩展性
    如果产品增加了某个功能,我们应该保证新增加的CSS代码不会影响到旧的CSS代码和页面,并且尽可能少地增加新代码而重用旧代码。

    3、可修改性
    如果某个模块产品经理觉得要修改样式,或者要删掉它,如果没有规划好相应的CSS代码,过了一段时间之后,开发人员可能已经不记得这段代码作用了几个地方,不敢修改或删除它,这样下去CSS代码也就越来越多,影响了页面的性能,还造成了代码的复杂度。

    四、自己无法控制的gif图片的停止与播放

    比方说,页面上用户上传了些gif图片,哎呀,闪瞎了我的中华田园眼,我要全部暂停,肿么办?如果后台同学没有对gif进行静态处理,此时,只能靠前端小伙伴,有什么办法吗?

    有一个。HTML5 canvas可以读取图片信息,绘制当前图片。于是可以实现图片马赛克,模糊,色值过滤等很多图片特效。我们这里不用那么复杂,只要读取我们的图片,重绘下就可以。

    您可以狠狠地点击这里:使用JS和canvas实现gif动图的停止和播放demo

    点击按钮,然后:
    图片 11

    图片 12

    如何使用?
    我对HTMLImageElement原型进行了扩展,增加了stop()play()两个方法,如下:

    if ('getContext' in document.createElement('canvas')) { HTMLImageElement.prototype.play = function() { if (this.storeCanvas) { // 移除存储的canvas this.storeCanvas.parentElement.removeChild(this.storeCanvas); this.storeCanvas = null; // 透明度还原 image.style.opacity = ''; } if (this.storeUrl) { this.src = this.storeUrl; } }; HTMLImageElement.prototype.stop = function() { var canvas = document.createElement('canvas'); // 尺寸 var width = this.width, height = this.height; if (width & height) { // 存储之前的地址 if (!this.storeUrl) { this.storeUrl = this.src; } // canvas大小 canvas.width = width; canvas.height = height; // 绘制图片帧(第一帧) canvas.getContext('2d').drawImage(this, 0, 0, width, height); // 重置当前图片 try { this.src = canvas.toDataURL("image/gif"); } catch(e) { // 跨域 this.removeAttribute('src'); // 载入canvas元素 canvas.style.position = 'absolute'; // 前面插入图片 this.parentElement.insertBefore(canvas, this); // 隐藏原图 this.style.opacity = '0'; // 存储canvas this.storeCanvas = canvas; } } }; }

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    if ('getContext' in document.createElement('canvas')) {
        HTMLImageElement.prototype.play = function() {
            if (this.storeCanvas) {
                // 移除存储的canvas
                this.storeCanvas.parentElement.removeChild(this.storeCanvas);
                this.storeCanvas = null;
                // 透明度还原
                image.style.opacity = '';
            }
            if (this.storeUrl) {
                this.src = this.storeUrl;    
            }
        };
        HTMLImageElement.prototype.stop = function() {
            var canvas = document.createElement('canvas');
            // 尺寸
            var width = this.width, height = this.height;
            if (width & height) {
                // 存储之前的地址
                if (!this.storeUrl) {
                    this.storeUrl = this.src;
                }
                // canvas大小
                canvas.width = width;
                canvas.height = height;
                // 绘制图片帧(第一帧)
                canvas.getContext('2d').drawImage(this, 0, 0, width, height);
                // 重置当前图片
                try {
                    this.src = canvas.toDataURL("image/gif");
                } catch(e) {
                    // 跨域
                    this.removeAttribute('src');
                    // 载入canvas元素
                    canvas.style.position = 'absolute';
                    // 前面插入图片
                    this.parentElement.insertBefore(canvas, this);
                    // 隐藏原图
                    this.style.opacity = '0';
                    // 存储canvas
                    this.storeCanvas = canvas;
                }
            }
        };
    }

    大家只要在页面中自己的JS文件中复制上面的代码,然后就可以直接:

    var image = document.getElementsByTagName("img")[0]; // 停止gif图片 image.stop(); // 播放gif图片 image.play();

    1
    2
    3
    4
    5
    var image = document.getElementsByTagName("img")[0];
    // 停止gif图片
    image.stop();
    // 播放gif图片
    image.play();

    //zxx: 上面代码并未详尽测试,以及可能的体验问题(IE闪动)没有具体处理(影响原理示意),若要实际使用,需要自己再微调完美下。

    不足

    1. IE9+支持。IE7/IE8不支持canvas没搞头。
      2. 只能停止gif,不能真正意义的暂停。因为canvas获得的gif图片信息为第一帧的信息,后面的貌似获取不到。要想实现暂停,而不是停止,还需要进一步研究,如果你有方法,非常欢迎分享。

    细节2:html里面外联的js文件,前一个文件的加载会阻塞下一个文件的执行;而如果a.js负责渲染并会动态拉取js、拉取cgi并做渲染,会发现它后面的js文件再怎么阻塞也不会影响到它的处理

    前半部分的结论在细节1里面已经证明,因为浏览器的执行是串行的。这说明,我们负责渲染内容的js代码要等到它前面所有的js文件加载执行完才会执行,即使那些代码跟渲染无关的代码如数据上报:

    图片 13

    而后半部分的结论很好验证,我们在负责渲染的js文件后面外联一个别的js文件并把它阻塞住,你会发现渲染相关的js不管是动态拉取新的js文件、拉取渲染相关内容都一切正常,页面内容顺利渲染出来,它们的执行并不需要等被阻塞的这个文件。

     

    知道这个有何用?

    1. 无关紧要”的js不要放在负责渲染的js前面,这里的“无关紧要”是指和首屏渲染无关,如数据上报组件。我们可以选择将要上报的数据临时存起来,先继续执行渲染的js,等负责渲染的js执行完再加载上报组件再上报。甚至连zepto之类的库我们也可以放后面,把渲染相关的代码抽离出来并用原生js书写,放到最前面;
    2. 可以看到,动态加载的js的执行是不会受到html后面外联的js的阻塞的影响,即是说,它的执行和后面js的执行顺序是不确定的。因此我们要小心处理好文件的依赖关系。当然还可以采用最不容易出错的方法:负责动态加载js的文件是html里面外联的最后一个文件

    (注:个人觉得这是全文最重要的两点结论,因为我正在做首屏优化^-^)

     

    CSS代码重构的基本方法

    前面说到了CSS代码重构的目的,现在我们来说说一些如何达到这些目的的一些基本方法,这些方法都是易于理解,容易实施的一些手段,大家平时可能也不知不觉地在使用它。

    五、结束语

    是胡不是霍,是霍躲不过!哈哈!
    图片 14
    上面这个gif也是demo示意gif强力候选。后来一琢磨,看我文章的还是宅男多,腐女少,所以,你懂的……
    图片 15

    ——我是多年不见的低调的分隔线—–

    本文gif比较多,如果您是移动设备查看本文,会发现,怎么我的电池怎么越来越瘦了!不是因为天冷冻小了,而是gif比较耗电。所以,从这个角度讲,我们其实有必要在移动端默认停止这些gif的播放,用户点击再播放。一来省流量,二来省电。

    如果没有静态图片资源支持,那不妨试试文章出现的一些方法,有心得记得来这里反馈哈! 图片 16

    最后,本文的方法都是有瑕疵的,自己也尚未在实际项目中使用过。因此,假如阅读本文的您:

    1. 有更完美的gif暂停与播放方法;
    2. 发现文中方法有不足和遗漏;

    都非常希望可以不吝赐教!

    感谢阅读!周末温暖!

     

    1 赞 6 收藏 评论

    图片 17

    细节3:如果html的返回头包含chunk,则它是边返回边解析的,不然就是一次性返回再解析。这个是在服务器配置的

    图片 18

    打点1一般写在html里head标签的最前面,时常有朋友拿直出时的 点4 – 点1 的时间和非直出时 点8 – 点1 的时候做对比,来说明直出优化了多少多少毫秒,我倒觉得不一定。要知道直出的情况html文件包含渲染后的内容和dom节点,文件大小一般比非直出大,有时甚至大个几十K都有,那我觉得要说明直出优化了多少就要把html的加载时间考虑进去了。那上面的计算方法是否考虑上html的加载时间?

    那就要看html文件的返回头是否包含chunk:

    图片 19

    如果包含这个返回头,那html文件是边返回边解析的,此时上面的计算方法是合理的。如果不包含这个头,则html文件是整一个返回来后才开始解析,此时上面的计算方法就少算了html的加载时间,也就不够精准。这个返回头是由后台控制的。

     

    知道这个有何用?

    1. 如果我们想说明直出的优化程度,最好先瞧瞧你的html返回头。如果不包含chunk返回头,考虑拿HTML5 performance里面的 navigationStart 作为打点1(这个API也是Android4.4及以上才支持),要不就要评估文件大小变化做点修正了;
    2. 对于没有启用chunk的html,建议不要inline太多跟渲染首屏内容无关的js在里面,这样会影响渲染时间

     

    本文由金沙国际官网发布于web前端,转载请注明出处:研究首屏时间,CSS代码重构与优化之路

    关键词: