js模块化/js模块加载器/js模块打包器

之前对这几个概念一直记得很模糊,也无法用自己的语言表达出来,今天看了大神的文章,尝试根据自己的理解总结一下,算是一篇读后感。

大神的文章:http://www.css88.com/archives/7628(大神的文章写的很详细,建议先看完大神的文章)

一.js模块化

什么是js模块化,我们从历史说起。

1.一开始我们怎么写脚本?就是在html文件中用<script></script>写代码

这种方式的缺点:代码复用靠复制,基本是全局变量。

2.后来我们用js文件写代码,用<script></script>的src引入html,html/css/js分离

这种方式的缺点:

代码虽然可复用,但是<script></script>越来越多,一个html文件加载了好多js(http请求过多,影响性能),

全局变量也多,依赖关系也越来越复制,比如b依赖a,则a文件一定要在b文件之前加载

(这种方式的问题就是全局变量过多和依赖关系复杂)

3.为了解决全局对象的问题,我们进化到第三个阶段,用模块对象和IIFE(立即执行函数)

这种方式的缺点:

虽然暴露的全局变量少了,只有这一个模块对象,可以说解决了污染全局变量的问题,但是依赖关系还没解决,因为IIFE依赖这个模块对象进行各个文件的操作,就是说导入导出都靠这个模块对象。

(这个时候已经实现了js模块化,每个文件都包在匿名函数中,所以说每个文件都是一个模块,模块与模块之间的调用通过这个全局模块对象,这个时候的问题是,全局变量少了,但是依赖模块没解决,所有的js文件都依赖全局模块对象,就是说这个全局模块对象要在其他js文件之前引入,所以说我们下个方案就是解决依赖关系)

二.js模块加载器

新的模块化方案提出:解决了全局变量和依赖关系的问题,但是性能方面还可以优化。

commonJS规范的提出,让人们有了新的方案来解决全局变量污染和依赖关系复杂这两个问题。(一开始是运行在服务器端)。先让我们了解下什么是commonJS。

commonJS是一个规范,不是一个库,他提出了模块化方案,定义了一个模块化的API,让我们写出模块化的js更容易,不再需要借助IIFE。

用法:在一个js文件中,用export导出变量,用require导入

//a.js

var a=1;
module.exports=a;

//b.js
var a=require(/a.js);

这种方式在服务器端运行良好

但是有个问题,这种方式是同步运行的,俗称CMD(同步模块定义),(当然服务器端去读取文件特别快,没这个问题,不像浏览器端还要发请求去获取),就是说当b.js在require(a.js)时,这个时候js代码不会去往下执行,他必须等到a.js加载完才可以,如果a.js文件特别大,那么页面就会卡死,为什么?(因为commonJS是同步运行的,而js又是单线程的,会阻塞js文件的渲染),所以说浏览器端不能用这种方案,,所以commonJS提出了AMD(异步模块定义),就是获取文件是异步的,规范提出来了,但是在浏览器怎么实现?业内大神造出了轮子,用的多的就是require.js和sea.js

RequireJS 和 SeaJS 是模块加载器

利用模块加载器,我们只有一个入口文件,然后根据依赖关系去加载对应的js文件,依赖关系在入口文件写好,(只有一个入口文件,但是解析依赖关系的时候会去加载对应的依赖模块,加载的js文件就不止一个了)

两者的区别:

1.两者都是异步加载js,只不过一个写法遵循amd,一个写法遵循cmd,其实都是让浏览器支持模块化写法的库。

2.requirejs是无论模块需不需要都去加载完全部的依赖文件,seajs是某个模块需要用到才去加载,所以说AMD体验好,因为依赖模块一开始全都加载好了,cmd性能好,因为需要才去加载对应的模块

这样我们就可以在浏览器端实现模块化开发了,解决了全局变量的问题,也解决了依赖关系的问题,但是却也带来了新的问题,页面依赖的文件多(浏览器解析的时候就会去加载对应的依赖模块,一个模块就是一个文件),发起的http请求也多,随之而来的就是加载性能的影响(HTTP1,并行的http请求有限制个数).这个时候模块打包器就应运而生了.

三.模块打包器

在模块化加载器处理的基础上,为了减少解析时加载依赖模块而增加的http请求,我们可以把入口文件打包,在打包的过程中,让它去加载对应的依赖模块,最终生成的那份文件就是包含依赖模块的文件,那样就可以减少http请求,这样的打包操作我们交给构建工具或者说打包工具去实现,比如webpack/Browserify/rollup等等,这样,我们可以只专注怎么写出模块化的,可维护的,高聚合,低耦合的代码

随着es6的出现,js原生也出现了模块开发定义,也有对应的规范,用export导出,用import导入,让我们可以不用使用requirejs和seajs就能进行模块化开发,不过目前浏览器兼容性有限,不过我们可以用webpack来实现兼容,webpack不只可以帮我们把相关依赖的文件打成一个包,也能帮我们打成一个能够兼容的包(借助一些loader).

欢迎交流~

时间: 2024-10-09 11:37:16

js模块化/js模块加载器/js模块打包器的相关文章

JS模块化编程之加载器原理

世面上有好多JavaScript的加载器,比如 sea.js, require.js, yui loader, labJs...., 加载器的使用范围是一些比较大的项目, 个人感觉如果是小项目的话可以不用,  我用过seaJS和requireJS, 在项目中用过requireJS, requireJS是符合AMD,全称是(Asynchronous Module Definition)即异步模块加载机制 , seaJS是符合CMD规范的加载器. AMD__和__CMD AMD规范是依赖前置, CM

head.js让网站并行加载但顺序执行JS

http://headjs.com/ 并行加载JS,但是执行的时候却按顺序执行,提高网站速度 <script src="js/head.min.js"></script> <script type="text/javascript"> head.js("js/jquery-1.6.1.min.js","js/jquery.validate.min.js","js/my_valida

Python 模块化 模块搜索顺序、重复导入、模块加载列表(五)

模块搜索顺序.重复导入.模块加载列表 0x00 模块搜索顺序: 举例: #test.py import sys for p in sys.path: print(p) 运行结果: C:\python //pycharm环境中的Add content roots to PYTHONPATH C:\python //脚本所在目录 C:\Users\ihoney\AppData\Local\Programs\Python\Python35\python35.zip //打包,java扎包,避免大量小文

模块加载规范对比

一.commonJS模块加载规范 CommonJS规范加载模块是同步的,也就是说,只有加载完成,才能执行后面的操作.由于Node.js主要用于服务器编程,模块文件一般都已经存在于本地硬盘,所以加载起来比较快,不用考虑非同步加载的方式,所以CommonJS规范比较适用.浏览器端一般采用AMD模块加载方式或者ES6的模块加载标准. 模块导出方法(为防止混淆,建议一律采用module.exports而非exports): 模块导入方法:利用require //文件a.js module.exports

对于模块加载:ES6、CommonJS、AMD、CMD的区别

运行和编译的概念 编译包括编译和链接两步. 编译,把源代码翻译成机器能识别的代码或者某个中间状态的语言. 比如java只有JVM识别的字节码,C#中只有CLR能识别的MSIL.还简单的作一些比如检查有没有粗心写错啥关键字了啊.有啥词法分析,语法分析之类的过程. 链接,是把编译生成的二进制文件,组合成为一个系统可以执行的可执行文件. 运行: 把编译出来的可执行文件代码在系统中执行的过程,此时被装载到内存中. (代码保存在磁盘上没装入内存之前是个死家伙.只有跑到内存中才变成活的). 运行时类型检查就

[转] 通过反射实现动态功能模块加载

原文 如何通过反射实现动态功能模块加载 程序集包含模块,而模块包含类型,类型又包含成员.反射则提供了封装程序集.模块和类型的对象.您可以使用反射动态地创建类型的实例,将类型绑定到现有对象,或从现有对象中获取类型.然后,可以调用类型的方法或访问其字段和属性. 下面我们将介绍如何通过不使用反射的方式和使用反射的方式加载功能模块.实现效果: 1. WinForm 主程序 主程序我们使用Winform程序,VS2008 工具C#语言开发.包括工具栏.状态栏及TabControl控件.我们使用TabCon

python import 和 from.........import 模块加载和作用域

import导入:如import moduleName 变量名moduleNmae有两个目的:识别要被载入的外部文件同时生成脚本中的变量,在文件加载后,用来引用模块对象:因为import使一个变量名引用整个模块对象,我们必须通过模块名称来得到该模块的属性 from语句: from会把模块内的变量名赋值到另一个作用域(把模块中的变量名并且在from字句中选择的复制到了进行导入的作用域之内),所以它就可以让我们直接在脚本中使用复制后的变量而不用通过模块 默认情况下,Python只对每个文件的每个进程

*模块加载器、Node.js、NPM、Webpack基础汇总

--------------------------------NODE应用中的Node.js command prompt和Node.js--------------------------------------- ·安装node.js后,有两个可启动应用:黑色的Node.js command prompt和绿色的Node.js ·黑色的Node.js command prompt就和cmd DOS控制台一样,输入node -v后,若出现node的版本号,则表示当前node环境安装OK. ·

JS模块加载器加载原理是怎么样的?

路人一: 原理一:id即路径 原则.通常我们的入口是这样的: require( [ 'a', 'b' ], callback ) .这里的 'a'.'b' 都是 ModuleId.通过 id 和路径的对应原则,加载器才能知道需要加载的 js 的路径.在这个例子里,就是 baseUrl + 'a.js' 和 baseUrl + 'b.js'. 但 id 和 path 的对应关系并不是永远那么简单,比如在 AMD 规范里就可以通过配置 Paths 来给特定的 id 指配 path. 原理二:crea