js模块化入门与commonjs解析与应用

  • JS模块化的基本原理
  • commonjs规范
  • commonjs在前端模块化中的基本使用
  • commonjs的实现原理
  • AMD与CMD规范剖析博客链接

一、JS模块化基本原理

在JS没有提出来模块化的时候,开发JS项目比较简单,同时也比较杂乱,第一个问题就是全局变量的管理,为了解决这个问题基本上都使用了命名空间和闭包两个主流的解决方式,但是随着硬件基础和网络环境的改善,前端开发也越来越复杂,需要协同合作,代码复用的需求越来越多,复杂性带来的第一个问题就是命名管理问题再次遇到挑战,然后就是协同开发也被正式提上了议题,模块化正式走入台前。

 1 var a = 1;
 2 //函数
 3 function bindeEvent(){}
 4 function addClass(){}
 5 //命名空间
 6 var obj1 = {
 7     a:2,
 8     foo:function(){}
 9 }
10 var obj = {
11     a:2,
12     foo:function(){}
13 }
14 //闭包
15 (function($){
16     var a = 123;
17     function foo(){}
18     return {foo:foo}
19 })(jQuery);

模块化的在很大程度上与闭包的实现模式非常类似,传入闭包的参数可以看作是模块的引用,返回值可以看作是模块定义的接口,整个闭包就可以理解为一个模块,有差别的地方就是模块化是一个模块单独在一个js文件中实现、模块中使用的模块自身以外的参数和属性都必须依赖引入。

有了单独js文件和各种规范的标准接口,就能很好的实现了协同开发这问题,解决了前端开发越来越麻烦的复杂性,同时命名冲突问题也在模块的私有变量特性中迎刃而解。

二、commonjs规范

在commonjs官网的最上方有一句这样的描述:javascript: not just for browsers any more!翻译:javascript:不仅仅是针对浏览器了!最近两年在前端很火的nodejs就是commonjs规范的实现,而webpack是基于nodejs实现的,自然而然就是commonjs规范的实现。虽然我们后期在js的开发中不一定使用commonjs规范,但是我们需要使用webpack作为前端工程化的实现工具,还有基于nodejs的模块、插件、库,所以对于我们理解和应用其他技术很有帮助,所以对于commonjs的理解是有必要的。

可能说到这里,我们还不清除commonjs是个什么东西,这么来说,javascript官方定义的api只能构建基础的浏览器应用,也就是说javascript官方只实现了在浏览器环境中的api,如果来那javascript来做服务端应用程序,又或者是图形界面应用程序,还有命令行工具等就有些力不从心,2009年程序员Ryan Dahl创造了node,js项目,将javascript用于服务器端编程,这标志这javascript模块化开发的诞生,而commonjs就是这个模块的规范。

commonjs都有哪些规范呢?

1.commonjs的出发点:js没有模块系统、标准库较少、缺乏包管理工具;为了让javascript可以在任何地方运行,以达到JAVA、C#、PHP这些后台语言的开发能力。

2.commonjs规范的具体内容:

 一个文件就是一个模块;

 普通方式定义的变量、函数、对象都属于该模块内;

 通过require来加载模块;

 通过exports和modul.exports来暴露模块中的内容(接口);

3.所有代码都运行在模块作用域,不会污染全局作用域;模块可以多次加载,但只会在第一次加载的时候运行,然后运行结果就被缓存了,以后再加载就读取缓存里面的结果;模块的加载顺序按照代码的出现顺序同步加载。

4._dirname代表当前模块文件所在的文件夹路径,_filename代表当前模块文件所在文件夹路径+文件名。

5.require(同步加载基本功能):读取并执行一个js文件,然后返回该模块的exports对象,如果没有发现指定模块会报错。

6.模块内的exports:nodejs为每个模块提供了一个exposrts变量,其指向module.exports,相当于再模块头部加了这句代码:var exports = module.exports;在对外输出时,可以给exports对象添加方法,但不能直接赋值,因为这样会切断exports与module.exports的联系。

7.npm root -g 查看全局包安装位置,建议nvm目录下npm\node_modules目录,然后设置npm全局包安装位置npm config set prefix "",然后将该路径添加到环境变量中;

8.npm init -y 初始化package.json文件,加上-y就会默认生成该文件;npm docs 包名:查看包的文档;npm install:安装package.json中dependencies属性中所以来的包。

9.由于npm服务器是国外的,下载慢或者不能下载成功经常出现,建议使用淘宝NPM镜像http://npm.taobao.org/,与官方NPM同步频率为10分钟一次,安装命令:npm install -g cnpm --registry=https://registry.npm.taobao.org,安装包:cnpm install 包名(其它命令基本一致);

10.如果你不想下载cnpm,npm还提供了一个镜像源管理工具:npm install -g nrm,通过:nrm ls,查看镜像源列表 ,通过:npm use 镜像源,来切换;

11、NPM的模块加载机制:

如果require的是绝对路径文件,查找不会去遍历每个node_modules目录,其速度最快

  1).从module.paths数组中(由当前执行文件目录到磁盘根目录)取出第一个目录作为查找基准

  2).直接从目录中查找该文件,如果存在则结束查找,如果不存在则进行下一条查找

  3).尝试添加.js、.json、.node后缀之后查找,如果存在文件则结束查找,如果不存在则进行下一条查找

  4).尝试将require的参数作为一个包来进行查找,读取目录下的package.json文件,取得Main参数指定的文件

  5).尝试查找该文件,如果存在则结束查找,如果不存在则进行第3条查找

  6).如果继续失败,则取出module.paths数组中的下一目录作为基准查找,循环第1-5个步骤

  7).如果继续失败,循环第1-6个步骤,直到module.paths中的最后一个值

  8).如果继续失败,则抛出异常

三、commonjs在前端模块化中的基本使用

Commonjs规范最开始就是为了将javascript运行在服务器环境下,所以采用了同步加载不同模块文件,适用于服务端。因为模块文件都存放在服务器的各个硬盘上,读取速度块,适合服务器,不适应浏览器。

而且浏览器不兼容Commonjs,原因是浏览器缺少module、exports、require、global是个环境变量。如果要使用的化需要工具转换,有时候还会用到global这个nodejs中的全局变量,相当于dom中的window变量。

在前端开发中使用Commonjs模块化规范:

1.定义文件结构:

//工作区间
    -->modules//依赖模块
        -->m1.js
        -->m2.js
        -->m3.js
    -->demo.html//结构文本
    -->index.js//主入口文件

依赖模块代码(m1.js):

1 module.exports = {
2     msg:‘m1‘,
3     foo:function(){
4         return this.msg;
5     }
6 }

依赖模块代码(m2.js):

1 module.exports = function(){
2     return ‘m2‘;
3 }

依赖模块代码(m3.js):

1 // var exports = module.exports;在第博客二部分:commonjs规范中第六小点由说明
2 exports.foo = function(){
3     return ‘ms‘;
4 }

主入口文件(index.js):

1 var m1 = require(‘./modules/m1‘);
2 var m2 = require(‘./modules/m2‘);
3 var m3 = require(‘./modules/m3‘);
4
5 console.log(m1.foo());
6 console.log(m2());
7 console.log(m3.foo());

前面规范中说过在浏览器并不支持commonjs规范,主入口文件index.js肯定不能直接被demo.html结构文本使用,直接使用的话会报错;所以在要前端开发中使用commonjs规范的话就必须使用插件将commonjs模块化规范转换成浏览器识别的代码结构,在这之前系统上必须安装nodejs环境,这时候我们可以先在控制台中测试看看index.js的依赖是否成功:

1 node -v //测试node环境是否安装成功,如果成功的话会在控制台打印出node的版本号
2 node index.js

打印结果:

这是在node环境下能够编译执行index.js,前面说过要想将commonjs模块化结构代码在浏览器中编译执行,得需要使用工具转换成浏览器能够编译执行的代码结构,这个工具就是Browserify,工具的官网:http://browserify.org/

下载安装成功是这样的:

在Browserify官网首页的使用介绍中有这样一句命令说明:

意思是将commonjs规范的main.js文件通过browserify转换成浏览器能够执行的bundle.js文件;那么我们就可以使用这个命令来将示例中的index.js转换成一个可以在浏览器使用的js文件(下面这句命令是要在命令窗口执行):

 browserify index.js -o bundle.js

这行命令执行完成后会在我们的工作区间生成一个bendle.js文件,这个文件就是通过browserify工具将基于commonjs规范的index.js入口文件及其依赖的m1.js、m2.js、m3.js转换生成的浏览器可以执行的js代码。

这时候我们可以将bundle.js引入到demo.html结构文件中进行执行:

<script src="bundle.js"></script>

打开页面-查看浏览器控制台:

在前端使用commonjs规范然后使用browserify转换成浏览器能执行的文件,全部过程演示完成;值得我们关注的是生成的bundle.js是什么?

从生成的代码来看,本质上就是将依赖的文件合并到了一个文件中,然后同样是采用闭包加对象属性实现的命名空间的代码管理方式,只不过这个过程我们交给了工具来实现,在我们的日常开发中,我们只需要关注我们自己的模块开发,不再需要去考虑全局命名冲突,代码管理问题。而且通过模块化开发带来的最大的好处就是代码的复用性特别方便,采用依赖模式然后使用工具转换,也解决了原来在结构文件中引入大量插件和库的问题,给代码瘦身的同时也降低了网络请求压力。特别是插件、库、组件之间的相互依赖关系带来的加载阻塞问题得到了很好的解决。

然后,在Browserify的官方首页使用介绍中有一个基于全局模块uniq的示例:

下载安装uniq模块:

npm install uniq

下载安装成功以后会在当前工作区间生成一个node_modules文件夹和一个packge-lock.json文件,各相关的原理在webpack博客中详细解析。然后,官网给出的代码放到我们示例代码中的index.js中:

1 var unique = require(‘uniq‘);
2 var data = [1, 2, 2, 3, 4, 5, 5, 5, 6];
3 console.log(unique(data));

然后,在控制台中再次编译一次index.js到bundle.js:

 browserify index.js -o bundle.js

然后刷新demo.html,查看浏览器控制台:

关于commonjs的实现原理等过段时间再来补充;

AMD、COM规范解析

原文地址:https://www.cnblogs.com/ZheOneAndOnly/p/11071280.html

时间: 2024-09-29 00:51:00

js模块化入门与commonjs解析与应用的相关文章

一览js模块化:从CommonJS到ES6

本文由云+社区发表 模块化是指把一个复杂的系统分解到一个一个的模块. 模块化开发的优点: (1)代码复用,让我们更方便地进行代码管理.同时也便于后面代码的修改和维护. (2)一个单独的文件就是一个模块,是一个单独的作用域,只向外暴露特定的变量和函数.这样可以避免污染全局变量,减少变量命名冲突. js模块化规范有:CommonJS.AMD.CMD.ES6的模块系统.本文将依次介绍下每个规范. 0.早期:用script来引入js模块 <script type="text/javascript&

js模块化编程之CommonJS和AMD/CMD

一.CommonJS 1.CommonJS API定义很多普通应用程序(主要指非浏览器的应用)使用的API,从而填补了这个空白.它的终极目标是提供一个类似Python,Ruby和Java标准库.这样的话,开发者可以使用CommonJS API编写应用程序,然后这些应用可以运行在不同的JavaScript解释器和不同的主机环境中. 在兼容CommonJS的系统中,你可以使用JavaScript开发以下程序: (1).服务器端JavaScript应用程序(2).命令行工具(3).图形界面应用程序(4

从273二手车的M站点初探js模块化编程

前言 这几天在看273M站点时被他们的页面交互方式所吸引,他们的首页是采用三次加载+分页的方式.也就说分为大分页和小分页两种交互.大分页就是通过分页按钮来操作,小分页是通过下拉(向下滑动)时异步加载数据. 273这个M站点是产品推荐我看的.第一眼看这个产品时我就再想他们这个三次加载和翻页按钮的方式,那么小分页的pageIndex是怎么计算的.所以就顺便看了下源码. 提到看源码时用到了Chrome浏览器的格式化工具(还是朋友推荐我的,不过这个格式化按钮的确不明显,不会的话自行百度). 三次加载和分

前端模块化方案:CommonJS/AMD/CMD/ES6规范

模块化的开发方式可以提高代码复用率,方便进行代码的管理.通常一个文件就是一个模块,有自己的作用域,只向外暴露特定的变量和函数.目前流行的js模块化规范有CommonJS.AMD.CMD以及ES6的模块系统.前端模块化的演进过程可以看看阮一峰老师的文章.本文主要介绍各规范下的模块化实现方式. 一.CommonJS Node.js是commonJS规范的主要实践者,它有四个重要的环境变量为模块化的实现提供支持:module.exports.require.global.实际使用时,用module.e

JS模块化:CommonJS和AMD(Require.js)

早期的JS中,是没有模块化的概念的,这一情况直到09年的Node.js横空出世时有了好转,Node.js将JS作为服务端的编程语言,使得JS不得不寻求模块化的解决方案. 模块化概念 在JS中的模块是针对单个文件的,即一个文件是一个模块,要使用这个模块就加载该文件即可. CommonJS node.js的模块系统,是参照CommonJS规范实现的. 定义模块和加载模块 在CommonJS中,有一个全局性方法require(),用于加载模块,而module.exports用于导出当前文件的模块. 假

再唠叨JS模块化加载之CommonJS、AMD、CMD、ES6

Javascript模块化编程,已经成为一个迫切的需求.理想情况下,开发者只需要实现核心的业务逻辑,其他都可以加载别人已经写好的模块. Javascript社区做了很多努力,在现有的运行环境中,实现"模块"的效果. CommonJS CommonJS定义的模块分为:  模块引用(require)    模块输出(exports)       模块标识(module) CommonJS Modules有1.0.1.1.1.1.1三个版本: Node.js.SproutCore实现了 Mo

js模块化编程之彻底弄懂CommonJS和AMD/CMD!

先回答我:为什么模块很重要? 答:因为有了模块,我们就可以更方便地使用别人的代码,想要什么功能,就加载什么模块.但是,这样做有一个前提,那就是大家必须以同样的方式编写模块,否则你有你的写法,我有我的写法,岂不是乱了套! 于是下面三个模块规范出来了,这篇文章也出来了(拼出来的 {捂脸笑}). JS中的模块规范(CommonJS,AMD,CMD),如果你听过js模块化这个东西,那么你就应该听过或CommonJS或AMD甚至是CMD这些规范咯,我也听过,但之前也真的是听听而已. 现在就看看吧,这些规范

[转]js模块化编程之彻底弄懂CommonJS和AMD/CMD!

原文: https://www.cnblogs.com/chenguangliang/p/5856701.html ------------------------------------------------------------------------------------------------------ 先回答我:为什么模块很重要? 答:因为有了模块,我们就可以更方便地使用别人的代码,想要什么功能,就加载什么模块.但是,这样做有一个前提,那就是大家必须以同样的方式编写模块,否则你

js模块化开发--AMD--CMD

什么是模块化开发? 前端开发中,起初只要在script标签中嵌入几十上百行代码就能实现一些基本的交互效果,后来js得到重视,应用也广泛起来了,jQuery,Ajax,Node.Js,MVC,MVVM等的助力也使得前端开发得到重视,也使得前端项目越来越复杂,然而,JavaScript却没有为组织代码提供任何明显帮助,甚至没有类的概念,更不用说模块(module)了,那么什么是模块呢? 一个模块就是实现特定功能的文件,有了模块,我们就可以更方便地使用别人的代码,想要什么功能,就加载什么模块.模块开发