require的使用场景

require的最终执行结果是在例如.js文件源码外层套一个自执行函数,这个函数的入参就有module, exports, dirname, filename, require等。自执行函数的返回结果为exports或modules.exports的值。

  • 加载模块类型:
    • 加载内置模块: require('fs')
    • 加载node_modules模块: require('ejs')
    • 加载本地模块: require('./utils')
  • 支持文件类型:
    • 加载.js文件
    • 加载.mjs文件
    • 加载.json文件
    • 加载.node文件
    • 加载其他类型文件

require源码阅读过程中的一些思考

  • CommonJs 加载主模块的流程 加载流程和require基本一致, 主要区别就是 isMain 为 true, parent 为 null

  • require 如何加载内置模块? 通过 loadNativeModule(filename, request, experimentalModules) 方法在内置模块的map集合中查找。找到就直接返回 mod.exports

  • require 如何加载node_modules模块 require('ejs') 和 require('./ejs/index.js) 加载的方法基本类似,只不过 require('ejs') 会先通过Module._resolveFileName解析node_modules中文件的真是路径

  • require 为什么会将非js/json/node 文件视为js文件加载? 非 js/json/node 文件会被添加.js文件后缀,最后通过Module._extensions[.js]执行加载流程

  • require 连续加载同一个模块时,是如何进行缓存的? 第一次加载的时候通过 Module._cache[filename] = module 将文件缓存下来,第二次加载的时候如果在缓存中找到这个模块,就直接返回 module.exports

Module对象

  • id:源码文件路径,如:/Users/sam/Desktop/vue-test/imooc-test/bin/ejs/index.js
  • path:源码文件对应的文件夹,通过 path.dirname(id) 生成
  • exports:模块输出的内容,默认为 {}
  • parent:父模块信息
  • filename:源码文件路径
  • loaded:是否已经加载完毕
  • children:子模块对象集合
  • paths:模块查询范围

Module核心API

  • Module._resolveFileName : 返回文件的真实路径
  • Module._nodeModulePaths :返回请求文件可能存在的所有路径
  • Module._resolveLookUpPath : 将上一步返回的路径再拼装环境变量中的路径
  • Module._findPath : 返回文件真实路径
  • Module.prototype._compile :将.js文件外层包装一个自执行函数,并注入require、modules、exports、dirname、 filename等参数,返回执行结果。
  • Module.prototype.load : 解析文件后缀名,执行对应方法
Copyright © imooc-lego (2020 - present) all right reserved,powered by GitbookFile Modify: 2021-06-27 08:04:57

results matching ""

    No results matching ""