⾯面向未来的“重构”
                                                                                  kejun
                          hikejun.com | twitter/weibo: @kejunz | douban.com/people/listenpro




  http://www.flickr.com/photos/fernando_alda/6399170943/in/set-72157628144032827

Sunday, November 4, 12
“重构”观念的理解




Sunday, November 4, 12
“重构”观念的理解

                         第一层“重构”是指基于Web标准   发网站




Sunday, November 4, 12
“重构”观念的理解

                         第一层“重构”是指基于Web标准   发网站


                         第二层“重构”的目标是实现代码    用、⻚页面性能和可维护性




Sunday, November 4, 12
“重构”观念的理解

                         第一层“重构”是指基于Web标准   发网站


                         第二层“重构”的目标是实现代码    用、⻚页面性能和可维护性


                         第三层“重构”的目标是实现 活性和响应性




Sunday, November 4, 12
“重构”观念的理解

                         第一层“重构”是指基于Web标准   发网站


                         第二层“重构”的目标是实现代码    用、⻚页面性能和可维护性


                         第三层“重构”的目标是实现 活性和响应性


                         前   个层次是解决过去和当前的问题,第三个层次是解决未来问题的基础




Sunday, November 4, 12
Sunday, November 4, 12
迭代频率




                                   C类




                              B类

                         A类


                                        生命周期




Sunday, November 4, 12
迭代频率




                                           C类   活性




                                 B类 易维护性

                         A类 效率


                                                     生命周期




Sunday, November 4, 12
现象分析
             ⻚页面生命周期⻓长、迭代频繁的情况最容易产生代码冗余

                                       未用到    用到    扫描⻚页面数   Last-Modified

             weibo        frame.css    1686   485     25       11/02
                          index.css    299    38      25       10/10
                         A_index.css   3203   384     25       11/02
            douban        _init_.css   163    180     47       10/10
                           _all.css    256    118     47       10/17
                         douban.css    2011   360     47       11/01

Sunday, November 4, 12
现象分析
             ⻚页面生命周期⻓长、迭代频繁的情况最容易产生代码冗余

                                       未用到    用到    扫描⻚页面数   Last-Modified

             weibo        frame.css    1686   485     25       11/02
                          index.css    299    38      25       10/10
                         A_index.css   3203   384     25       11/02
            douban        _init_.css   163    180     47       10/10
                           _all.css    256    118     47       10/17
                         douban.css    2011   360     47       11/01

Sunday, November 4, 12
douban.css                douban.js


                   150


                112.5


                     75


                  37.5


                         0
                         2007-7   2009-2        2010-7   2011-7      2012-6




Sunday, November 4, 12
Sunday, November 4, 12
3x2

Sunday, November 4, 12
Sunday, November 4, 12
2x2+1

Sunday, November 4, 12
Sunday, November 4, 12
A/B测试、灰度上线、快速迭代、响应式   发......




Sunday, November 4, 12
A/B测试、灰度上线、快速迭代、响应式   发......


                          杂度更高、迭代更快、多版本并存......传统架构难于应付




Sunday, November 4, 12
A/B测试、灰度上线、快速迭代、响应式   发......


                          杂度更高、迭代更快、多版本并存......传统架构难于应付


                         深度重构前端架构,增强前端的“机动性”




Sunday, November 4, 12
A/B测试、灰度上线、快速迭代、响应式   发......


                          杂度更高、迭代更快、多版本并存......传统架构难于应付


                         深度重构前端架构,增强前端的“机动性”

                           a. 改造模板系统,实现真正模块化的view层
                           b. 完善静态文件管理系统




Sunday, November 4, 12
模块

               在程序设计中,为完成某一功能所需的一段程序或子程序;

               或指能由编译程序、装配程序等处理的独立程序单位;

               或指大型软件系统的一部分。




Sunday, November 4, 12
模块

               在程序设计中,为完成某一功能所需的一段程序或子程序;

               或指能由编译程序、装配程序等处理的独立程序单位;

               或指大型软件系统的一部分。




               1. 模块如何   分

               2. 模块应具有的独立性。装载/卸载不影响整个系统运行




Sunday, November 4, 12
http://en.wikipedia.org/wiki/Open_Source_Ecology_%28project%29
Sunday, November 4, 12
Sunday, November 4, 12
Sunday, November 4, 12
传统写法
          <head>
          <script src="jQuery.js"></script>
          <link rel="stylesheet" href="common.css">
          <link rel="stylesheet" href="boutique.css">
          <style>
          #db-boutique { ... }
          </style>
          </head>

          <body>

          <%include file=”boutique.html” />

          <script src="boutique.js"></script>
          <script>
          $('#bn').click(function(e){ ... });
          </script>
          </body>




Sunday, November 4, 12
传统写法
          <head>
          <script src="jQuery.js"></script>
          <link rel="stylesheet" href="common.css">
          <link rel="stylesheet" href="boutique.css">
          <style>
          #db-boutique { ... }
          </style>
          </head>

          <body>

          <%include file=”boutique.html” />

          <script src="boutique.js"></script>
          <script>
          $('#bn').click(function(e){ ... });
          </script>
          </body>


                   <!-- 模块文件boutique.html -->
                   <div id=”db-boutique” class="mod">
                   <a id="bn">link</a>
                   </div>




Sunday, November 4, 12
传统写法
          <head>
          <script src="jQuery.js"></script>
          <link rel="stylesheet" href="common.css">
          <link rel="stylesheet" href="boutique.css">
          <style>
          #db-boutique { ... }
          </style>
          </head>

          <body>

          <%include file=”boutique.html” />

          <script src="boutique.js"></script>
          <script>                              没有真正独立
          $('#bn').click(function(e){ ... });
                                                带来维护隐患
          </script>
          </body>


                   <!-- 模块文件boutique.html -->
                   <div id=”db-boutique” class="mod">
                   <a id="bn">link</a>
                   </div>




Sunday, November 4, 12
传统写法                                            模块真正实现独立
          <head>
          <script src="jQuery.js"></script>              <head>
          <link rel="stylesheet" href="common.css">      <script>
          <link rel="stylesheet" href="boutique.css">    ${istatic(‘/js/lib/head.js’)|n}
          <style>                                        </script>
          #db-boutique { ... }                           <link rel="stylesheet" href="common.css">
          </style>                                       </head>
          </head>
                                                         <body>
          <body>
                                                         <%include file=”boutique.html” />
          <%include file=”boutique.html” />
                                                         <script src="do.js" data-corelib="jQuery.js"></scri
          <script src="boutique.js"></script>            </body>
          <script>                              没有真正独立
          $('#bn').click(function(e){ ... });
                                                带来维护隐患
          </script>
          </body>


                   <!-- 模块文件boutique.html -->
                   <div id=”db-boutique” class="mod">
                   <a id="bn">link</a>
                   </div>




Sunday, November 4, 12
传统写法                                            模块真正实现独立
          <head>
          <script src="jQuery.js"></script>              <head>
          <link rel="stylesheet" href="common.css">      <script>
          <link rel="stylesheet" href="boutique.css">    ${istatic(‘/js/lib/head.js’)|n}
          <style>                                        </script>
          #db-boutique { ... }                           <link rel="stylesheet" href="common.css">
          </style>                                       </head>
          </head>
                                                         <body>
          <body>
                                                         <%include file=”boutique.html” />
          <%include file=”boutique.html” />
                                                         <script src="do.js" data-corelib="jQuery.js"></scri
          <script src="boutique.js"></script>            </body>
          <script>                              没有真正独立
          $('#bn').click(function(e){ ... });
                                                带来维护隐患
          </script>
          </body>                                              <!-- 模块文件boutique.html -->
                                                               <%block filter=”collect_css”>
                                                               #db-boutique { ... }
                   <!-- 模块文件boutique.html -->
                                                               </%block>
                   <div id=”db-boutique” class="mod">          <div id=”db-boutique” class="mod">
                   <a id="bn">link</a>                         <a id="bn">link</a>
                   </div>                                      </div>
                                                               <script>
                                                               Do(‘boutique.js’, function(){
                                                                 $('#bn').click(function(e){ ... });
                                                               });
                                                               </script>

Sunday, November 4, 12
Sunday, November 4, 12
Sunday, November 4, 12
业务代码和通用代码分离




Sunday, November 4, 12
业务代码和通用代码分离

                         公共文件冗余小




Sunday, November 4, 12
业务代码和通用代码分离

                         公共文件冗余小

                         模块迭代,模块内部解决




Sunday, November 4, 12
业务代码和通用代码分离

                         公共文件冗余小

                         模块迭代,模块内部解决


                         安装和卸载方便




Sunday, November 4, 12
业务代码和通用代码分离

                         公共文件冗余小

                         模块迭代,模块内部解决


                         安装和卸载方便


                         封装   杂度和多   状态




Sunday, November 4, 12
n年前


                          发


      3年前                前端按需加载&依赖管理

                         静态文件构建


       现在




Sunday, November 4, 12
n年前


                          发


      3年前                前端按需加载&依赖管理

                         静态文件构建


       现在




Sunday, November 4, 12
<a href="url" class="btn"><i>+</i>添加照片</a>




Sunday, November 4, 12
<a href="url" class="btn"><i>+</i>添加照片</a>



   <a href="url" class="btn" style="padding-left:8px;" >
     <i style="margin-right:2px; font-size:14px;" >+</i>添加照片
   </a>




Sunday, November 4, 12
<a href="url" class="btn"><i>+</i>添加照片</a>



   <a href="url" class="btn" style="padding-left:8px;" >
     <i style="margin-right:2px; font-size:14px;" >+</i>添加照片
   </a>


   <%block filter="collect_css">
   .btn-add-pic { padding-left:8px; }
   .btn-add-pic i { margin-right:2px;font-size:14px; }
   </%block>
   <a href="url" class="btn btn-add-pic"><i>+</i>添加照片</a>
Sunday, November 4, 12
线上态




Sunday, November 4, 12
线上态




                         发态




Sunday, November 4, 12
Sunday, November 4, 12
Sunday, November 4, 12
内联   用


                         少量⻚页面业务相




Sunday, November 4, 12
Sunday, November 4, 12
项目JS文件        使用场景




                                  外联   用 (粗粒度)

                                  内联   用 (细粒度)




Sunday, November 4, 12
<link rel="stylesheet" type="text/css" href="http://l.yimg.com/zz/combo?nn/lib/metro/g/
 core_yui_3.4.2.css&nn/lib/metro/g/core_srvc_1.0.9.css&nn/lib/metro/g/core_mod_1.0.116.css&nn/
 lib/metro/g/fp/fp_widecc_0.0.23.css&nn/lib/metro/g/fp/fp_403_0.0.2.css&nn/lib/metro/g/
 masthead/masthead_0.2.141.css&nn/lib/metro/g/masthead/masthead_403_0.0.34.css&nn/lib/metro2/g/
 announcebar/announcebar_1.0.22.css&nn/lib/metro/g/contentcarousel/
 contentcarousel_widecc_0.0.12.css&nn/lib/metro/g/multimedia/multimedia_1.0.48.css&nn/lib/
 metro/g/contentcarousel/contentcarousel_news_0.0.10.css&nn/lib/metro/g/mostpopular/
 mostpopular_0.0.10.css&nn/lib/metro/g/marketindices/marketindices_widecc_0.0.9.css&nn/lib/
 metro/g/news/offlead_0.1.15.css&nn/lib/metro/g/news/news_accordion_0.1.83.css&nn/lib/metro/g/
 contentcarousel/contentcarousel_polls_0.0.37.css&nn/lib/metro/g/tuc/tuc_wave3_0.0.20.css&nn/
 lib/metro/g/tabbar/tabbar_0.0.45.css&nn/lib/metro/g/uicontrib/locdrop_widget_0.0.6.css&nn/lib/
 metro/g/mail/mail_0.0.44.css&nn/lib/metro/g/mail/mail_403_0.0.21.css&nn/lib/metro/g/fptoday/
 fptoday_widecc_0.0.20.css&nn/lib/metro/g/pa/pa_widecc_0.1.25.css&nn/lib/metro/g/pa/
 pa_detached_0.1.91.css&nn/lib/metro/g/pa/pa_add_0.1.68.css&nn/lib/metro/g/tts/
 tts_widecc_0.0.18.css&nn/lib/metro/g/footer/footer_0.1.79.css&nn/lib/metro/g/footer/
 subfooter_0.0.15.css" />




Sunday, November 4, 12
<link rel="stylesheet" type="text/css" href="http://l.yimg.com/zz/combo?nn/lib/metro/g/
 core_yui_3.4.2.css&nn/lib/metro/g/core_srvc_1.0.9.css&nn/lib/metro/g/core_mod_1.0.116.css&nn/
 lib/metro/g/fp/fp_widecc_0.0.23.css&nn/lib/metro/g/fp/fp_403_0.0.2.css&nn/lib/metro/g/
 masthead/masthead_0.2.141.css&nn/lib/metro/g/masthead/masthead_403_0.0.34.css&nn/lib/metro2/g/
 announcebar/announcebar_1.0.22.css&nn/lib/metro/g/contentcarousel/
 contentcarousel_widecc_0.0.12.css&nn/lib/metro/g/multimedia/multimedia_1.0.48.css&nn/lib/
 metro/g/contentcarousel/contentcarousel_news_0.0.10.css&nn/lib/metro/g/mostpopular/
 mostpopular_0.0.10.css&nn/lib/metro/g/marketindices/marketindices_widecc_0.0.9.css&nn/lib/
 metro/g/news/offlead_0.1.15.css&nn/lib/metro/g/news/news_accordion_0.1.83.css&nn/lib/metro/g/
 contentcarousel/contentcarousel_polls_0.0.37.css&nn/lib/metro/g/tuc/tuc_wave3_0.0.20.css&nn/
 lib/metro/g/tabbar/tabbar_0.0.45.css&nn/lib/metro/g/uicontrib/locdrop_widget_0.0.6.css&nn/lib/
 metro/g/mail/mail_0.0.44.css&nn/lib/metro/g/mail/mail_403_0.0.21.css&nn/lib/metro/g/fptoday/
 fptoday_widecc_0.0.20.css&nn/lib/metro/g/pa/pa_widecc_0.1.25.css&nn/lib/metro/g/pa/
 pa_detached_0.1.91.css&nn/lib/metro/g/pa/pa_add_0.1.68.css&nn/lib/metro/g/tts/
 tts_widecc_0.0.18.css&nn/lib/metro/g/footer/footer_0.1.79.css&nn/lib/metro/g/footer/
 subfooter_0.0.15.css" />




Sunday, November 4, 12
CSS模块库



 <link rel="stylesheet" type="text/css" href="http://l.yimg.com/zz/combo?nn/lib/metro/g/
 core_yui_3.4.2.css&nn/lib/metro/g/core_srvc_1.0.9.css&nn/lib/metro/g/core_mod_1.0.116.css&nn/
 lib/metro/g/fp/fp_widecc_0.0.23.css&nn/lib/metro/g/fp/fp_403_0.0.2.css&nn/lib/metro/g/
 masthead/masthead_0.2.141.css&nn/lib/metro/g/masthead/masthead_403_0.0.34.css&nn/lib/metro2/g/
 announcebar/announcebar_1.0.22.css&nn/lib/metro/g/contentcarousel/
 contentcarousel_widecc_0.0.12.css&nn/lib/metro/g/multimedia/multimedia_1.0.48.css&nn/lib/
 metro/g/contentcarousel/contentcarousel_news_0.0.10.css&nn/lib/metro/g/mostpopular/
 mostpopular_0.0.10.css&nn/lib/metro/g/marketindices/marketindices_widecc_0.0.9.css&nn/lib/
 metro/g/news/offlead_0.1.15.css&nn/lib/metro/g/news/news_accordion_0.1.83.css&nn/lib/metro/g/
 contentcarousel/contentcarousel_polls_0.0.37.css&nn/lib/metro/g/tuc/tuc_wave3_0.0.20.css&nn/
 lib/metro/g/tabbar/tabbar_0.0.45.css&nn/lib/metro/g/uicontrib/locdrop_widget_0.0.6.css&nn/lib/
 metro/g/mail/mail_0.0.44.css&nn/lib/metro/g/mail/mail_403_0.0.21.css&nn/lib/metro/g/fptoday/

                                                               导入依赖的CSS模块
 fptoday_widecc_0.0.20.css&nn/lib/metro/g/pa/pa_widecc_0.1.25.css&nn/lib/metro/g/pa/
 pa_detached_0.1.91.css&nn/lib/metro/g/pa/pa_add_0.1.68.css&nn/lib/metro/g/tts/
 tts_widecc_0.0.18.css&nn/lib/metro/g/footer/footer_0.1.79.css&nn/lib/metro/g/footer/
 subfooter_0.0.15.css" />




Sunday, November 4, 12
静态文件管理

                         •   前端的加载器负责粗粒度文件的按需加载和依赖管理


                         •   后端的静态文件管理

                             a. 细粒度文件引用

                             b. 自动分离内联css/js代码

                             c. css/js的预处理(SCSS、伪语法)




Sunday, November 4, 12
变量      嵌套

                         mixin




                                 单行注释
                         运算




Sunday, November 4, 12
变量                     嵌套

                                        mixin




                         单行 vs. 多行 ?
                                                              单行注释
                         问题:输入优美输出     运算
                                        肿 :(
                         嵌套问题:避免       杂的嵌套
                         组合问题:冗余的定义
                         继承问题:继承多余的定义
                         保持简单!保持       平!
                         调试问题,chrome24支持SASS的Source Mapping



Sunday, November 4, 12
“ 用”不是简单的组合
                           完全   用。大而全未必好
                           粒度越细、功能越单一越有可能   用
                           基础代码     用
                           copy 用




Sunday, November 4, 12
http://sheldonbrown.com/retroraleighs/catalogs/1977-drawings/pages/22-track-bike.html
Sunday, November 4, 12
框架




http://sheldonbrown.com/retroraleighs/catalogs/1977-drawings/pages/22-track-bike.html
Sunday, November 4, 12
小粒度
                          元件


              框架




http://sheldonbrown.com/retroraleighs/catalogs/1977-drawings/pages/22-track-bike.html
Sunday, November 4, 12
小粒度
                          元件


              框架                                                                        大粒度
                                                                                        组件




http://sheldonbrown.com/retroraleighs/catalogs/1977-drawings/pages/22-track-bike.html
Sunday, November 4, 12
小粒度
                          元件


              框架                                                                        大粒度
                                                                                        组件




      组件的分解




http://sheldonbrown.com/retroraleighs/catalogs/1977-drawings/pages/22-track-bike.html
Sunday, November 4, 12
..   ...
                         超越传统响应式    发




Sunday, November 4, 12
响应性图片


                          响应性布局


                         viewport meta


                           原始⻚页面




Sunday, November 4, 12
适配大小、精度
                          响应性图片          dataURL

                                         320 px    mobile portrait
                          响应性布局          480 px    mobile landscape
                                         600 px    small tablet
                                         768 px    tablet portrait
                         viewport meta   1024 px   tablet landscape
                                         1280 px   desktop

                           原始⻚页面




Sunday, November 4, 12
性能优化           注⻚页面性能、电池消耗


                               响应交互          增强触屏行为和兼容            面事件

                                             适配大小、精度
                              响应性图片          dataURL

                                             320 px    mobile portrait
                              响应性布局          480 px    mobile landscape
                                             600 px    small tablet
                                             768 px    tablet portrait
                             viewport meta   1024 px   tablet landscape
                                             1280 px   desktop

        前端                     原始⻚页面


                              响应性模块          可定制、可组合
        后端

                         响应性静态资源文件(JS/CSS)   可兼容       面版,也可以重新           发


Sunday, November 4, 12
group.douban.com

Sunday, November 4, 12
<%def name=”main”>
                  <%include file=”path/mod1.html” args=”data=data” />
                  <%include file=”path/mod2.html” args=”data=data” />
                  <%include file=”path/mod3.html” args=”data=data” />
              </%def>
              <%def name=”mobile_main”>
                 ${self.main()} ## 简单!
              </%def>



             path/mod3.html
                    mobile_mod3.html
             js_path/mod3.js
                         mobile_mod3.js                  Desktop       Mobile
             css_path/mod3.css
                          mobile_mod3.css


Sunday, November 4, 12
增强触屏行为和兼容           面事件

                         mobile浏览器和   面浏览器的事件模型有明显差




Sunday, November 4, 12
增强触屏行为和兼容           面事件

                         mobile浏览器和   面浏览器的事件模型有明显差




Sunday, November 4, 12
增强触屏行为和兼容                  面事件

                         mobile浏览器和   面浏览器的事件模型有明显差




                                  a. 绑定document上的事件代理挂了



                                  b. mouse事件的顺序:
                                  mouseover > mousemove > mousedown > mouseup

                                  c. mouseout再次击非点击区域时触发

                                  d. click最后发生(大约300ms,有延迟感), 且有可能不发生




Sunday, November 4, 12
增强触屏行为和兼容                               面事件

                         mobile浏览器和     面浏览器的事件模型有明显差




                                  a. 绑定document上的事件代理挂了
                                      body { cursor:pointer; }



                                  b. mouse事件的顺序:
                                  mouseover > mousemove > mousedown > mouseup

                                  c. mouseout再次击非点击区域时触发

                                  d. click最后发生(大约300ms,有延迟感), 且有可能不发生

                                      利用jQuery的sepcial event重写click、mousedown/up/move
                                      https://gist.github.com/3358036
                                      TouchPunch(http://touchpunch.furf.com)



Sunday, November 4, 12
调试和监测




                         http://hikejun.com/blog/?p=693
Sunday, November 4, 12
group.douban.com




Sunday, November 4, 12
发环境同时预览 ;P
                         group.douban.com




Sunday, November 4, 12
adobe edge inspect(adobe shadow) + 本地weinre server




Sunday, November 4, 12
tcpdump
    sudo tcpdump -i en1 -n -s 0 -w yourapp.pcap tcp or port 53

    用Charles或pcapperf打




Sunday, November 4, 12
用户不   心流量
                          快、流畅、省电




Sunday, November 4, 12
新“角色” − 电池




Sunday, November 4, 12
新“角色” − 电池

                                iPhone 5: 3.8v 5.45Whr, 5.45 / 3.8 = 1434mAh
                                总电能 5.45 * 3600 = 19620J(焦耳)

                                iPhone 4S: 3.7v 5.3Whr, 5.3 / 3.7 = 1432mAh
                                总电能5.3 * 3600 = 19080J(焦耳)

                                HTC(G6,我的手机): 3.7v , 1500mAh
                                总电能3.7 * 1.5 * 3600 = 19980J(焦耳)

                                S3: 3.8v 7.98Whr, 7.98/3.8 = 2100mAh
                                总电能7.98 * 3600 = 28728J(焦耳)




Sunday, November 4, 12
下载260K,耗电约25J

            上传260K,耗电约15J

            显示600px宽的图片(no cache),耗电约1.4J

            显示600px宽的图片(cache),耗电约0.6J

            显示JPEG图片耗电 < PNG < GIF

            有cache能耗远小于没cache

            ......

            出自 http://www2012.wwwconference.org/proceedings/proceedings/p41.pdf




Sunday, November 4, 12
平均⻚页面大小


            下载260K,耗电约25J                                1M
            上传260K,耗电约15J

            显示600px宽的图片(no cache),耗电约1.4J

            显示600px宽的图片(cache),耗电约0.6J

            显示JPEG图片耗电 < PNG < GIF

            有cache能耗远小于没cache

            ......

            出自 http://www2012.wwwconference.org/proceedings/proceedings/p41.pdf




Sunday, November 4, 12
影响能耗的        键因子:

            cache、请求数、图片大小、js/css的冗余、css/js的   杂度




Sunday, November 4, 12
总结

                    1. 改造模板系统和完善静态文件管理系统提升机动性,在此基础上进行重构

                    2. 模块化view层的实现

                    3. 在上面实现后,顺利进入响应式   发阶段

                    4. 响应式 发实践的一些收获




Sunday, November 4, 12
Q &A
                                                      kejun
                         hikejun.com | twitter/weibo: @kejunz | douban.com/people/listenpro




Sunday, November 4, 12
我 说完了
                                                                                看?
                                                                         芳, 你怎么
                                                                      元




                                               Q &A
                                                      kejun
                         hikejun.com | twitter/weibo: @kejunz | douban.com/people/listenpro




Sunday, November 4, 12
谢谢!
                                                      kejun
                         hikejun.com | twitter/weibo: @kejunz | douban.com/people/listenpro




Sunday, November 4, 12

面向未来的重构

  • 1.
    ⾯面向未来的“重构” kejun hikejun.com | twitter/weibo: @kejunz | douban.com/people/listenpro http://www.flickr.com/photos/fernando_alda/6399170943/in/set-72157628144032827 Sunday, November 4, 12
  • 2.
  • 3.
    “重构”观念的理解 第一层“重构”是指基于Web标准 发网站 Sunday, November 4, 12
  • 4.
    “重构”观念的理解 第一层“重构”是指基于Web标准 发网站 第二层“重构”的目标是实现代码 用、⻚页面性能和可维护性 Sunday, November 4, 12
  • 5.
    “重构”观念的理解 第一层“重构”是指基于Web标准 发网站 第二层“重构”的目标是实现代码 用、⻚页面性能和可维护性 第三层“重构”的目标是实现 活性和响应性 Sunday, November 4, 12
  • 6.
    “重构”观念的理解 第一层“重构”是指基于Web标准 发网站 第二层“重构”的目标是实现代码 用、⻚页面性能和可维护性 第三层“重构”的目标是实现 活性和响应性 前 个层次是解决过去和当前的问题,第三个层次是解决未来问题的基础 Sunday, November 4, 12
  • 7.
  • 8.
    迭代频率 C类 B类 A类 生命周期 Sunday, November 4, 12
  • 9.
    迭代频率 C类 活性 B类 易维护性 A类 效率 生命周期 Sunday, November 4, 12
  • 10.
    现象分析 ⻚页面生命周期⻓长、迭代频繁的情况最容易产生代码冗余 未用到 用到 扫描⻚页面数 Last-Modified weibo frame.css 1686 485 25 11/02 index.css 299 38 25 10/10 A_index.css 3203 384 25 11/02 douban _init_.css 163 180 47 10/10 _all.css 256 118 47 10/17 douban.css 2011 360 47 11/01 Sunday, November 4, 12
  • 11.
    现象分析 ⻚页面生命周期⻓长、迭代频繁的情况最容易产生代码冗余 未用到 用到 扫描⻚页面数 Last-Modified weibo frame.css 1686 485 25 11/02 index.css 299 38 25 10/10 A_index.css 3203 384 25 11/02 douban _init_.css 163 180 47 10/10 _all.css 256 118 47 10/17 douban.css 2011 360 47 11/01 Sunday, November 4, 12
  • 12.
    douban.css douban.js 150 112.5 75 37.5 0 2007-7 2009-2 2010-7 2011-7 2012-6 Sunday, November 4, 12
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
    A/B测试、灰度上线、快速迭代、响应式 发...... 杂度更高、迭代更快、多版本并存......传统架构难于应付 Sunday, November 4, 12
  • 20.
    A/B测试、灰度上线、快速迭代、响应式 发...... 杂度更高、迭代更快、多版本并存......传统架构难于应付 深度重构前端架构,增强前端的“机动性” Sunday, November 4, 12
  • 21.
    A/B测试、灰度上线、快速迭代、响应式 发...... 杂度更高、迭代更快、多版本并存......传统架构难于应付 深度重构前端架构,增强前端的“机动性” a. 改造模板系统,实现真正模块化的view层 b. 完善静态文件管理系统 Sunday, November 4, 12
  • 22.
    模块 在程序设计中,为完成某一功能所需的一段程序或子程序; 或指能由编译程序、装配程序等处理的独立程序单位; 或指大型软件系统的一部分。 Sunday, November 4, 12
  • 23.
    模块 在程序设计中,为完成某一功能所需的一段程序或子程序; 或指能由编译程序、装配程序等处理的独立程序单位; 或指大型软件系统的一部分。 1. 模块如何 分 2. 模块应具有的独立性。装载/卸载不影响整个系统运行 Sunday, November 4, 12
  • 24.
  • 25.
  • 26.
  • 27.
    传统写法 <head> <script src="jQuery.js"></script> <link rel="stylesheet" href="common.css"> <link rel="stylesheet" href="boutique.css"> <style> #db-boutique { ... } </style> </head> <body> <%include file=”boutique.html” /> <script src="boutique.js"></script> <script> $('#bn').click(function(e){ ... }); </script> </body> Sunday, November 4, 12
  • 28.
    传统写法 <head> <script src="jQuery.js"></script> <link rel="stylesheet" href="common.css"> <link rel="stylesheet" href="boutique.css"> <style> #db-boutique { ... } </style> </head> <body> <%include file=”boutique.html” /> <script src="boutique.js"></script> <script> $('#bn').click(function(e){ ... }); </script> </body> <!-- 模块文件boutique.html --> <div id=”db-boutique” class="mod"> <a id="bn">link</a> </div> Sunday, November 4, 12
  • 29.
    传统写法 <head> <script src="jQuery.js"></script> <link rel="stylesheet" href="common.css"> <link rel="stylesheet" href="boutique.css"> <style> #db-boutique { ... } </style> </head> <body> <%include file=”boutique.html” /> <script src="boutique.js"></script> <script> 没有真正独立 $('#bn').click(function(e){ ... }); 带来维护隐患 </script> </body> <!-- 模块文件boutique.html --> <div id=”db-boutique” class="mod"> <a id="bn">link</a> </div> Sunday, November 4, 12
  • 30.
    传统写法 模块真正实现独立 <head> <script src="jQuery.js"></script> <head> <link rel="stylesheet" href="common.css"> <script> <link rel="stylesheet" href="boutique.css"> ${istatic(‘/js/lib/head.js’)|n} <style> </script> #db-boutique { ... } <link rel="stylesheet" href="common.css"> </style> </head> </head> <body> <body> <%include file=”boutique.html” /> <%include file=”boutique.html” /> <script src="do.js" data-corelib="jQuery.js"></scri <script src="boutique.js"></script> </body> <script> 没有真正独立 $('#bn').click(function(e){ ... }); 带来维护隐患 </script> </body> <!-- 模块文件boutique.html --> <div id=”db-boutique” class="mod"> <a id="bn">link</a> </div> Sunday, November 4, 12
  • 31.
    传统写法 模块真正实现独立 <head> <script src="jQuery.js"></script> <head> <link rel="stylesheet" href="common.css"> <script> <link rel="stylesheet" href="boutique.css"> ${istatic(‘/js/lib/head.js’)|n} <style> </script> #db-boutique { ... } <link rel="stylesheet" href="common.css"> </style> </head> </head> <body> <body> <%include file=”boutique.html” /> <%include file=”boutique.html” /> <script src="do.js" data-corelib="jQuery.js"></scri <script src="boutique.js"></script> </body> <script> 没有真正独立 $('#bn').click(function(e){ ... }); 带来维护隐患 </script> </body> <!-- 模块文件boutique.html --> <%block filter=”collect_css”> #db-boutique { ... } <!-- 模块文件boutique.html --> </%block> <div id=”db-boutique” class="mod"> <div id=”db-boutique” class="mod"> <a id="bn">link</a> <a id="bn">link</a> </div> </div> <script> Do(‘boutique.js’, function(){ $('#bn').click(function(e){ ... }); }); </script> Sunday, November 4, 12
  • 32.
  • 33.
  • 34.
  • 35.
    业务代码和通用代码分离 公共文件冗余小 Sunday, November 4, 12
  • 36.
    业务代码和通用代码分离 公共文件冗余小 模块迭代,模块内部解决 Sunday, November 4, 12
  • 37.
    业务代码和通用代码分离 公共文件冗余小 模块迭代,模块内部解决 安装和卸载方便 Sunday, November 4, 12
  • 38.
    业务代码和通用代码分离 公共文件冗余小 模块迭代,模块内部解决 安装和卸载方便 封装 杂度和多 状态 Sunday, November 4, 12
  • 39.
    n年前 发 3年前 前端按需加载&依赖管理 静态文件构建 现在 Sunday, November 4, 12
  • 40.
    n年前 发 3年前 前端按需加载&依赖管理 静态文件构建 现在 Sunday, November 4, 12
  • 41.
  • 42.
    <a href="url" class="btn"><i>+</i>添加照片</a> <a href="url" class="btn" style="padding-left:8px;" > <i style="margin-right:2px; font-size:14px;" >+</i>添加照片 </a> Sunday, November 4, 12
  • 43.
    <a href="url" class="btn"><i>+</i>添加照片</a> <a href="url" class="btn" style="padding-left:8px;" > <i style="margin-right:2px; font-size:14px;" >+</i>添加照片 </a> <%block filter="collect_css"> .btn-add-pic { padding-left:8px; } .btn-add-pic i { margin-right:2px;font-size:14px; } </%block> <a href="url" class="btn btn-add-pic"><i>+</i>添加照片</a> Sunday, November 4, 12
  • 44.
  • 45.
    线上态 发态 Sunday, November 4, 12
  • 46.
  • 47.
  • 48.
    内联 用 少量⻚页面业务相 Sunday, November 4, 12
  • 49.
  • 50.
    项目JS文件 使用场景 外联 用 (粗粒度) 内联 用 (细粒度) Sunday, November 4, 12
  • 51.
    <link rel="stylesheet" type="text/css"href="http://l.yimg.com/zz/combo?nn/lib/metro/g/ core_yui_3.4.2.css&nn/lib/metro/g/core_srvc_1.0.9.css&nn/lib/metro/g/core_mod_1.0.116.css&nn/ lib/metro/g/fp/fp_widecc_0.0.23.css&nn/lib/metro/g/fp/fp_403_0.0.2.css&nn/lib/metro/g/ masthead/masthead_0.2.141.css&nn/lib/metro/g/masthead/masthead_403_0.0.34.css&nn/lib/metro2/g/ announcebar/announcebar_1.0.22.css&nn/lib/metro/g/contentcarousel/ contentcarousel_widecc_0.0.12.css&nn/lib/metro/g/multimedia/multimedia_1.0.48.css&nn/lib/ metro/g/contentcarousel/contentcarousel_news_0.0.10.css&nn/lib/metro/g/mostpopular/ mostpopular_0.0.10.css&nn/lib/metro/g/marketindices/marketindices_widecc_0.0.9.css&nn/lib/ metro/g/news/offlead_0.1.15.css&nn/lib/metro/g/news/news_accordion_0.1.83.css&nn/lib/metro/g/ contentcarousel/contentcarousel_polls_0.0.37.css&nn/lib/metro/g/tuc/tuc_wave3_0.0.20.css&nn/ lib/metro/g/tabbar/tabbar_0.0.45.css&nn/lib/metro/g/uicontrib/locdrop_widget_0.0.6.css&nn/lib/ metro/g/mail/mail_0.0.44.css&nn/lib/metro/g/mail/mail_403_0.0.21.css&nn/lib/metro/g/fptoday/ fptoday_widecc_0.0.20.css&nn/lib/metro/g/pa/pa_widecc_0.1.25.css&nn/lib/metro/g/pa/ pa_detached_0.1.91.css&nn/lib/metro/g/pa/pa_add_0.1.68.css&nn/lib/metro/g/tts/ tts_widecc_0.0.18.css&nn/lib/metro/g/footer/footer_0.1.79.css&nn/lib/metro/g/footer/ subfooter_0.0.15.css" /> Sunday, November 4, 12
  • 52.
    <link rel="stylesheet" type="text/css"href="http://l.yimg.com/zz/combo?nn/lib/metro/g/ core_yui_3.4.2.css&nn/lib/metro/g/core_srvc_1.0.9.css&nn/lib/metro/g/core_mod_1.0.116.css&nn/ lib/metro/g/fp/fp_widecc_0.0.23.css&nn/lib/metro/g/fp/fp_403_0.0.2.css&nn/lib/metro/g/ masthead/masthead_0.2.141.css&nn/lib/metro/g/masthead/masthead_403_0.0.34.css&nn/lib/metro2/g/ announcebar/announcebar_1.0.22.css&nn/lib/metro/g/contentcarousel/ contentcarousel_widecc_0.0.12.css&nn/lib/metro/g/multimedia/multimedia_1.0.48.css&nn/lib/ metro/g/contentcarousel/contentcarousel_news_0.0.10.css&nn/lib/metro/g/mostpopular/ mostpopular_0.0.10.css&nn/lib/metro/g/marketindices/marketindices_widecc_0.0.9.css&nn/lib/ metro/g/news/offlead_0.1.15.css&nn/lib/metro/g/news/news_accordion_0.1.83.css&nn/lib/metro/g/ contentcarousel/contentcarousel_polls_0.0.37.css&nn/lib/metro/g/tuc/tuc_wave3_0.0.20.css&nn/ lib/metro/g/tabbar/tabbar_0.0.45.css&nn/lib/metro/g/uicontrib/locdrop_widget_0.0.6.css&nn/lib/ metro/g/mail/mail_0.0.44.css&nn/lib/metro/g/mail/mail_403_0.0.21.css&nn/lib/metro/g/fptoday/ fptoday_widecc_0.0.20.css&nn/lib/metro/g/pa/pa_widecc_0.1.25.css&nn/lib/metro/g/pa/ pa_detached_0.1.91.css&nn/lib/metro/g/pa/pa_add_0.1.68.css&nn/lib/metro/g/tts/ tts_widecc_0.0.18.css&nn/lib/metro/g/footer/footer_0.1.79.css&nn/lib/metro/g/footer/ subfooter_0.0.15.css" /> Sunday, November 4, 12
  • 53.
    CSS模块库 <link rel="stylesheet"type="text/css" href="http://l.yimg.com/zz/combo?nn/lib/metro/g/ core_yui_3.4.2.css&nn/lib/metro/g/core_srvc_1.0.9.css&nn/lib/metro/g/core_mod_1.0.116.css&nn/ lib/metro/g/fp/fp_widecc_0.0.23.css&nn/lib/metro/g/fp/fp_403_0.0.2.css&nn/lib/metro/g/ masthead/masthead_0.2.141.css&nn/lib/metro/g/masthead/masthead_403_0.0.34.css&nn/lib/metro2/g/ announcebar/announcebar_1.0.22.css&nn/lib/metro/g/contentcarousel/ contentcarousel_widecc_0.0.12.css&nn/lib/metro/g/multimedia/multimedia_1.0.48.css&nn/lib/ metro/g/contentcarousel/contentcarousel_news_0.0.10.css&nn/lib/metro/g/mostpopular/ mostpopular_0.0.10.css&nn/lib/metro/g/marketindices/marketindices_widecc_0.0.9.css&nn/lib/ metro/g/news/offlead_0.1.15.css&nn/lib/metro/g/news/news_accordion_0.1.83.css&nn/lib/metro/g/ contentcarousel/contentcarousel_polls_0.0.37.css&nn/lib/metro/g/tuc/tuc_wave3_0.0.20.css&nn/ lib/metro/g/tabbar/tabbar_0.0.45.css&nn/lib/metro/g/uicontrib/locdrop_widget_0.0.6.css&nn/lib/ metro/g/mail/mail_0.0.44.css&nn/lib/metro/g/mail/mail_403_0.0.21.css&nn/lib/metro/g/fptoday/ 导入依赖的CSS模块 fptoday_widecc_0.0.20.css&nn/lib/metro/g/pa/pa_widecc_0.1.25.css&nn/lib/metro/g/pa/ pa_detached_0.1.91.css&nn/lib/metro/g/pa/pa_add_0.1.68.css&nn/lib/metro/g/tts/ tts_widecc_0.0.18.css&nn/lib/metro/g/footer/footer_0.1.79.css&nn/lib/metro/g/footer/ subfooter_0.0.15.css" /> Sunday, November 4, 12
  • 54.
    静态文件管理 • 前端的加载器负责粗粒度文件的按需加载和依赖管理 • 后端的静态文件管理 a. 细粒度文件引用 b. 自动分离内联css/js代码 c. css/js的预处理(SCSS、伪语法) Sunday, November 4, 12
  • 55.
    变量 嵌套 mixin 单行注释 运算 Sunday, November 4, 12
  • 56.
    变量 嵌套 mixin 单行 vs. 多行 ? 单行注释 问题:输入优美输出 运算 肿 :( 嵌套问题:避免 杂的嵌套 组合问题:冗余的定义 继承问题:继承多余的定义 保持简单!保持 平! 调试问题,chrome24支持SASS的Source Mapping Sunday, November 4, 12
  • 57.
    “ 用”不是简单的组合 完全 用。大而全未必好 粒度越细、功能越单一越有可能 用 基础代码 用 copy 用 Sunday, November 4, 12
  • 58.
  • 59.
  • 60.
    小粒度 元件 框架 http://sheldonbrown.com/retroraleighs/catalogs/1977-drawings/pages/22-track-bike.html Sunday, November 4, 12
  • 61.
    小粒度 元件 框架 大粒度 组件 http://sheldonbrown.com/retroraleighs/catalogs/1977-drawings/pages/22-track-bike.html Sunday, November 4, 12
  • 62.
    小粒度 元件 框架 大粒度 组件 组件的分解 http://sheldonbrown.com/retroraleighs/catalogs/1977-drawings/pages/22-track-bike.html Sunday, November 4, 12
  • 63.
    .. ... 超越传统响应式 发 Sunday, November 4, 12
  • 64.
    响应性图片 响应性布局 viewport meta 原始⻚页面 Sunday, November 4, 12
  • 65.
    适配大小、精度 响应性图片 dataURL 320 px mobile portrait 响应性布局 480 px mobile landscape 600 px small tablet 768 px tablet portrait viewport meta 1024 px tablet landscape 1280 px desktop 原始⻚页面 Sunday, November 4, 12
  • 66.
    性能优化 注⻚页面性能、电池消耗 响应交互 增强触屏行为和兼容 面事件 适配大小、精度 响应性图片 dataURL 320 px mobile portrait 响应性布局 480 px mobile landscape 600 px small tablet 768 px tablet portrait viewport meta 1024 px tablet landscape 1280 px desktop 前端 原始⻚页面 响应性模块 可定制、可组合 后端 响应性静态资源文件(JS/CSS) 可兼容 面版,也可以重新 发 Sunday, November 4, 12
  • 67.
  • 68.
    <%def name=”main”> <%include file=”path/mod1.html” args=”data=data” /> <%include file=”path/mod2.html” args=”data=data” /> <%include file=”path/mod3.html” args=”data=data” /> </%def> <%def name=”mobile_main”> ${self.main()} ## 简单! </%def> path/mod3.html mobile_mod3.html js_path/mod3.js mobile_mod3.js Desktop Mobile css_path/mod3.css mobile_mod3.css Sunday, November 4, 12
  • 69.
    增强触屏行为和兼容 面事件 mobile浏览器和 面浏览器的事件模型有明显差 Sunday, November 4, 12
  • 70.
    增强触屏行为和兼容 面事件 mobile浏览器和 面浏览器的事件模型有明显差 Sunday, November 4, 12
  • 71.
    增强触屏行为和兼容 面事件 mobile浏览器和 面浏览器的事件模型有明显差 a. 绑定document上的事件代理挂了 b. mouse事件的顺序: mouseover > mousemove > mousedown > mouseup c. mouseout再次击非点击区域时触发 d. click最后发生(大约300ms,有延迟感), 且有可能不发生 Sunday, November 4, 12
  • 72.
    增强触屏行为和兼容 面事件 mobile浏览器和 面浏览器的事件模型有明显差 a. 绑定document上的事件代理挂了 body { cursor:pointer; } b. mouse事件的顺序: mouseover > mousemove > mousedown > mouseup c. mouseout再次击非点击区域时触发 d. click最后发生(大约300ms,有延迟感), 且有可能不发生 利用jQuery的sepcial event重写click、mousedown/up/move https://gist.github.com/3358036 TouchPunch(http://touchpunch.furf.com) Sunday, November 4, 12
  • 73.
    调试和监测 http://hikejun.com/blog/?p=693 Sunday, November 4, 12
  • 74.
  • 75.
    发环境同时预览 ;P group.douban.com Sunday, November 4, 12
  • 76.
    adobe edge inspect(adobeshadow) + 本地weinre server Sunday, November 4, 12
  • 77.
    tcpdump sudo tcpdump -i en1 -n -s 0 -w yourapp.pcap tcp or port 53 用Charles或pcapperf打 Sunday, November 4, 12
  • 78.
    用户不 心流量 快、流畅、省电 Sunday, November 4, 12
  • 79.
  • 80.
    新“角色” − 电池 iPhone 5: 3.8v 5.45Whr, 5.45 / 3.8 = 1434mAh 总电能 5.45 * 3600 = 19620J(焦耳) iPhone 4S: 3.7v 5.3Whr, 5.3 / 3.7 = 1432mAh 总电能5.3 * 3600 = 19080J(焦耳) HTC(G6,我的手机): 3.7v , 1500mAh 总电能3.7 * 1.5 * 3600 = 19980J(焦耳) S3: 3.8v 7.98Whr, 7.98/3.8 = 2100mAh 总电能7.98 * 3600 = 28728J(焦耳) Sunday, November 4, 12
  • 81.
    下载260K,耗电约25J 上传260K,耗电约15J 显示600px宽的图片(no cache),耗电约1.4J 显示600px宽的图片(cache),耗电约0.6J 显示JPEG图片耗电 < PNG < GIF 有cache能耗远小于没cache ...... 出自 http://www2012.wwwconference.org/proceedings/proceedings/p41.pdf Sunday, November 4, 12
  • 82.
    平均⻚页面大小 下载260K,耗电约25J 1M 上传260K,耗电约15J 显示600px宽的图片(no cache),耗电约1.4J 显示600px宽的图片(cache),耗电约0.6J 显示JPEG图片耗电 < PNG < GIF 有cache能耗远小于没cache ...... 出自 http://www2012.wwwconference.org/proceedings/proceedings/p41.pdf Sunday, November 4, 12
  • 83.
    影响能耗的 键因子: cache、请求数、图片大小、js/css的冗余、css/js的 杂度 Sunday, November 4, 12
  • 84.
    总结 1. 改造模板系统和完善静态文件管理系统提升机动性,在此基础上进行重构 2. 模块化view层的实现 3. 在上面实现后,顺利进入响应式 发阶段 4. 响应式 发实践的一些收获 Sunday, November 4, 12
  • 85.
    Q &A kejun hikejun.com | twitter/weibo: @kejunz | douban.com/people/listenpro Sunday, November 4, 12
  • 86.
    我 说完了 看? 芳, 你怎么 元 Q &A kejun hikejun.com | twitter/weibo: @kejunz | douban.com/people/listenpro Sunday, November 4, 12
  • 87.
    谢谢! kejun hikejun.com | twitter/weibo: @kejunz | douban.com/people/listenpro Sunday, November 4, 12