谈谈石豆官网改版的前端优化

(注:本人现已不在石豆任职,且石豆官网又进行了一次新的改版,故本文章内容已不再匹配石豆现有官网)

这俩星期主要致力于公司官网的改版,今天也算是比较完整地上线(暂时还是全静态的),可以在 http://www.shidou.com 查看效果(旧版是http://www.shidou.com/sdcm/ )。

效果还不错,主要提升了交互以及首屏速率。就加载速度来说,从下图(上方为旧版,下方为新版)可以看出白屏时间和首屏时间均较大幅度下滑,鉴于requireJS无阻塞加载模块以及部分图片懒加载的处理,也很好地把首屏加载时间跟整页加载时间分开:

再次访问的速度也算是翻了几倍:

先说说一些遗憾的地方吧,毕竟不是大企业那样资源充足,所以没额外的服务器来做静态资源CDN处理,而且gulp给静态资源加md5后缀的方式跟requireJS实在难配合,故也暂不考虑给页面加expire头。

另外一些gzip、Etag之类的后端优化,也不属于我这边能管理的范畴了,所以有些想优化的东西还是蛮有心无力。

下面还是稍微唠嗑点有趣的东西。

兼容处理

新版项目要求是兼容到IE7,但页面上的确使用了很多的CSS3特性,对于不支持的浏览器只能做优雅降级的处理。

产品介绍页的第一个动画来说,以常规形式使用了浏览器判断标签来显示不同内容(IE9-仅显示一张图片):

        <!--[if lte IE 9 ]><div class="low"></div><![endif]-->
        <!--[if (gt IE 9)|!(IE) ]><!-->
        <div class="anm-wrap monitored">
          <div class="bottom-wrap">
            <span class="l1-1"></span>
            <span class="l1-2"></span>
            <span class="l2-1"></span>
            <span class="l2-2"></span>
            <span class="l3"></span>
            <span class="l4"></span>
            <span class="l5-1"></span>
            <span class="l5-2"></span>
            <span class="l6-1"></span>
            <span class="l6-2"></span>
            <div class="c1-1"></div>
            <div class="c1-2"></div>
            <div class="c2-1"></div>
            <div class="c2-2"></div>
            <div class="c3"></div>
            <div class="c4"></div>
            <div class="c5-1"></div>
            <div class="c5-2"></div>
            <div class="c6-1"></div>
            <div class="c6-2"></div>
          </div><div class="top"></div>
        </div><!--<![endif]-->
      </div>
View Code


而在其它css3动画模块上,则是尽量使用 translate3d 来取代 translateX/Y,原因是IE9不支持这个特性,那么可以在它忽略动画(transition/animation)的情况下也忽略为了动画而设置的方位偏移:

不过有些动画毕竟需要用上透明度opacity,如动画起始点设置opacity:0,会导致IE9在不支持动画的情况下也显示为透明度0,那么就得常规使用css hack做额外处理。

但在使用gulp-sass编译sass过程中,会发现它经常会把一些css hack的特定符号给忽略掉(见issue),故在一位朋友的建议下采用他们公司的hack方法——类区分处理。主要是在html标签加入对应浏览器的css类名:

<!--[if IE 7 ]>
<html class="ie7" lang="zh-cn"><![endif]-->
<!--[if IE 8 ]>
<html class="ie8" lang="zh-cn"><![endif]-->
<!--[if IE 9 ]>
<html class="ie9" lang="zh-cn"><![endif]-->
<!--[if (gt IE 9)|!(IE) ]><!-->
<html lang="zh-cn"><!--<![endif]-->

后续咱自然可以很方便地在样式中hack任意IE浏览器,比如 

.ie9 .pd-wrap3 .intro2{
  .p-wrap>span,div.info{opacity: 1;}
}

另外不得不说,在做CSS3动画处理过程中最恼人的无异于要写一堆兼容代码,如光是一个 transition 就会有 -webkit/moz/ms/o- 几种前缀。
于是乎果断拿sass封装一个样式库来提高工作效率,例如上述的 transition 我们可以在一个 _base.scss 中这么定义:

@mixin transition($content){
  transition: $content;-webkit-transition: $content;
  -moz-transition: $content;-ms-transition: $content;
}

然后在其它sass文件中import进来,以@include的形式使用:

@include transition(all .8s cubic-bezier(.15, .73, .37, 1.2));

YEP!就这么一句话搞定,妈妈再也不用操心我花时间复制粘贴改兼容代码了。

不过有时候transition里的特性也得加前缀啊,比如 -webkit-transition:-webkit-transform(XXX) 。傻孩纸,再封装一个方法就可以咯:

@mixin transition($content){
  transition: $content;-webkit-transition: $content;
  -moz-transition: $content;-ms-transition: $content;
}
@mixin pTransition($content){    //内部特性也要加前缀的方法
  -webkit-transition:-webkit-#{$content};-moz-transition:-moz-#{$content};
  -ms-transition:-ms-#{$content};transition: $content;
}

实际上我们要考虑的情况可能略复杂,但都不在sass话下,比如我在页面中经常复用一个translate3d和scale特性的样式定义,那么可以用sass这么包装:

@mixin scaleNt3d($x:1,$y:1,$a:0,$b:0,$c:0){
  transform: scale($x,$y) translate3d($a,$b,$c);
  -webkit-transform: scale($x,$y) translate3d($a,$b,$c);
  -moz-transform: scale($x,$y) translate3d($a,$b,$c);
  -ms-transform: scale($x,$y) translate3d($a,$b,$c);
}

综上可以知道,在css3动画模块的设计过程中,使用sass/less能极大提高你的工作效率、带来便捷。

动画处理

大部分的动画原理基本在我上篇文章优秀网站看前端 —— 小米Note介绍页面里说的七七八八了,主要思想无非还是 —— 先布局好动画最终效果,再添加translate3d等特性将其显示为动画起始的形态,然后通过窗口scroll到当前动画模块位置的时候给该模块加一个置空样式,把translate3d什么的效果统统清除掉,这样便也在transition的作用下动态展示了“清除样式”的过程。当然animation的形式也是同样原理。

比较棘手一些的还是window.onscroll事件卸载的处理吧,拿上述的产品介绍页来说,我是希望用户在看完三个选项卡的共8个动画之后,就直接off掉窗口的滚动事件。

于是拿下述代码来做处理:

        function checkModule(){
            var st = $win.scrollTop() + $win.height() - 300,
                pn = 'p' + flag;
            func[pn]();
            for(var i=0;i<arrs[pn].length;i++){
                if(!arrs[pn][i] || st<arrs[pn][i]) continue;
                arrs['e'+flag][i].addClass('act');
                arrs[pn][i] = null;
                if(i>=arrs[pn].length-1) arrs['f'+flag]=1
            }
            if(arrs['f3'] && arrs['f2'] && arrs['f1']) $win.off('scroll',checkModule);
        }

其中 arrs 的初始模式如下:

            arrs = {
                p1:[], p2:[], p3:[],
                e1:[], e2:[], e3:[]
            }

pn用来push各动画模块的offset().top,en用来push各动画模块容器元素的JQ对象,窗体每滚动一次都会遍历对应的pn(通过flag识别用户在浏览哪个选项卡,从而遍历对应的pn和en)来判断窗体是否滚到了某个动画模块要被触发的位置,如果是,则给en加上触发动画的class。
每处理完en最后一个元素,就会给arrs加上对应的一个属性fn,然后在  if(arrs['f3'] && arrs['f2'] && arrs['f1'])  为真的时候卸下窗体的滚动监听。

另外在合作加盟页面做了个滚动视觉差效果(钱币会根据窗体滚动也上下滚动,没做太大幅度,可能得稍仔细看)

看着玄乎玄乎的,其实实现非常简单,跟h5和css3也没啥关系,无非在浏览器滚动的时候做判断和计算,给钱币一个对应的margin-top值:

        //钱币视觉差滚动
       var $win = $(window),
            purse_h = $("#purse").offset().top,
            step4_h = $("#step4").offset().top,
            $moneys = $('span','#intro3'),
            $m1 = $moneys.slice(0,3),
            $m2 = $moneys.slice(3,6),
            $m3 = $moneys.slice(6);
        $win.on("scroll",function(){
            var h = $win.scrollTop() + $win.height();
            if( (h <= purse_h) || ($win.scrollTop() > step4_h) ) return;
            $m1.css("marginTop",(purse_h-h)/5);
            $m2.css("marginTop",(purse_h-h)/15);
            $m3.css("marginTop",(purse_h-h)/20);
        });

其中的 purse_h 和 step4_h 分别是那个红色大钱袋以及下面那个“04加盟流程”容器距离文档顶部位置,窗体滚动的时候先判断是否在它们二者之间的区域内滚动,是的话才给钱币们(这里把11个钱币分为3个部分)做动画处理。

lazyload

这块主要针对首屏加载的优化,主要用于首页的幻灯片处,还有合作加盟页面。

拿合作加盟页面来说,有非常多的图片,篇幅也较长,等待这些图片的加载会消磨访问者的耐心。

于是我们不妨先加载首屏展示的图片,等DOMReady后再加载非首屏的图片:

我们把首屏的图片和其它部分图片区分为两部分的雪碧图(图1图2),首屏的雪碧图做正常加载,其它部分要用到雪碧图的元素均加上一个class="lazyload"的类,用于脚本检索。

接着在DOMReady之后给这些元素添加设置了背景图片的class:

$(".lazyload").addClass('sprite-bg');

于是乎我们可以看到其它部分的雪碧图成功地延迟到最后下载:

总而言之懒加载的实现很简单,主要是需要有这样的优化思路,从小处着手。

资源压缩

新项目除了使用gulp常规化压缩脚本和样式外,也使用了gulp-imagemin 来优化图片大小(建议配合imagemin-pngquant使用)

 

从项目起始到现在,预计压缩掉超过1/3的图片体积。而且摆脱了手动去TinyPNG压缩图片的过程,也算是蛮大便利(也谢谢我这边的UI小欧妹子在PS中就先做了优化处理,特别是首页幻灯片和banner处基本都转为gif格式)

其它

新版的站点不再使用旧版的bootstrap布局,提高渲染效率也减少冗余资源请求。也将把PC和移动端的版本分开为独立文件处理,不然像旧版那样混杂一起实在不便处理(也是旧版用bootstrap的原因),交互上也会被局限。

移动端版的仍处于UI设计过程中,后续会针对移动页面进行专版的优化,也打算把阿里的自适配技巧应用过来(前端只需按320的宽度做布局即可),以后有机会再跟大家分享。

另外在新版的站点上一共使用了俩款第三方字体,用的辅助工具是字蛛

后续可能还会考虑走类似 r.js 打包项目的形式,以前会觉得这种形式略粗暴,不利于资源复用,但现在会觉得http连接建立的开销优化可能比资源复用更来的重要,有时间想玩玩jspm,据说包含了打包功能。

就唠嗑下这些有的没得,共勉~

donate

posted @ 2015-04-16 13:55 vajoy 阅读(...) 评论(...) 编辑 收藏
Copyright © 2014 - 2017 VaJoy Studio