Node.js之模块化开发
模块化的最终目的是将程序划分成一个一个的小的结构
在结构中编写属于自己的逻辑代码,有自己的独立作用域,不会影响到其他的结构
同时在这个结构中可以暴露出自己的变量、函数、对象等导出给其他结构使用
也可以通过某种方式,导入其他结构的变量,函数,对象等。
此时,这里的结构就是模块。
模块化之CommonJS规范
①Node是CommonJS在服务器端的一个具有代表性的实现
②同时webpack打包工具对CommonJS的支持和转换
在Node中,每个js文件都是一个单独的模块,模块中包括ComminJS规范的核心变量:export、module.exports、require,我们可以使用这些变量来方便的进行模块化开发
export和module.exports负责对模块中的内容进行导出;
require函数可以帮助我们导入其他模块中的内容。
对于require函数,导入格式如下require(X) 有以下三种情况
- 情况一:X是一个核心模块,比如path、http
- 直接返回核心模块,并且停止查找
- 情况二:X是以
./
或../
或/
(根目录)开头的- 第一步:将X当做一个文件在对应的目录下查找;
- 1.如果有后缀名,按照后缀名的格式查找对应的文件
- 2.如果没有后缀名,会按照如下顺序:
- 1> 直接查找文件X
- 2> 查找X.js文件
- 3> 查找X.json文件
- 4> 查找X.node文件
- 第二步:没有找到对应的文件,将X作为一个目录
- 查找目录下面的index文件
- 1> 查找X/index.js文件
- 2> 查找X/index.json文件
- 3> 查找X/index.node文件
- 查找目录下面的index文件
- 如果没有找到,那么报错:
not found
- 第一步:将X当做一个文件在对应的目录下查找;
- 情况三:直接是一个X(没有路径),并且X不是一个核心模块
模块的加载顺序
结论一:模块在被第一次引入的时候,模块中的js代码会被运行一次
结论二:模块被多次引入时,会缓存,最终只加载运行一次
只会加载运行一次:每个模块对象Module都有一个属性:loader。为false时表示还没有加载,为true表示已经加载。
CommonJS规范的缺点
CommonJS的加载模块是同步的,意味着只有等到对应的模块加载完毕,当前模块的内容才能被运行,在浏览器加载js文件,需要先从服务器将文件下载下来,之后再加载运行,同步则意味着后续的js代码无法正常运行。
ES Module的认识
ES Module模块采用export和import关键字来实现模块化
export负责将模块从其他内容导出 import负责从其他模块内容导入
需要注意的是采用ES Module模块将自动采用严格模式: use strict
对于export关键字,我们使用的时候有以下三种方式
①在语句声明的前面直接加上export关键字
②将所有需要导出的标识符,放到export后面的{}中
③导出时给标识符起一个别名
对于import关键字,我们使用的时候有以下三种方式
①import {标识符列表} from '模块'
②导入时给标识符起别名
③将模块功能放倒一个模块功能对象(a module object)上
还有一种导出叫做默认导出(default export)
- 默认导出export时可以不需要指定名字;
- 在导入时不需要使用
{}
,并且可以自己来指定名字; - 它也方便我们和现有的CommonJS等规范相互操作;
ES Module与CommonJS区别
CommonJS模块加载 文件的过程是运行时加载的,并且是同步的
运行时加载意味着js引擎在执行js代码的过程中加载模块;同步的就意味着一个文件没有加载结束之前,后面的代码都不会执行
CommonJS通过module.export导出的是一个对象:
意味着可以将这个对象的引用在其他模块中赋值给其他变量,但是最终都是指向同一个对象那么一个变量修改了对象的属性,所有的地方都会被修改。
ES Module加载js文件的过程是编译(解析)时加载的,并且是异步的:
编译时(解析)加载,意味着import不能和运行时相关的内容放在一起使用:
①:from后面的路径需要动态获取
②:不能将import放在if等语句的代码块中
③:称ES Module是静态解析的,而不是动态或者运行时解析的
异步意味着JS引擎在遇到import关键字时回去获取这个js文件,但是这个获取的过程是异步的,并不会阻塞主线程继续执行;