Kiwi中js资源加载的优化



shellzhang    
2013-12-6    

开发与部署环境加载异同

  • 808X端口上,全部独立<script>加载
  • 80端口上:
    • 通过combo_resource合并为一个请求或者
    • spm提前打包合并成一个js文件加载
  • 目标:
    • 线上环境最大限度减少请求数
  • 不足:
    • 通用文件的更新,会导致各个合并文件均需要更新
  • 栗子

栗子

  • CommonWidgets
  • Model(Helper)
  • BU-related JS(Calendar、Event)

  • 公用CW与M两个模块
  • 一旦其中某一模块更新,会导致两个文件都需要重新合并
  • 用户也需要重新下载整个文件

Tradeoff——折中

  • 解耦CommonWidget与Model模块
    • 解耦方法,见代码
      • common-widgets/main.js
      • model/all.js
    • 引入CommonWidget或Model模块的方法
      • PPY.SC.CommonWidget.XXX
      • PPY.SC.ModelHelper.xxxxHelper
      • 而不是之前的require('xxxxx.js')

解耦过程中遇到的问题

  • 发现之前代码有直接在Helper文件中require controller的情况
    • 解决办法:helper中采用Spine.trigger的消息机制向监听者发送消息
  • Helper之间存在依赖关系
    • eventHelper等依赖labelHelper,因为需要初始化并获取用户已选择的label信息
    • 解决方法:暂时没找到更好的处理办法,只能在model/all.js中,优先引入labelHelper.js

如何加载

Seajs.use([CW.js, M.js], function(CW, M){
    seajs.use(BU.js, function(BU__){
        BU__.init();
    })
});

  • 呀,多了两次js请求。。。
    • 以前是(BU+CW+M).js,一次请求
    • 现在是CW.js, M.js, 然后,BU.js
    • seajs中对BU与CW的加载采用的是async的方式

script的加载方式

  • 最基本的<script src="">,无任何添加剂的,阻塞下载+立即执行
  • 带defer的script,<script defer src="">
    • 立即下载(不阻塞页面解析),但等到页面parse完后才执行,DOMContentLoaded之前
  • 带async的script,<script async src="">
    • 立即下载(不阻塞页面解析),但不保证多个async的代码会顺序执行
  • defer与async
    • 尽量不用defer,ie兼容,但其他浏览器支持不够,且表现不尽相同
    • async是html5的特性,至少在高级浏览器上表现一致

我们的折中方案

  • seajs中的js的加载,会默认使用async方式
    • CW与M的下载是异步同时启动的
    • 且两者充分解耦,谁先执行都不要紧
    • 同时,保证了BU的下载会是在以上两个下载执行完后,才会启动下载并执行
  • 这样:
    • 虽然我们增加了两个请求,但是换来了:
      • 同时下载两个js文件,减少了加载时间
      • 解耦了模块,更新时候只需要下载少量js代码就好

后续开发中需要注意的

  • 定义了新的ModelHelper,在Controller一层不要直接require
    • 在model/all.js中require并赋值给PPY.SC.ModelHelper.XX
    • 使用时候直接从ModelHelper名空间下取

  • CommonWidget也是同理处理方式

  • 注意引用关系,避免反向引用。比如Helper中require了Controller。解耦方法可以采用Spine.trigger来解决



进一步还可以做的工作

  • 对event模块进行区分加载
    • 根据用户是否登录
      • 区分为包含了themeModule、repeatBox、reminderSetting等模块的event.js
      • 以及不包含以上模块的event_nologin.js
    • 这么做的原因
      • 事件页可能会成为未来的运营点
      • 会有很多无登录态的新用户从这里起步访问我们
      • 如何最快地将页面展示给用户就很重要了
    • 方案
      • 像第一点说的,区分加载,尽快完成js加载展示页面
      • 页面静态化,对热点事件页可以这样处理

进一步还可以做的工作

  • 对event页面分为首屏js与非首屏js
    • 首屏与非首屏              
    • pageMain.js, nfsPageMain.js (none-first-screen)
    • seajs.async('nfsPageMain.js'),异步加载

  • 对comments模块做区分加载
    • 非登录用户,其实只要展示comments列表就好,各种操作代码其实都不需要的

参考文献

Optimize Js load in Kiwi

By shellzhang

Optimize Js load in Kiwi

  • 999