谈谈JavaScript代码优化

概述:

  • 案例:Cesium打包流程,相关技术点和大概流程
  • 原理:代码优化的意义:压缩 优化 混淆
  • 优化:如何完善Cesium打包流程

关键字:Cesium gulp uglifyjs

字数:2330 | 阅读时间:7min+

1 Cesium打包流程

如果没有记错,Cesium从2016年初对代码构建工具做了一次调整,从grunt改为gulp。作为一名业余选手,就不揣测两者的差别了。个人而言,gulp和Ant的思路很相似,通过管道连接,都是基于流的构建风格,而且gulp更像是JS的编码风格,自带一种亲切感。

gulp.task('task1',['task0'], function() { return fun_task1(); });

Task语句是gulp中最常见的,懂了这句话,就等于你看懂脚本了。这句话的意思是,要执行task1,需要先执行task0,而task1的具体工作都在fun_task1方法中。这就是之前说的基于流的构建风格。有了这句话,在命令行中键入:gulp task1,回车执行该指令即可。

先安装Node,环境变量等,并安装npm包后,即可使用gulp打包工具,这里推荐cnpm。环境搭建好后,命令行中键入gulp minify开始打包。完整的过程是build->generateStubs->minify

Cesium打包流程

build:准备工作,创建Build文件夹;将glsl文件转为js形式;最主要的是createCesiumJs方法,遍历Source中所有js脚本,将所有Object记录到Source/Cesium.js;其他的是范例,单元测试相关模块。

generateStubs:用于单元测试,略。

minify; 首先combineJavaScript主要做了两件事情,打包Cesium和Workers脚本,这是打包的最终结果。Gulp根据指令的不同,比如minify下采用uglify2优化,而combine对应的参数为none,生成路径为CesiumUnminified。

另外,细心的人会发现,combineCesium的实现中有这样一句话path.relative('Source',require.resolve('almond')),这是一个小优化,almond是requirejs的精简包,因此,最终的Cesium.js中包含'almond脚本,内置了requirejs的主要方法。

如上是Cesium打包的主要流程,简单说主要有3+1类个指令:

  • Clean
    • 清空文件
  • minify
    • 打包&压缩
  • combine
    • 只打包,不压缩
  • JScoverage
    • 单元测试覆盖率,不了解

2 代码优化

对流程有了一个大概了解,下面,我们详细了解一下uglify2过程都做了哪些代码优化,一言以蔽之,压缩,优化,混淆。

uglify2主要有三个参数:-o,-c,-m,-o参数必选,指定输出文件,-c压缩,-m混淆变量名。如下分别为combine、(uglifyjs -o)、(uglifyjs –c -m -o)的文件对比,单位是k:

uglify2的压缩对比

都在一个屋檐下,差距怎么就这么大呢?我们简单说一下从1~2,2~3之间青取之于蓝而胜于蓝的过程。

1~2的过程其实很简单,就是干了三件事,去掉注释, 去掉多余的空格(换行符),去掉不必要的分号(;)。就这三件事情,文件一下子小了一半多,换句话就是平时你写的代码有一大半都是废话,此时你旁边的AI程序员可能会喃喃道来“你们人类好愚蠢~”。

2~3则是很多小细节的综合应用:

  • 去掉一些实际没有调用的函数(Dead code);
  • 将零散的变量声明合并,比如 var a; var b;变为var a,b;
  • 逻辑函数的精简,比如if(a) b(); else c()变为a ? b() : c();
  • 变量名的简化,比如var strObject;变为var s;
  • ……

这些小技巧有很多,具体要看不同的压缩工具的考虑优劣,但有些压缩高效的工具并不稳定,可能会破坏语法规范或语意,所以没必要为了几个kb承担过多的风险,目前比较成熟的工具主要有三个uglify2,google closure以及yuicompressor,具体优劣得自己来体会了,我是按照自己的理解给出的先后顺序。最终的效果如下:

Cesium脚本效果

这样的代码只能用单位“坨”来形容了,人类是无法直接读懂的,那浏览器能读懂吗?这是一个好问题!如下是V8引擎对JS语法解析的大概流程:

V8引擎解析JS脚本

下面是在我本机Chrome解析Cesium.js脚本花费时间(脚本从下载完到浏览器解析完的时间差),单位毫秒,因为只测试了一次,可能会有误差,但基本吻合期望值:

JS脚本解析时间对比

首先因为是本机测试,脚本无论是最大的8M还是最小的2.4M,下载速度都很快,因此我们不讨论(但实际应用中要考虑)脚本下载所需时间。

其次,如上图,多了一个source,这是源码情况下,这个时间水分比较大,因为是零散的文件,可以做到按需下载,但因为文件比较琐碎,性能也不高。

结论是,这种JS脚本优化策略对浏览器的影响不大,浏览器看到优化后的代码,可能会愣一会神,但很快就克服了。

3实战

知道了代码优化的大概原理,回顾一下代码优化的目的(压缩,优化,混淆),匹配一下结果是否符合期望值。嗯,其一,脚本小了,其二,效率优化了,其三,别人看不懂了。似乎该做的都已经做了,这个脚本已经很完美了。

Format后的效果

毛爷爷说,与人斗其乐无穷。确实,前两点的目的达到了,但第三点,还差很多。如上,和刚才的脚本是同一个文件,我只是用Chrome的调试工具format而已。这就是理想和现实之间的差距。

可见,Cesium默认打包工具在压缩和优化上都没有问题,但在混淆上并不充分,当然Cesium本身是开源的,也没必要搞这些。客观说,JS脚本是明码的,所以反编译只是时间和能力的问题,所以不妨换个态度来看待这个问题,增加反编译的成本,当该成本大于购买成本即可。

抱歉,下面的内容因为一些顾虑,不方便开放,如果感兴趣可以留言单聊,当然如果你认可超图的技术,欢迎加入超图研发WebGL团队。

Beneath this mask, there is more than flesh. Beneath this mask, there is an idea. And ideas are bulletproof.

原文发布于微信公众号 - LET(LET0-0)

原文发表时间:2017-02-18

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏coding

听说,撸代码,ide与vim更配哦vim折腾记vim常用命令

在选择编辑器上面,我是一个纠结的人,曾经年少的我执着地追求一款万能的编辑器,可以支持所有编辑语言,灵活可定制,可纯粹用键盘操作。符合这种条件的编辑器,非vim莫...

692
来自专栏小特工作室

工作流组件示例(全部开源)

1.概述 1.1简介 本文档旨在帮助开发人员快速使用工作流组件,完成OA或审批等涉及到工作流组件的系统开发工作 1.2组件构成 1.2.1组件层次图 ? 组...

53210
来自专栏FSociety

Python爬取猫眼「碟中谍」全部评论

评论算保存完了,近期会再做一个关于此次数据的可视化分析。另外阿汤哥真心太帅了,全程打肾上腺素,各位还没去看的赶紧~

300
来自专栏性能与架构

Meteor平台下网站开发只需数小时?

前阶段看到一篇文章,说以往花费数周时间才能完成的网站,现在使用 Meteor 只需要几小时 很好奇Meteor是个什么技术?怎么大幅提高开发效率的?就了解并试用...

3404
来自专栏嵌入式程序猿

你的代码敢上Polyspace跑吗?

嵌入式代码动态验证 在嵌入式开发中,代码静态分析工具相信大家应该都熟悉,都用过像PClint,understand C等,但对于动态验证,运行时错误验证工具还是...

2996
来自专栏FSociety

Python爬取猫眼「碟中谍」全部评论

昨天晚上看完碟中谍后,有点小激动,然后就有了这片文章。 我们将猫眼上碟中谍的全部评论保存下来,用于后期分析~ 总共评论3W条左右。

1303
来自专栏王大锤

iOS中的预编译指令的初步探究

3678
来自专栏java学习

Java每日一练(2017/6/1)

Java基础 | 数据库 | Android | 学习视频 | 学习资料下载 课前导读 ●回复"每日一练"获取以前的题目! ●答案公布时间:为每期发布题目的第二...

2507
来自专栏Golang语言社区

深入理解Wi-Fi P2P

本章主要内容: 介绍Wi-Fi P2P相关知识; 介绍Android中WifiP2pService、wpa_supplicant的相关代码。 7.1 概述 承...

3443
来自专栏猿人谷

PHP程序员应该掌握的10个技能

php程序员应该掌握的10个技能,看看你都掌握了哪些:   1、语法:必须熟练掌握 ,写代码的时候IDE的编辑器对某一行报错应该能够根据报错信息知道是什么样的语...

1727

扫码关注云+社区