精读 js 板块化发展
1 引言
如今,Javascript 板块化规范非常方便、自然,但这个新规范仅执行了2年,就在 4 年前,js 的板块化还停留在运行时支持,10 年前,通过后台模版定义、注释定义板块依赖。对经历过来的人来说,历史的板块化方式还停留在脑海中,反而新上手的同学会更快接受现代的板块化规范。
但为什么要理解 Javascript 板块化发展的历史呢?由于凡事都有两面性,理解 Javascript 板块化规范,有利于我们思考出更好的板块化方案,纵观历史,从 1999 年开始,板块化方案最多维持两年,就出现了新的替代方案,比原有的板块化更清晰、强壮,我们不可以被现代板块化方式限制住思维,由于现在的 ES2015 板块化方案距离发布也仅仅过了两年。
2 内容概要
直接定义依赖 (1999): 因为当时 js 文件非常简单,板块化方式非常简单粗暴 —— 通过全局方法定义、引使用板块。这种定义方式与现在的 commonjs 非常神似,区别是 commonjs 以文件作为板块,而这种方法能在任何文件中定义板块,板块不与文件关联。
闭包板块化模式 (2003): 使用闭包方式处理了变量污染问题,闭包内返回板块对象,只要对外暴露一个全局变量。
模版依赖定义 (2006): 这时候开始流行后台模版语法,通过后台语法聚合 js 文件,从而实现依赖加载,说实话,现在 go 语言等模版语法也很流行这种方式,写后台代码的时候不觉得,回头看看,还是挂在可维护性上。
注释依赖定义 (2006): 几乎和模版依赖定义同时出现,与 1999 年方案不同的,不仅仅是板块定义方式,而是终于以文件为单位定义板块了,通过 lazyjs 加载文件,同时读取文件注释,继续递归加载剩下的文件。
外部依赖定义 (2007): 这种定义方式在 cocos2d-js 开发中普遍用,其核心思想是将依赖抽出单独文件定义,这种方式不利于项目管理,毕竟依赖抽到代码之外,我是不是得两头找呢?所以才有通过 webwpack 打包为一个文件的方式暴力替换为 commonjs 的方式出现。
Sandbox模式 (2009): 这种板块化方式很简单,暴力,将所有板块塞到一个 sanbox 变量中,硬伤是无法处理明明冲突问题,毕竟都塞到一个 sandbox 对象里,而 Sandbox 对象也需要定义在全局,存在被覆盖的风险。板块化需要保证全局变量尽量干净,目前为止的板块化方案都没有很好的做到这一点。
依赖注入 (2009): 就是大家熟知的 angular1.0,依赖注入的思想现在已广泛运使用在 react、vue 等流行框架中。但依赖注入和处理板块化问题还差得远。
CommonJS (2009): 真正处理板块化问题,从 node 端逐步发力到前台,前台需要用构建工具模拟。
Amd (2009): 都是同一时期的产物,这个方案主要处理前台动态加载依赖,相比 commonJs,体积更小,按需加载。
Umd (2011): 兼容了 CommonJS 与 Amd,其核心思想是,假如在 commonjs 环境(存在 module.exports,不存在 define),将函数执行结果交给 module.exports 实现 Commonjs,否则使用 Amd 环境的 define,实现 Amd。
Labeled Modules (2012): 和 Commonjs 很像了,没什么硬伤,但生不逢时,碰上 Commonjs 与 Amd,那只有被人遗忘的份了。
YModules (2013): 既然都出了 Commonjs Amd,文章还列出了此方案,肯定有其独到之处。其核心思想在于用 provide取代 return,能控制板块结束时机,解决异步结果;拿到第二个参数 module,修改其余板块的定义(尽管很有拓展性,但使用在项目里是个搅屎棍)。
ES2015 Modules (2015): 就是我们现在的板块化方案,还没有被浏览器实现,大部分项目已通过 babel 或者 typescript 提前体验。
3 精读
本次提出独到观点的同学有:@流形@黄子毅@苏里约@camsong@杨森@淡苍@留影 精读由此归纳。
从语言层面到文件层面的板块化
从 1999 年开始,板块化探究都是基于语言层面的优化,真正的革命从 2009 年 CommonJS 的引入开始,前台开始大量用预编译。
这篇文章所提供的板块化历史的方案都是逻辑板块化,从 CommonJS 方案开始前台把服务端的处理方案搬过来之后,算是看到标准物理与逻辑统一的板块化。但之后前台工程不得不引入板块化构建这一步。正是这一步给前台开发无疑带来了诸多的不便,尤其是现在我们开发过程中经常为了优化这个工具带了很多额外的成本。
从 CommonJS 之前其实都只是封装,并没有一套板块化规范,这个就有些像类与包的概念。我在10年左右使用的最多的还是 YUI2,YUI2 是使用 namespace 来做板块化的,但有很多问题没有处理,比方多版本共存,因而后来 YUI3 出来了。
YUI().use('node', 'event', function (Y) {
YUI3 的 sandbox 像极了差不多同时出现的 AMD 规范,但早期 yahoo 在前台圈的影响力还是很大的,而 requirejs 到 2011 年才诞生,因而圈子不是使用着 YUI 要不就自己封装一套 sandbox,内部用 jQuery。
为什么板块化方案这么晚才成型,可可以早期应使用的复杂度都在后台,前台都是非常简单逻辑。后来 Ajax 火了之后,web app 概念的开始流行,前台的复杂度也呈指数级上涨,到今天几乎和后台接近一个量级。工程发展到肯定阶段,要出现的必然会出现。
前台三剑客的板块化展望
从 js 板块化发展史,我们还看到了 css html 板块化方面的严重落后,如今依赖编译工具的板块化加强在未来会被标准所替代。
原生支持的板块化,处理 html 与 css 板块化问题正是以后的方向。
再回到 JS 板块化这个主题,开头也说到是为了构建 scope,实则提供了业务规范标准的输入输出的方式。但文章中的 JS 的板块化还不等于前台工程的板块化,Web 界面是由 HTML、CSS 和 JS 三种语言实现,不管是 CommonJS 还是 AMD 包括之后的方案都无法处理 CSS 与 HTML 板块化的问题。
对于 CSS 本身它就是 global scope,因而开发样式能说是喜忧参半。近几年也涌现把 HTML、CSS 和 JS 合并作板块化的方案,其中 react/css-modules 和 vue 都为人熟知。当然,这一点还是非常依赖于 webpack/rollup 等构建工具,让我们意识到在 browser 端还有很多本质的问题需要推进。
对于 css 板块化,目前不依赖预编译的方式是 styled-component,通过 js 动态创立 class。而目前 css 也引入了与 js 通信的机制 与 原生变量支持。未来 css 板块化也很可可以是运行时的,所以目前比较看好 styled-component 的方向。
对于 html 板块化,小尤最近爆出与 chrome 小组调研 html Modules,假如 html 得到了浏览器,编辑器的板块化支持,未来可可以会取代 jsx 成为最强大的板块化、模板语言。
对于 js 板块化,最近出现的
板块化加载方式,尽管还没有得到浏览器原生支持,但也是我比较看好的未来趋势,这样就连 webpack 的拆包都不需要了,直接把源代码传到服务器,配合 http2.0 完美抛开预编译的枷锁。
上述三中方案都不依赖预编译,分别实现了 html、css、js 板块化,相信这就是未来。
板块化标准推进速度依然缓慢
2015 年提出的标准,在 17 年仍然没有得到实现,即使在 nodejs 端。
这几年 TC39 对语言终于重视起来了,慢慢有动作了,但针对板块标准制定的速度,与落实都非常缓慢,与 javascript 越来越流行的趋势逐步脱节。nodejs 至今也没有实现 ES2015 板块化规范,所有 jser 都处在构建工具的阴影下。
Http 2.0 对 js 板块化的推动
js 板块化定义的再美好,浏览器端的支持粒度永远是瓶颈,http 2.0 正是考虑到了这个因素,大力支持了 ES 2015 板块化规范。
幸运的是,板块化构建将来可可以不再需要。随着 HTTP/2 流行起来,请求和响应能并行,一次连接允许多个请求,对于前台来说宣告不再需要在开发和上线时再做编译这个动作。
几年前,板块化几乎是每个流行库必造的轮子(YUI、Dojo、Angular),大牛们自己爽的同时其实造成了社区的分裂,很难积累。有了 ES2015 Modules 之后,JS 开发者终于能像 Java 开始者十年前一样用一致的方式愉快的互相引使用板块。
不过 ES2015 Modules 也只是处理了开发的问题,因为浏览器的特殊性,还是要经过繁琐打包的过程,等 Import,Export 和 HTTP 2.0 被主流浏览器支持,那时候才是彻底的板块化。
Http 2.0 后就不需要构建工具了吗?
看到大家基本都提到了 HTTP/2,对这项技术处理前台板块化及资源打包等工程问题抱有非常大的期待。很多人也认为 HTTP/2 普及后,基本就没有 Webpack 什么事情了。
不过 Webpack 作者 @sokra 在他的文章 webpack & HTTP/2 里提到了一个新的 Webpack 插件 AggressiveSplittingPlugin。简单的说,这款插件就是为了充分利使用 HTTP/2 的文件缓存可以力,将你的业务代码自动拆分成若干个数十 KB 的小文件。后续若其中任意一个文件发生变化,能保证其余的小 chunck 不需要重新下载。
可见,即便不断的有新技术出现,也仍然需要配套的工具来将前台工程问题处理方案推向极致。
板块化是大型项目的银弹吗?
只需遵循了最新板块化规范,即可以使项目具备最好的可维护性吗? Js 板块化的目的是支持前台日益上升的复杂度,但绝不是唯一的处理方案。
分析下 JavaScript 为什么没有板块化,为什么又需要板块化:这个 95 年被设计出来的时候,语言的开发者根本没有想到它会如此的大放异彩,也没有将它设计成一种板块化语言。按照文中的说法,99 年也就是 4 年后开始出现了板块化的需求。假如只有几行代码使用板块化是扯,初始的 web 开发业务逻辑都写在 server 端,js 的作使用小之又小。而现在 spa 都出现了,几乎所有的渲染逻辑都在前台,假如还是没有板块化的组织,开发过程会越来越难,维护也是更痛苦。
文中已经详细说明了板块化的发展和优劣,这里不准备做过多的探讨。我想说的是,在板块化之后还有一个板块间耦合的问题,假如板块间耦合度大也会降低代码的可重使用性或者者说复使用性。所以也出现了降低耦合的观察者模式或者者发布/订阅模式。这对于提升代码重使用,复使用性和避免单点故障等都很重要。说到这里,还想顺便提一下最近流行起来的响应式编程(RxJS),响应式编程中有一个很核心的概念就是 observable,也就是 Rx 中的流(stream)。它能被 subscribe,其实也就是观察者设计模式。
补充阅读
JavaScript 板块化七日谈
JavaScript板块化编程简史(2009-2016)
总结
未来前台复杂度不断添加已成定论,随着后台成熟,自然会将焦点转移到前台领域,而且服务化、使用户体验越来越重要,前台体验早不是当初可以看就行,任何网页的异常、视觉的差异,或者文案的模糊,都会导致使用户流失,支付中断。前台对公司营收的影响,渐渐与后台服务宕机同等严重,所以前台会越来越重,异常监控,性可以检测,工具链,可视化等等都是这几年大家逐步重视起来的。
我们早已不可以将 javascript 早期玩具性质的板块化方案使用于现代越来越重要的系统中,前台界必然出现同等重量级的板块化管理方案,感谢 TC39 制定的 ES2015 板块化规范,我们已经离不开它,哪怕所有人必需用 babel。
话说回来,标准推进的太慢,我们还是把编译工具当作常态,抱着哪怕支持了 ES2015 所有特性,babel 仍然还有使用的心态,将预编译进行究竟。一句话,板块化仍在路上。js 板块化的矛头已经对准了 css 与 html,这两位元老也该向前卫的 js 学习学习了。
未来 css、html 的板块化会自立门户,还是赋予 js 更强的可以力,让两者的板块化依附于 js 的可以力呢?目前 html 有自立门户的苗头(htmlModules),而 css 迟迟没有改变,社区出现的 styled-component 已经使用 js 将 css 板块化得很好了,最新 css 规范也支持了与 js 的变量通信,难道希望依附于 js 吗?这里希望得到大家更广泛的探讨。
我也认同,毕竟压缩、混淆、md5、或者者利使用 nonce 属性对 script 标签加密,都离不开本地构建工具。
据说 http2 的优化中,有个最佳文件大小与数量的比例,那么还是脱离不了构建工具,前台未来会越来越复杂,同时也越来越美好。
至此,对于 javascript 板块化探讨已接近尾声,对其优缺点也基本达成了一致。前台复杂度不断提高,促使着板块化的改进,代理商(浏览器、node) 的支持程度,与前台特殊性(流量、缓存)可可以前台永远也离不开构建工具,新的标准会让这些工作做的更好,同时取代、加强部分特征,前台的未来是更加美好的,复杂度也更高。
原文地址:https://zhuanlan.zhihu.com/p/26118022
我只是搬运工。
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » 精读 js 板块化发展