注:本文是纯技术探讨文,无图无笑点,希望您喜欢

一.前言

软件行业极其缺乏前端人才这是圈内的共识了,某种程度上讲,同等水平前端的工资都要比后端高上不少,而圈内的另一项共识则是——网页是公司的脸面!

几年前,谷歌的一项统计表明,如果亚马逊页面加载每慢 100ms,将影响他们 1% 的收入;如果谷歌页面加载慢 500ms,流量将锐减 20%,这个数据现在必将更加恐怖!

前端高性能优化(一)(二)中,笔者介绍了一些关于前端优化的技术,这些技术都依赖于前人的辛苦努力,但我们仍要明白的是,前端的情况十分复杂,优化前端性能是必须因地制宜、因时制宜。

在本篇文章中,主要介绍的就是在一些条件下,传统优化 JavaScript 的技术并不像我们认为的那样适用。

二.JavaScript 模块化误区

加快 JavaScript 加载和执行的速度,一直是前端优化的一个热点。因此我们先来说下 JavaScript 模块化技术的相关知识,希望通过实践来体现模块化技术在使用时的注意事项,避免滥用。

为什么会有模块化技术?

长久以来,编写 JavaScript 一直以文件为单位,一般一个类型的 JavaScript 功能代码会被放在同一个文件里。在一个页面里,引用的文件一般是写死的,也就是不管页面用不用,只要你引入了这个文件,这个文件就会被加载。

举个例子,我们开发了一个内容复杂、功能强大的页面,JavaScript 文件大到 500K,当页面费劲的把这 500K 加载下来,然而用户真正只使用了这 500K 里极少的一部分功能,但我们又不得不把这 500K 加载下来,因为不同的用户使用的功能点可能不一样,我们必须满足所有需求。

而模块化技术提出 按需加载,也就是当用户触发该功能的时候,那个功能才真正的被加载。好比 500K 被拆成了 50 个模块,每个模块 10K,当用户触发一个功能时,加载 10K,再触发再加载,以这样懒加载的方式来加载模块,可以很大的提高响应速度。这样,管理模块懒加载的技术也随之诞生。

模块化技术并非到处靠谱!!

之前笔者在网上搜索到了一个模块化技术:SeaJS。它是一个遵循 CommonJS 规范的 JavaScript 模块加载框架,可以实现 JavaScript 的模块化开发及加载机制。与 JQuery 等 JavaScript 框架不同,SeaJS 不会扩展封装语言特性,而只是实现 JavaScript 的模块化及按模块加载。

SeaJS 的主要目的是令 JavaScript 开发模块化并可以轻松愉悦进行加载,将前端工程师从繁重的 JavaScript 文件及对象依赖处理中解放出来,可以专注于代码本身的逻辑。说白了就是有 Lazy Load 的特性,用到某模块时,SeaJS 才会去加载模块的 JS 文件。我们可以按功能划分多个模块,触发模块功能时,SeaJS 先加载功能模块的文件,然后执行相应的功能。

这个 SeaJS 拥有的特性,初看非常吸引人,它可以说是新定义了一种开发和管理 JavaScript 文件的模式。遵循这个模式,你会享受起 JavaScript 的开发。

实践证明,它也的确可以使 JavaScript 模块化,根据功能划分模块,每个模块对应一个 JavaScript 文件,当执行到模块的功能,或者你需要加载模块时,模块才会被下载,同时不会造成重复下载。这一切看起来如此的合理,如此的顺畅。。。。。

但是在使用后发现了一些 问题:由于当时开发的网站功能相对简单,JavaScript 文件并不是非常大,过多的模块,反而会导致总加载的时间变多了。

由于是 Lazy Load 特性,不适合的模块划分导致网站出现反应慢的现象,原因是得先加载模块的文件,才能执行模块的功能。当网络情况不好时,该现象表现的更为严重!!!

可以说,问题出在了对新技术的不了解上,从而出现了问题,预期是 SeaJS 可以处理 JavaScript 优化的问题,因为它具有避免加载不必要模块的功能,结果反而南辕北辙。

总结

虽然尝试出现了问题,但是,收获也是巨大的,简单来说就是以下两点:

1)因地制宜,根据实际需要使用模块化技术,切勿跟风技术,在自己没有完全掌握时,谨慎用于产品中。

2)模块如果是懒加载的,粒度不能太小,也就是模块不能太小。

根据 大功能来划分模块 也是一个不错的尝试。

笔者尝试将所有模块划分为 基础模块功能模块 ,基础模块包括页面头部,尾部相关的公共部分,功能模块则根据前后台划分,前台部分,又根据具体的页面来划分,能合并到一起的,就合并成一个模块,增加粒度。结果 JavaScript 文件减少,也达到了预期的效果。

从实际体验来看,对于流量不大的网站来说,没有必要使用懒加载 JavaScript 的相关技术,因为本身 JavaScript 文件就不是非常大。因此在网页加载时,就可以先加载所需要的模块。避免不必要的延迟。

三.JavaScript 的位置问题

这一部分,我们来说说 JavaScript 的位置问题对网页网站性能的影响。

为什么要考虑位置问题?

其实不管是 CSS 还是 JavaScript,都需要考虑位置的问题,因为 HTML 的渲染和加载顺序是从上往下,也就是如果前面插入了 JavaScript 的引用,那么必须等到这个 JavaScript 下载完毕才会渲染后续的部分。

因此 JavaScript 的插入位置就成为一个值得考虑的问题,因为不适合的位置可能引起渲染的延迟等,造成不好的用户体验。

传统方案带来的问题和思考

CSS 放在头部,JavaScript 放在尾部,这是传统的经验,它的好处是可以让页面优先渲染, 从而页面可以快速显示。

但有事实往往没有我们预想的那么美好。

有的时候会出现这么一种情况:当页面已经渲染完毕时,我们立刻去使用网站的功能,但很多时候 功能按钮会没有反应。原因也很简单,就是 JavaScript 放在页面的尾部,还没来得及加载。。。。

这就纠结了。。。。

两种 JavaScript 放置方式,一种放在头部,一种放在尾部(暂时忽略部分放在头部,部分放在尾部的方式),一个牺牲了渲染速度,一个牺牲了用户体验。所以很多时候 js 的问题我们需要做权衡。

对一般的小型网站来说,用户体验问题要远远大于页面渲染的问题,就比如上文提到的那种功能按钮不可用的情况。而且,如果 JavaScript 不是很大的话,放在头部就很好,既不会有太久的页面空白,也能让其优先加载,二者得到了很好的平衡。

因此,很多经验上的东西并不是绝对的,一定要根据实际的情况,包括功能特点、服务器网络情况等来综合考虑。

为此,笔者写下一个自认为较为合理的位置选择方案,仅供参考。

图 1. 判断 JavaScript 放置位置决策表

从上面的分类介绍,我们也可以看出,将功能代码按类型归类到不同的 JavaScript 文件是多么的重要,比如应该放头部和应该放尾部的代码,最好不要合并在一起,不要等到出问题要优化的时候再去整理和重构,这样会增加很多不必要的工作量。

这不仅仅是为自己工作负责,也是为后面要读你代码的新人负责。养成好的设计编码习惯,也是技术积累的一部分。最后再根据 JavaScript 文件的功能类型,来决定是放在页面的头部还是尾部。

四.怎样确定是不是 JavaScript 的问题?

这个问题在之前的前端高性能优化(一)(二)中也都简单的说过,之所以在这再次提及是因为确实觉得这个工具用着很舒服。

没错,就是舒服。

随着信息爆炸时代的到来,网站本身性能也深刻影响着公司的形象、利益等问题。但是大多数前端测试工具都太碎片化,没有办法针对多个使用场景,而且很多都是像 yslow 这样简单打个分,也不是真实的用户体验。前一段时间在网上找到了一款前端性能优化分析工具——Browser Insight,里面的功能相当全面,而且可以针对多个使用场景,包括:PC端,移动微信,移动浏览器,移动webview,还是 真实的用户体验,也就是说,用户访问你的网页是什么样的,从这个工具中体现出的就是什么样子的。

基于 JavaScript 这个维度 Bi 做的也是相当丰富了。

首先是 脚本错误 板块。Bi 里面可以从不同的时间维度查看被监控页面出现过的脚本错误,具体信息包括:发生时间、设备类型、报错的浏览器及其版本号、错误堆栈信息都可以看到,不论是 线上还是线下测试或者页面维护 都是够用了。

不但能看到时间、系统、浏览器等,还可以具体定位到出错的代码行,这个确实很方便。

图 2.Bi 脚本错误

其次是页面响应时间板块,这个算是意外的收获了。通过响应时间板块里面的慢加载追踪,可以看到本次慢加载的页面资源加载情况,然后我们就知道该优化哪个页面的哪些 js 、css、img等。

图 3.Bi 资源列表-时序图

五.前端优化?用户体验?

各位看客,如果你真能坚持看到这里,是否会觉得这篇更像解决用户体验问题的文章?但是讲心里话,前端优化的最终目的,难道不是为了改善用户体验吗?

任何基于用户体验的方案,都可以叫前端优化技术。

不管使用多么好的机器、多么高的技术,响应速度问题总是避免不了的,因此纠结于什么技术来解决是不实际的。但是有一款好的工具,使用一些小技巧,也可以改善用户等待的体验。

比如,我们为每个非 _target 的超链接或者表单的点击,添加点击事件处理,处理逻辑也很简单,就是设置 3 秒超时,显示等待对话框。如果在 3 秒内页面发生跳转,那么这个等待对话框就不会出现,否则会弹出提示用户等待,从而及时的将响应反馈给用户,减少用户空白等待时间。

这并不是什么高深的技术,但是运用这个技巧,却可以大大的改善用户体验。

各位,我们优化的目的,就是不要让用户一直得不到响应,避免空白等待,让用户体验越来越好。

前端性能优化(三)——传统 JavaScript 优化的误区的更多相关文章

  1. MySQL优化三(InnoDB优化)

    body { font-family: Helvetica, arial, sans-serif; font-size: 14px; line-height: 1.6; padding-top: 10 ...

  2. MySQL优化三 表结构优化

    由于MySQL数据库是基于行(Row)存储的数据库,而数据库操作 IO 的时候是以 page(block)的方式,也就是说,如果我们每条记录所占用的空间量减小,就会使每个page中可存放的数据行数增大 ...

  3. 萌新接触前端的第三课——JavaScript

    JavaScript概述 一.JavaScript的历史 1992年Nombas开发出C-minus-minus(C--)的嵌入式脚本语言(最初绑定在CEnvi软件中).后将其改名ScriptEase ...

  4. [前端笔记]第三篇:JavaScript

    JavaScript是一门编程语言,浏览器内置了JavaScript语言的解释器,所以在浏览器上按照JavaScript语言的规则编写相应代码之,浏览器可以解释并做出相应的处理. 一.代码存放位置 J ...

  5. 前端性能优化:细说JavaScript的加载与执行

    本文主要是从性能优化的角度来探讨JavaScript在加载与执行过程中的优化思路与实践方法,既是细说,文中在涉及原理性的地方,不免会多说几句,还望各位读者保持耐心,仔细理解,请相信,您的耐心付出一定会 ...

  6. 【前端性能优化】高性能JavaScript整理总结

    高性能JavaScript整理总结 关于前端性能优化:首先想到的是雅虎军规34条然后最近看了<高性能JavaScript>大概的把书中提到大部分知识梳理了下并加上部分个人理解这本书有参考雅 ...

  7. js中级系列三:前端性能优化

    原文链接:http://www.cnblogs.com/xxcanghai/p/5205998.html 链接:http://www.zhihu.com/question/21658448/answe ...

  8. 前端性能优化JavaScript篇

    关于前端性能优化的讨论一直都很多,包罗的知识也很多,可以说性能优化只有更好,没有最好.前面我写了一篇关于css优化的总结文章,今天再从javascript方面聊一聊. 1.从资源加载方面来说,浏览器的 ...

  9. 前端性能优化(JavaScript篇)

    正巧看到在送书,于是乎找了找自己博客上记录过的一些东西来及其无耻的蹭书了~~~ 小广告:更多内容可以看我的博客 优化循环 如果现在有个一个data[]数组,需要对其进行遍历,应当怎么做?最简单的代码是 ...

随机推荐

  1. 使用CocoaPods遇到的几个坑,记录一下

    最近使用pod的时候升级到1.0.0版本后遇到一些坑,整理一下 首先是CocoaPods报错:The dependency `` is not used in any concrete target ...

  2. 通过jQuery的attr修改onclick值的的解决方法

    好了,直接给大家贴上js代码吧 var js = "alert('B:' + this.id); return false;"; var newclick = eval(" ...

  3. Nginx+Tomcat+memcached负载均衡实现session共享

    http://blog.csdn.net/love_ubuntu/article/details/8464983 1.  安装各个软件不用说了. 2.  到tomcat的安装目录lib中,加入: me ...

  4. 20160421javaweb之上传下载小案例---网盘

    一.建立数据库: CREATE TABLE IF NOT EXISTS `netdisk` ( `id` ) NOT NULL AUTO_INCREMENT, `uuidname` ) NOT NUL ...

  5. asp.net中Get请求和Post请求

    Get和Post请求的区别:Get请求因为传输的数据在URL中,因此不安全,而且多数浏览器有限制其长度,最长为2KB.通过Get请求获取数据的方式:string strName=context.Req ...

  6. 分享使用method swizzling的经历

    原文:http://www.cnblogs.com/lujianwenance/p/5800232.html   这是一个很蛋疼的过程,先说一下需求,列表页预加载更多(60%).当我看到这个需求的时候 ...

  7. O-c中类的继承与派生的概念

    什么是继承 众所周知,面向对象的编程语言具有: 抽象性, 封装性, 继承性, 以及多态性 的特征. 那么什么是继承呢? 传统意义上是指从父辈那里获得父辈留下的东西 在开发中, 继承就是"复用 ...

  8. 我眼中真正优秀的CTO

    该文转自“肉饼铺子”.作者robbin是前JavaEye网站的创始人,TOPITCLUB互联网俱乐部发起人.  原文链接 现在进入正题,最近几个月,不断有人找我推荐CTO人选,这两年互联网创业和创投实 ...

  9. requirejs源码

    require.js /** vim: et:ts=4:sw=4:sts=4 * @license RequireJS 2.1.11 Copyright (c) 2010-2014, The Dojo ...

  10. 加载jar文件输出class和method

    package file import java.util.jar.JarEntry import java.util.jar.JarFile import org.junit.Test; class ...