CommonJS模块化规范
- 加载时机: - 服务器端: 模块的加载是运行时同步加载的,node.js实现了模块化规范
- 浏览器端: 模块需要提前编译打包处理,需使用Browserify编译打包,推荐使用ESM
 
- 暴露模块:module.exports、exports
- 导入模块:require
模块导出
- module.exports = 任意数据 (字符串、整数、布尔值、对象)
- exports.模块名 = 任意数据 (字符串、整数、布尔值、对象),相当于exports={模块名: 任意数据}
- module.exports 与 exports 的关系: - 在模块内部存在一种隐式关系:exports = module.exports = {}
- 模块最终取的是module.exports的值
- exports只能是引用类型数据,不能使用exports = 基本类型的数据。如果 exports = ‘abc’,不会改变模块返回的结果,因为module.exports为{},所以模块返回的是{}
 
- 在模块内部存在一种隐式关系:
模块导入
-  使用require方法导入文件: - 自定义的模块:路径建议写相对路径 const m = require('./m.js');,并且不能省略./或../
- 内置的模块:直接require('模块名'),无需加./或../
 
- 自定义的模块:路径建议
-  文件类型处理 - js、- json类型的文件不用写后缀
- 其他类型的文件不写后缀就会按js类型处理
 
-  require导入自定义模块的基本流程: - 将相对路径转为绝对路径,定位目标文件
- 缓存检测
- 读取目标文件代码
- 包裹为一个函数并执行(自执行函数),通过arguments.callee.toString()查看自执行函数
- 缓存模块的值
- 返回module.exports的值
 const path = require('path'); const fs = require('fs'); let caches = []; function require(file) {// 将相对路径转为绝对路径,定位目标文件let absolutePath = path.resolve(__dirname, file);// 缓存检测if(caches[absolutePath]) {return caches[absolutePath];}// 读取目标文件代码let code = fs.readFileSync(absolutePath).toString();// 包裹为一个函数并执行(自执行函数)let module = {};let exports = module.exports = {};(function(exports, require, module, __filename, __dirname){// eval(code)})(exports, require, module, __filename, __dirname)// 缓存模块的值caches[absolutePath] = module.exports;// 返回module.exports的值return module.exports; } // 测试 const m = require('./m.js');// m.js文件 const mt = {name: '模块1' }; module.exports = mt;
-  导入路径是文件夹的处理流程: - 先检查该文件夹下package.json文件的main属性对应的文件,如果main属性或package.json文件不存在,则会检查文件夹下的index.js或index.json文件,如果还是找不到就会报错
 
- 先检查该文件夹下