前言
nodejs模块化规范有两套,分别为CommonJS规范和ESModule规范!
注意:在一个项目中要使用不同的规范可以通过在项目的package.json文件中配置type即可!
{
"name": "npm-demo",
"version": "1.0.0",
"description": "npm test",
"main": "index.js",
"type": "commonjs",// 配置这个就可以了(若没有配置type,则默认使用ESModule规范)
}
CommonJS规范
引入
CommonJS规范有五种模式引入
- 引入自身编写的模块
// test1.js
console.log('test1')
// index.js
require('./test1.js')
// 最后运行node index.js,控制台打印test1
- 引入第三方模块
// 例子:
// 先执行npm i md5
// index.js
const md5 = require('md5')
console.log(md5(123))
// 202cb962ac59075b964b07152d234b70
- 引入nodejs内置模块(fs,http,net…)
const fs = require('fs')
console.log(fs)
- 引入C++扩展
CommonJS规范还支持引入C++扩展模块,需要使用node-gyp编译生成.node文件,然后使用require引入。例如:
const addon = require('./build/Release/addon.node');
console.log(addon.hello());
- 引入JSON文件
// test.json
{
"name": "John",
"age": 30,
"city": "New York"
}
// index.js
const data = require('./test.json')
console.log(data.name) // John
导出
// test.js
module.exports = {
audit: 1,
pass: 2,
fail: 0
}
// index.js
const expres = require('./test.js')
console.log(expres) // { audit: 1, pass: 2, fail: 0 }
ESModule规范
ESModule规范使用import和export进行模块的导入和导出,支持静态编译和Tree Shaking等高级特性,但需要使用Babel等工具转换为CommonJS规范才能在Node.js中使用。
// test.js
export const age = 18
export default{
audit: 1,
pass: 2,
fail: 0
}
// index.js
import expres,{age} from './test.js'
console.log(expres) // { audit: 1, pass: 2, fail: 0 }
console.log(age) // 18
// 如果想要全部导入则可以如下操作
import * as allData from './test.js'
console.log(allData)
// [Module: null prototype] {
// age: 18,
// default: { audit: 1, pass: 2, fail: 0 }
//}
ESModule规范不支持引入JSON文件(nodejs 18版本以下)!
// data.json
{
"name": "zs",
"age": "18"
}
// index.js
import json from './data.json'
console.log(json)
运行结果如下图:
// nodejs高版本可以引入JSON文件(nodejs 18以上),但会警告
import json from './data.json' assert { type: 'json' }
console.log(json)
两大规范区别
- ESModule规范基于编译时异步加载,CommonJS规范基于运行时同步加载(运行方式不一样)
因此,我们可以按照以下写法来写
// 优点:CommonJS规范下可以这样写,即和逻辑代码混在一起写
// 但是这样写的话会有个缺点:由于基于运行时同步加载,当引入这个模块过大,就会阻塞后面的代码
if (true) {
const md5 = require('md5')
}
// 但是ESModule规范就不能这样写了,import导入声明只能在模块的顶层使用
if (true) {
import md5 from 'md5'
}
// ----------------------------------------------------
// 如果import非要写在逻辑里面也可实现,使用import函数模式
// index.js
if (true) {
import('./test.js').then((module) => {
console.log(module)
})
}
// 运行 结果:
// [Module: null prototype] {
// age: 18,
// default: { audit: 1, pass: 2, fail: 0 }
//}
// test.js
export const age = 18
export default{
audit: 1,
pass: 2,
fail: 0
}
- ESModule规范下引入的模块是只读的(不可修改),而CommonJS规范下引入的模块是可读可写的
- ESModule规范支持Tree Shaking优化,而CommonJS规范不支持!
- ESModule规范下的顶层this指向undefined,而CommonJS规范下的顶层this指向模块本身.
总结
模块化对于大型项目的开发尤其重要,可以将功能划分为多个独立的模块,每个模块负责处理特定的业务逻辑。这有助于提高代码的可维护性和可测试性,也有利于团队协作和代码重用。🚗🚓🚕🛺🚙
千淘万漉虽辛苦,吹尽狂沙始到金!