JavaScript模块化的旅程

原创 Badmaster_Y 随笔 瞎鼓捣 257阅读 2017-12-04 17:47:57 举报

写在前面的话:(摘自阮一峰的网络日志:Javascript模块化编程(一):模块的写法

随着网站逐渐变成"互联网应用程序",嵌入网页的Javascript代码越来越庞大,越来越复杂。
网页越来越像桌面程序,需要一个团队分工协作、进度管理、单元测试等等......开发者不得不使用软件工程的方法,管理网页的业务逻辑。
Javascript模块化编程,已经成为一个迫切的需求。理想情况下,开发者只需要实现核心的业务逻辑,其他都可以加载别人已经写好的模块。但是,Javascript不是一种模块化编程语言,它不支持"类"(class),更遑论"模块"(module)了。(现在ES6已经支持模块化的概念,我们在后续介绍)。

本文根据时间顺序为各位讲解一下前端模块化的一些东西,前一部分或许并不是很有趣,也不是很重要(毕竟是老古董了)。感兴趣可以看一看,重点在后半部分。摘自部分我会在最后给出文献。其中大篇幅为转载整理,有一小部分是我个人见解,若有不准请指出。

Why Modular? —— WEB IS EVOLVING

[ul]
[li]网站正在变成网络应用[/li]
[li]当站点变得更大时,代码的复杂性就会增加[/li]
[li]需要高度解耦的JS文件/模块[/li]
[li]部署需要在几个HTTP调用中优化代码[/li]
[/ul]

一、上古时期——MODULE?从设计模式说起

1.模块就是实现特定功能的一组方法。
最早,只要把不同的函数(以及记录状态的变量)简单地放在一起,就算是一个模块。
javascript 代码

上面的函数foo()和bar(),组成一个模块。使用的时候,直接调用就行了。
这种做法的缺点很明显:Global 被污染,很容易命名冲突,而且模块成员之间看不出直接关系。

2.为了解决上面的缺点,可以把模块写成一个对象,所有的模块成员都放到这个对象里面。简单封装:Namespace 模式:
javascript 代码

减少 Global 上的变量数目,本质是对象,这样的写法会暴露所有模块成员,内部状态可以被外部改写。一点都不安全。

3.使用"立即执行函数"(Immediately-Invoked Function Expression,IIFE),可以达到不暴露私有成员的目的。匿名闭包 :IIFE 模式:
html 代码

使用上面的写法,外部代码无法读取内部的变量。函数是 JavaScript 唯一的 Local Scope。

4.再增强一点 :引入依赖
javascript 代码

这就是模块模式,也是现代模块实现的基石。

二、石器时代——SCRIPT LOADER——只有封装性可不够,我们还需要加载

让我们回到脚本标记,秩序是有必要的,DOM顺序便是执行顺序。
javascript 代码

这样的代码看着也不错,不是么?然后,现实是这样的…
javascript 代码

WTF?这一堆代码是什么鬼?!
难以维护 Very difficult to maintain!
依赖模糊 Unclear Dependencies
请求过多 Too much HTTP calls

1.LABjs - Script Loader(2009)
加载和阻塞JavaScript,使用LABjs将取代所有的丑陋“脚本标记汤”。
How Does It Works?
javascript 代码

并行执行?No,并不是的。

Sugar
javascript 代码

Dependency Management——基于文件的依赖管理。

三、蒸汽朋克——MODULE LOADER——模块化架构的工业革命

YUI3 Loader - Module Loader(2009)
YUI核心和是轻量级的模块化的体系结构使,它可伸缩、快速和健壮。
回顾往昔王者的风采:(是的,现在谁还用呢?)
javascript 代码

YUI3是一个基于模块的依赖管理。
Y 其实是一个强沙箱,所有依赖模块通过 attach 的方式被注入沙盒(attach:在当前 YUI 实例上执行模块的初始化代码,使得模块在当前实例上可用)。
那么现在还去使用恶心的“脚本标记汤”么?我们不再需要在一个集合顺序中包含脚本标记,从执行中分离加载。

额,好吧,我们漏了一个问题——Too much HTTP calls
YUI Combo
那么是如何工作的?如果我们不使用模块化的东西,我们或许会像下面这样引用:
javascript 代码

但这不是我们希望看到的,↓ magic combo:
javascript 代码

GET请求,这需要服务器支持。
优化:合并 Concat,压缩 Minify,混淆 Uglify。

四、号角吹响——COMMONJS——征服世界的第一步是跳出浏览器

CommonJS - API Standard(2009)
javascript:不仅仅是为了浏览器!(从这一次开始,JavaScript开始了征服世界的脚步)

MODULES/1.0
所以,现在我们使用这种方式进行模块的定义与引用:
javascript 代码

很神奇,不是么?然而既然提到了commonjs那不得不说一下node了。
NodeJS : Simple HTTP Server
javascript 代码

javascript 代码

同步(Synchronously)——同步/阻塞式加载
javascript 代码

然而同步加载对服务器/本地环境并不是问题,浏览器环境才是问题!

五、双塔奇兵——AMD/CMD——浏览器环境模块化方案

Modules/Async
Modules/Wrappings
Modules/Transport
Modules/2.0
《前端模块化开发的那点历史 - 玉伯》

AMD(Async Module Definition)——RequireJS 对模块定义的规范化产出
CMD(Common Module Definition)——SeaJS 对模块定义的规范化产出

2.RequireJS - AMD Implementation(2011)
JavaScript文件和模块加载器。它是为在浏览器内使用而优化的。
If require() is async?
javascript 代码

然而这段代码并不起作用。

下面这段代码看起来一定很熟悉:
javascript 代码

Sugar - 简化的CommonJS包装
javascript 代码

javascript 代码

AMD vs CommonJS——书写风格
javascript 代码

javascript 代码

AMD vs CommonJS——执行时机
javascript 代码

javascript 代码

3.SeaJS - CMD Implementation(2011)
非常简单的模块开发经验。看起来很像CommonJS代码。
javascript 代码

javascript 代码

AMD vs CMD - 真正的不同——执行时机
javascript 代码

javascript 代码

六、精灵宝钻——BROWSERIFY/WEBPACK——大势所趋,去掉这层包裹!

1.NPM——Node Package Manger
浏览器没有定义的需求方法,但Node.js可以。

2.Browserify - CommonJS In Browser
通过将所有依赖项捆绑起来,在浏览器中require('modules')。
安装:[backcolor=#bfbfbf]$ npm install -g browserify[/bgcolor]
实际上您只需要编写CommonJS代码!
javascript 代码

每一次改动都需要手动 recompile ?

No, auto-recompile.

Watch - Watchify
javascript 代码

Build 后要如何 Debug

Source Map——逆向所有合并、压缩、混淆!
javascript 代码

Npm Run
javascript 代码

3.鼎鼎大名的 Webpack - Module Bundler
对任何资源或资产进行转换、捆绑或打包。然而webpack的核心概念是模块化的打包机,只不过对于过多的插件混淆了这一原本分明的标识。
至于webpack的用法请详见:《SurviveJS - Webpack: From apprentice to master》——这是一本很棒的webpack从学徒与大师(From apprentice to master)的书,不过想要更深入的了解webpack还是建议查看官方文档。这本书面向新手或对于webpack有一定了解的前端开发者

七、王者归来——ES6 MODULE——最后的战役

虽然现在ES6还是存在着兼容性的问题,但我们也不得不断言,ES6是大势所趋。而兼容性问题也并非没有好的解决方案:
Babel - JavaScript Compiler(2015)
javascript 代码

哇哦。很神奇不是么?
ECMA-262/6.0/#Exports

ECMA-262/6.0/#Imports
“ 习惯了就会觉得很好用的 (´Д` ) ”
现在的技术核心:

JavaScript模块化的旅程

JavaScript模块化的旅程

关于ES6的学习,可以查看《ES6标准入门》一书。
或者去查看官方文档

主要出处:JavaScript 模块化七日谈 -《JavaScript Modularization Journey》

最后,前端路漫漫,莫忘初心!
评论 ( 1 )
最新评论
Badmaster_Y 2017-12-05 09:09:39 1F

补充一句,虽然ES6很好用,但是还是与webpack一同使用才是王道,毕竟ES6自身并没有打包捆绑的功能。