Node.js的模块规范-ES Module
讲到node,就离不开node的模块化,下面先讲一下什么是模块,在讲一下为什么要分模块。
一、什么是模块
这个很容易理解,所谓模块,就是将功能强相关的函数写在一起进行封装,尽量与其他功能独立,高内聚低耦合是我们在设计模块时的中心思想。
二、为什么要分模块
前面说了,高内聚低耦合是我们在前期划分模块的标准,这样做的优点有:1.出现问题时便于排查,不会出现函数互相嵌套引用的情况;2.有利于我们模块的复用,当我们在其他项目中也用到之前开发的功能模块时,直接把这部分copy过来就行。
早期的浏览器环境没有支持模块化,证据就是当加载多个js文件时,使用var声明的顶层变量和函数可以互相访问。Node.js诞生之初,浏览器还没有标准的模块规范,所以这个时候nodejs支持的模块规范是commonjs,后来js有了自己的标准化模块规范ES Modules,所以nodejs自v13.2.0版本之后也开始支持ES Modules,同时兼容早期的commonjs规范。(因为不同的规范对应着不同的语法标准,这就关乎我们写的代码能不能编译成功的问题)。
三、通过例子介绍一下ES-Modules模块规范
首先,我们在项目目录下创建一个test.mjs文件(注意:这个文件的后缀名是.mjs),这个文件的内容如下:
const printsth = (content) => `print ${content}`;
export {printsth}
ES规范中的模块导出语法为:export {}。在另外一个模块中引用这个导出的模块也很简单,定义一个index.mjs,内容如下:
import {printsth} from './test.mjs'
const argv = process.argv;
console.log(printsth(argv[2] || "未输入要打印的字符串"));
执行的时候很简单,就是node index.mjs或者node index.mjs sth,如下:
实际上,以上就是ES规范中模块的导入、导出用法,具体一点就是:
# 导出
export {模块的公共api}, 如export {api1, api2, ...}
# 导入
import {API的名字} from 模块名, 如import {api1, api2, ...} from 模块名
如果我们在导出时,不想暴露原API接口的名字,可以用这种:
export {api1 as api_new}
#导入时
import {api_new} from 模块名
此外,还可以导出一个默认模块:(一个模块中,只能有一个export default)
export default api1;
# 导入
import api1 from 模块名
最后注意一点:我们命名js模块,用的是.mjs后缀名,而不是.js后缀名,这是因为,NodeJs默认用CommonJs规范来解析.js文件,用ES Modules来解析.mjs文件,如果我们将index.mjs强行改成index.js,那么在用node index.js来执行文件时,就会因为代码内容不符合相应的语法规范而报错:
解决方法为:可以在项目目录下,通过 npm init -y 或者手动创建一个package.json文件,并在其中设置type:module,
#package.json
{
"type": "module" //告诉编译器,用的是ES Module规范
}
这样就可以用node来执行用ES Module规范来写的.js文件了。