资讯专栏INFORMATION COLUMN

切图崽的自我修养-使用模块化JS

littleGrow / 768人阅读

摘要:之前的闭包也好,自执行函数也好,都是模块化的一些尝试,直到规范推出之后,模块化才真正迅猛发展起来。因为有了模块化的概念,才有了按需加载的概念。

前言

我们来玩乐高积木吧

模块化Js已经成为了老生常谈,不过在JavaScript设计之初,由于定位的问题并没有提供类的功能,开发者需要模拟出类似的功能,来隔离、组织复杂的JavaScript代码。之前的闭包也好,自执行函数也好,都是模块化的一些尝试,直到CommonJs规范推出之后,模块化Js才真正迅猛发展起来。

从时间点上来说:

Node遵循CommonJs模块化规范,NPM包管理系统发展如此迅猛就是CommonJs模块化规范的最佳实践

后来在CommonJs的基础上衍生出了AMD/CMD规范,其各自的实践分别是RequireJSSeaJs

CommonJs同步加载规范

CommonJs规范遵循的是同步加载模块规范,即:

var A = require(./module/a);
A.funA();
var B = require(./module/b);
B.funB();

即只有a.js加载完以后,才能接着向下执行A.funA();才能接着向下加载b.js, 等b.js加载完之后,才能向下执行B.funB();。但这种同步串行的加载方式确对效率并没有多大影响,因为CommonJs是在Node上运行,处于服务器环境,服务器环境对模块的加载等同于硬盘的读写速度,是非常非常快的。

AMD/CMD异步加载规范

AMD/CMD 遵循的是异步加载模块规范,拿CMD规范的SeaJs举例:

 define(function(require,exports,module){
    require.async("./module/a", function(){alert(1)}
    require.async("./module/b", function(){alert(2)}
  });

其中,alert(1) 和alert(2)的执行顺序是不固定的,因为是采用异步加载模块的方式,a模块和b模块是并行加载的 ,谁先加载完毕,谁先掉用回调. 因为网络和文件大小的原因, 当然有可能是b模块先加载完毕,所以可能是alert(2)先执行.

因为requireJs(AMD)SeaJs(CMD) 都是运行在客户端浏览器上的. 模块的加载速度和网络状况有关系,加载情况是非常不稳定,如果采用同步串行加载的方式,会出现因为前面的模块加载耗时太长而阻塞了它之后的模块的加载. 所以AMD/CMD才有了异步的解决方案

(当然,AMD/CMD也支持同步加载)

按需加载

按需加载是模块化Js引伸出来的概念.我们可以让特定的页面加载特定的JS,就像搭积木刚好把房子搭起来一样,用Js模块组合的方式可以项目搭建起来,保证不缺少任何一个必要的模块,也保证不会有任何一个多余的模块.

如果index.html只需要弹窗功能和滑动功能,就只加载pop.js和slip.js

说起来倒是挺简单,但实际上呢?

实际上也非常简单,拿seaJS举例来说,页面index.html引用了Sea.js后,就可以以index.js为加载入口,对页面所需的七七八八的JS模块进行加载:

index.html:




其中index.js:

define(function(require,exports,module){
     //引入模块a
     var A = require("./module/a"); 
     //引入模块b
     var B = require("./module/b")     
     
     ...
});

其中a.js又依赖了其他的模块:

define(function(require,exports,module){
     //引入模块c
     var C = require("./module/c");          
     ...
});    

不管这个依赖关系有多复杂,层级有多深,seaJS的模块加载器会递归找到所有页面index.html依赖的Js,就拿例子来说,和index.html有关的依赖有 入口文件index.js和它依赖的a.js, b.js ,并且还有a.js依赖的 c.js 所以最后index.html实际上会加载index.js, a.js, b.js , c.js

这样就实现了页面需要什么模块,就加载什么模块(和这些模块依赖的模块),从而实现了按需加载。

但有同学估计又想到了,这个地方有个小缺陷,虽然模块化Js使得加载逻辑更清晰了,但是如此碎片化的Js会增加页面http的请求数,从而影响页面的加载速度。

没错,所以我们通常在上线前会利用自动化工具对当前页面依赖的所有Js做一个合并处理,即合并压缩成一个Js文件, 这样能最大程度上的利用浏览器缓存,减少Http请求数。

(注:Js模块书写的时候请尽量避免循环引用的问题,即a.js引用了c.js,反过来c.js又引用了a.js. 这肯定是模块书写不规范造成的,请检查这两个模块的逻辑是否有重叠. 当然,除此之外循环引用还是有别的办法解决的,这里就不提了)

结语

总而言之,模块化Js目前有两大规范(当然要说成三种规范也可以,不过在作者本人看来AMD/CMD并没有本质上的区别)

CommonJS同步加载模块规范,运行在服务端

AMD/CMD 异步加载模块规范,运行在客户端

因为CommonJs规范在服务器端的同步串行加载Js模块的方式并不适用于客户端浏览器,所以才有了AMD/CMD规范延伸出异步并行加载Js模块的方式。

因为有了Js模块化的概念,才有了Js按需加载的概念。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/79906.html

相关文章

  • 切图崽的自我修养使用自动化工具

    摘要:前言已烂想来大家对自动化构建工具已经不陌生了,自动化构建工具可以帮开发者省去很多重复劳动比如语法纠错文件打包文件操作,合并压缩等等常用的自动化构建工具有等等,这些构建工具核心都是依赖第三方插件,通过颗粒化任务,再将这些任务按照合适的方式进行 前言 F5已烂 showImg(https://segmentfault.com/img/bVyS47); 想来大家对自动化构建工具已经不陌生了,...

    jayce 评论0 收藏0
  • 切图崽的自我修养使用自动化工具

    摘要:前言已烂想来大家对自动化构建工具已经不陌生了,自动化构建工具可以帮开发者省去很多重复劳动比如语法纠错文件打包文件操作,合并压缩等等常用的自动化构建工具有等等,这些构建工具核心都是依赖第三方插件,通过颗粒化任务,再将这些任务按照合适的方式进行 前言 F5已烂 showImg(https://segmentfault.com/img/bVyS47); 想来大家对自动化构建工具已经不陌生了,...

    GT 评论0 收藏0
  • 切图崽的自我修养使用自动化工具

    摘要:前言已烂想来大家对自动化构建工具已经不陌生了,自动化构建工具可以帮开发者省去很多重复劳动比如语法纠错文件打包文件操作,合并压缩等等常用的自动化构建工具有等等,这些构建工具核心都是依赖第三方插件,通过颗粒化任务,再将这些任务按照合适的方式进行 前言 F5已烂 showImg(https://segmentfault.com/img/bVyS47); 想来大家对自动化构建工具已经不陌生了,...

    luqiuwen 评论0 收藏0
  • 切图崽的自我修养-[ES6] 编程风格规范

    摘要:前言没有规矩不成方圆用替换来定义变量如果是常量,使用静态字符串统一用单引号动态拼接成的字符串统一用反引号使用数组成员对变量赋值时,尽量用解构赋值往对象里添加修改属性时,使用,而不用松散的语法面向对象的写法一律写成的形式,摒弃原生的的书写方法 前言 没有规矩 不成方圆 用let替换var来定义变量. 如果是常量,使用const 静态字符串统一用单引号 , 动态拼接成的字符串统一用反...

    Bryan 评论0 收藏0
  • 切图崽的自我修养-[ES6] 编程风格规范

    摘要:前言没有规矩不成方圆用替换来定义变量如果是常量,使用静态字符串统一用单引号动态拼接成的字符串统一用反引号使用数组成员对变量赋值时,尽量用解构赋值往对象里添加修改属性时,使用,而不用松散的语法面向对象的写法一律写成的形式,摒弃原生的的书写方法 前言 没有规矩 不成方圆 用let替换var来定义变量. 如果是常量,使用const 静态字符串统一用单引号 , 动态拼接成的字符串统一用反...

    DoINsiSt 评论0 收藏0

发表评论

0条评论

littleGrow

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<