`
limu
  • 浏览: 322673 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

如果给JS代码发布正式使用前增加一个编译步骤,我们能做些什么.

阅读更多
最近看了Hedger Wang的"Coding Better Object-Oriented JavaScript with Closure Compiler"(中文),算是给D2预热.终于明白Google这工具为啥叫Compiler而不是Compressor.

相对于编译型语言,JavaScript缺少了编译这个环节.传统编译器把代码转换为可执行的机器指令的动作交由浏览器中的JS引擎在运行时执行.但现代的编译器除了代码翻译还有哪些功能?而JS引擎能在运行时Cover住这些任务么?

最常见的运行时编译无法解决的问题就是代码压缩.所以我们有各种Compressor让代码传输给浏览器的时是最小的.
而在这篇文章中Google Closure Complier告诉我们还可以在编译时统一OO风格,减小对象深度以提高访问速度,使用枚举,常量等等其他语言好用的特性.

但看了文章之后我还是没有马上使用GCC这些高级功能的打算.
预编译时只能做这么多么?
我觉得Google Closure Complier更有意义的是告诉我们,可以有这样一个发布前预编译的步骤,可以有这样的一个时间窗口,在这个时候结合我们自己的应用,结合我们自己遇到的问题是不是也可以做点什么.

最近我在做kissyLite,前一篇文章kissyLite的包管理和无需预先注册的带依赖关系模块异步加载,讲的是用较少的代码为JS引入具有良好扩展性的模块化.就这个应用场景,我们可以在预编译的环节做点什么.

场景一

mod开发者开发一个功能,将它封装在mod-a中.
然后我们发现mod-a中可以抽象出来mod-b,让mod-b其他地方也能使用到.
于是就有了mod-b,同时mod-a requires mod-b.

mod使用者的代码始终是KSLITE.use('mod-a',function(){});

由于原有mod-a被拆分,就需要串行的加载mod-a,mod-b.
因为以kissyLite的模块化模式,在mod-a加载进来之前是不清楚它require mod-b的.

为了颗粒化可重用,造成了性能的损失 -- 多了一个请求,而且是串行的.

通过预编译能解决这个问题么?可以.

模块使用者,使用Debug(带预编译相关功能)版本的kissylite,控制台就可以给出两个优化建议:
"为了让子模块能够平行加载,你应该修改此处代码为KSLITE.use('mod-a,mod-b');!"
可见至少我们解决了平行加载的问题.
而且我们可以在开发的时候完全不去考虑这个问题,当所有功能做好之后再来优化,这其实就是预编译时优化功能.

场景二

mod开发者还是发现mod-a中可以抽象出来mod-b,让mod-b其他地方也能使用到.
这次他非常清楚过细的颗粒化会引入更多的请求和串行加载等性能问题.
所以他在纠结到底要不要为了可能的重用单独先提出来mod-b.

通过预编译能解决这个问题么?如果预编译模块能结合自动化测试和自动构建,可以
首先回答:要将mod-b拆出来!
当我们把当前应用所有重要的测试用例都跑过一遍之后,发现当前的所有应用场景mod-b都是跟着mod-a进来的.
那么预编译可以给出优化建议
"为了减少请求数,可以将mod-b的内容追加到mod-a的后面".
因为mod-a必须要叫上mod-b,而当前mod-b还没有被单独使用,不如合并.
甚至可以结合自动构建工具,给出最适合当前应用的kissy版本kissy4U.
"为了减少请求数,这次构建已经吧mod-b的内容追加到mod-a的后面:)".
基准的kissy版本,mod-a和mod-b每个都是独立的.
而在为你应用构建的kissy4U中,mod-b在mod-a文件中.
不用纠结提出mod-b引入的性能问题了,写最优雅的代码吧.

场景三
还是mod-b要不要跟着mod-a一同输出.
现在问题又变化了,mod-b可能被单独使用,也可能被mod-a调用.
还要不要合并mod-a mod-b 到mod-a.js呢?
到底是先use mod-b 再 use mod-a的情况多呢?(这样显然不要合并文件)
还是直接就use-a的情况多呢?(这样还是合并了好点)

通过预编译能解决这个问题么?如果预编译模块能结合线上实际使用情况的统计反馈数据,可以.
我们参见Facebook的静态网页资源的管理和优化
我们有了抽样统计数据的反馈,就可以在预编译阶段根据反馈来决定要不要合并mod-a和mod-b.

场景四
add时到底要不要attach?
add的重要功能是注册一个模块,当这个模块不依赖其他模块或所依赖的内容都可用.那就具备attach的条件,要不要attach呢?
如果attach了,use的时候更快.如果不attach,页面加载更快.

回答问题:add的时候不要attach.
默认attach引入的代码运行消耗是不必要的.微软还有一个专门的工具Doloto来拆分加载时必要的代码和不必要的.

但这样做use的时候可能就会慢了.尤其use还可能涉及异步模块加载...
跟随微软的思路我们很容易想到办法,在domready之后,浏览器不忙的时候把可能用到的模块预先attach.
我称这个动作为预热.那该预热哪些?页面上有几十个功能都预热么?

通过预编译能解决这个问题么?依然可以.
在页面开发完之后把将会常用的功能使用一遍.然后编译器就可以给出提示.
"应该在domready的之后use('a,b,c,d'),进行预先attach".
即domready前按需加载,domready后选择性预热.

预编译打开一扇窗
可以看到针对kissyLite这个具体的应用:
        利用好这个环节,模块开发者的模块的划分,不必再因为性能问题而纠结.
        利用好这个环节,应用开发者可以配置出最优的代码打包方案,如Facebook做的那样.
        利用好这个环节,模块化架构可以不必纠结add时attach影响页面速度,不attach又拖慢功能使用.
但这不重要,可能没有一条适合你.

我们看到Hedger Wang在文章开头先抱怨了一通,然后使用GCC解决了这些问题.
而这里给出的几个场景完全不同,又何其相似.
我们也抱怨一通,然后经GCC启发,在其引入的预编译阶段也解决了这些问题.

每个应用都会遇到自己独特的问题被抱怨,也能在预编译这个时间窗口解决一些什么么?

分享到:
评论

相关推荐

    Laya 用TypeScript写的代码,编译成JavaScript后bundle.js没更新问题的原因追寻.pdf

    在开发Laya项目时,使用TypeScript作为源代码语言,然后将其编译为JavaScript,有时可能会遇到一个棘手的问题:bundle.js文件没有更新。这个问题在初看之下可能让人困惑,尤其是当你尝试各种方法如新建工程、拷贝...

    Laya 用TypeScript写的代码,编译成JavaScript后bundle.js没更新.pdf

    在使用Laya开发游戏或应用时,遇到的一个常见问题是 TypeScript 编写的代码在编译成JavaScript后,bundle.js 文件没有更新。这个问题可能导致开发者的新添加功能无法正常工作,因为bundle.js中没有反映出这些改动。...

    【JavaScript源代码】手把手教你如何编译打包video.js.docx

    【JavaScript源代码】手把手教你如何编译打包video.js 在JavaScript开发中,有时我们需要对第三方库进行编译和打包,以适应项目需求或优化性能。video.js 是一个流行的开源JavaScript库,专用于处理HTML5视频播放。...

    将一个vue文件编译成js文件的工具

    Vue.js 是一款流行的前端框架,它使用组件化的方式构建用户界面,其源代码通常是以 `.vue` 文件形式存在。`.vue` 文件包含模板、脚本和样式三个主要部分,这使得代码结构清晰,易于管理和维护。然而,在实际的项目...

    nwjs(v0.14.7)中使用sqlite3所需的编译文件和使用教程

    使用`nw.App.dataPath`获取一个安全的本地存储路径。 9. **使用教程**:一旦编译完成并成功导入,你就可以开始使用SQLite3 API进行数据操作,如创建数据库、表,执行SQL查询,事务处理等。务必遵循SQLite3的官方...

    javascript预编译思考

    JavaScript中的变量声明会被提升到当前作用域的顶部,这是预编译阶段的一个重要表现。理解这一点对于避免潜在的运行时错误至关重要。例如,即使在变量声明之后使用,JavaScript引擎也会在预编译阶段找到并处理变量...

    wasm使用vs2022编译

    接下来,我们使用 CMakeLists.txt 文件生成 Makefile,然后使用 emmake 工具将 C++ 代码编译成 WASM 文件。 ```cmake cmake .. emmake cmake .. emmake make ``` 这将生成一个 lib.a 文件,然后我们可以使用 emcc ...

    Node.js-一个简单的CLI用于将Node.js模块及其所有依赖项编译为单个文件

    这通常涉及一系列的编译和链接步骤,将JavaScript代码和其依赖项整合在一起,形成一个独立的可执行文件。 这个CLI工具可能是`ncc`,全称是`node.js compiler`,它是zeit公司(现为Vercel)开发的一个开源项目。`ncc...

    代码编译软件

    在IT行业中,代码编译软件是开发者不可或缺的工具,它能将人类可读的源代码转换为计算机可执行的机器语言。"代码编译软件"这个标题暗示了我们讨论的主题,即用于处理和编译代码的工具。这些工具通常包括各种编程语言...

    android.bp动态编译文档

    例如,如果一个模块只在特定的设备或产品变体上存在,我们可以在`if`语句中检查这些条件。 ```javascript if (is_my_device) { android_library { name: "my_library", srcs: ["src/main/java/...

    编程开发-编译工具-respond.main.js.zip

    "respond.main.js"可能是一个用于处理响应式布局的JavaScript库,它可能利用了JIT编译来优化代码执行。 在JavaScript环境中,编译过程分为两个主要步骤:解析和执行。解析阶段,源代码被转化为抽象语法树(AST),...

    vue-devTool编译和安装教程附源代码和编译后的安装包

    Vue.js 是一个流行的前端JavaScript框架,用于构建用户界面。Vue DevTools 是一款强大的浏览器扩展,它为Vue应用程序提供了丰富的开发工具,包括组件树查看、实时数据观察、性能分析等功能。在Chrome、Firefox等...

    安装typescript环境并开启VSCode自动监视编译ts文件为js文件.doc

    安装typescript环境并开启VSCode自动监视编译ts文件为js文件 本文将详细介绍如何安装typescript环境,并配置VSCode以...这样,我们可以简洁地编写TypeScript代码,并自动编译成JavaScript文件,方便了我们的开发工作。

    node.js 源码编译后(win)

    Node.js是一个开源、跨平台的JavaScript运行环境,它允许开发者在服务器端运行JavaScript代码。源码编译通常是为了获取最新特性、优化性能或者针对特定系统进行定制。接下来,我们将深入探讨Node.js源码编译的过程...

    Mono-mbe版源码编译.pdf

    对于大多数Windows用户而言,搭建Linux环境的一个常见做法是使用虚拟机。具体来说,可以通过下载和安装虚拟机软件以及Linux发行版(例如Ubuntu),来创建一个适合编译的环境。安装虚拟机和Linux的具体步骤在网上有很...

    web代码混淆方案.混淆js代码,压缩css代码

    **混淆JavaScript代码** JavaScript混淆是一种通过改变原始代码的可读性来增加其保密性的技术。这通常涉及到变量名和函数名的重命名,以及代码结构的打乱。例如,Proguard是一款常用的Java混淆工具,虽然它主要用在...

    Kettle源码编译流程说明

    - 构建完成后,会在项目根目录下生成一个名为`dist`的目录,该目录包含了所有构建好的可运行应用。 5. **启动Kettle** - 进入`build`目录,运行`spoon.bat`来启动Kettle。 #### 四、常见问题及解决方法 1. **...

    js模板编译原理

    通过以上分析,我们可以看到JS模板引擎的工作原理主要是通过解析模板、生成并执行JavaScript代码来实现动态内容的填充。这种方式不仅提高了开发效率,还使得页面内容更加灵活多样。在实际开发中,开发者可以根据项目...

    Node.js-Node.js的PNG解码器使用LodePNG编译成WebAssembly

    在IT行业中,Node.js是一个基于Chrome V8引擎的JavaScript运行环境,它允许开发者在服务器端使用JavaScript进行编程。本文将深入探讨如何在Node.js中利用LodePNG库编译成WebAssembly来实现PNG图像的解码功能。 首先...

    微信小程序反编译脚本(配合Node.js使用)

    这篇描述提到的"微信小程序反编译脚本"是一个工具,可以帮助开发者或者研究者获取已经被编译的小程序的源代码。这个脚本是从GitHub上获取的,由社区的大神分享,它声称可以无痛地反编译微信小程序,无需安装额外的...

Global site tag (gtag.js) - Google Analytics