您的位置:

深入浅出:内部模块cjs的加载机制

一、简介

Node.js采用CommonJS规范来组织模块,即在每个文件中定义模块,通过exports对象或module.exports对象对外暴露接口,通过require函数来引用其他模块。

在Node.js内部,处理模块加载的主要逻辑被封装在模块内部模块cjs的loader.js文件中。该文件的作用是确定模块的文件路径和文件名,以及使用该路径来读取文件内容并在代码中执行该模块。因此,深入了解internal/modules/cjs/loader.js文件对于了解Node.js模块加载机制非常重要。

二、分析内部模块cjs的loader.js文件

loader.js文件将Node.js的模块加载机制进行了抽象,可以分为以下几个步骤:

1. 从module对象中获取模块信息

function tryModuleLoad(module, filename) {
  var threw = true;
  try {
    module.load(filename);
    threw = false;
  } finally {
    if (threw) {
      delete Module._cache[filename];
    }
  }
}

该函数的作用是尝试加载模块。

首先从Module._cache对象中获取模块,如果缓存中存在模块,则跳过加载步骤,直接返回该模块。

如果缓存中不存在模块,则根据文件名解析出完整文件路径,并捕获可能的异常。

如果异常被捕获,将删除缓存中的模块信息。

如果没有异常,将调用模块对象的load方法实现模块加载和执行。

2. 获取模块对应的文件路径

function resolveFilename(request, parentModule, isMain) {
  var resolvedModule = Module._resolveFilename(request, parentModule, isMain);

  return resolvedModule;
}

该函数的作用是获取一个请求模块路径的完整路径名。

该方法内部调用了Module._resolveFilename方法,通过路径分析算法找到对应的文件,查找路径顺序为:

  1. 原始文件路径
  2. 系统模块
  3. node_modules文件夹

3. 加载模块

Module.prototype.load = function(filename) {
  var extension = pathModule.extname(filename) || '.js';
  if (!Module._extensions[extension]) extension = '.js';
  Module._extensions[extension](this, filename);
  this.loaded = true;
};

该方法的作用是加载模块。

首先通过node的pathModule模块获取文件扩展名,再根据扩展名查找对应的Module._extensions对象中的方法,如果找到对应的方法,则执行该方法加载模块。

例如,若文件扩展名为.js,则调用Module._extensions['.js']。

4. 编译模块

Module._extensions['.js'] = function(module, filename) {
  var content = fs.readFileSync(filename, 'utf8');
  module._compile(stripBOM(content), filename);
}

该函数的作用是读取文件,并将读取到的内容作为字符串编译成可执行的代码。

代码读取使用了Node.js的文件系统模块(fs模块)中的readFileSync()方法。

读取出来的内容会有BOM标记,所以需要stripBOM()函数将其去除,该函数被定义在Module.js文件中。

最后,执行module._compile()函数将字符串转换成可执行的代码并存储在module.exports对象中。

三、总结

Node.js的内部模块cjs的loader.js文件是Node.js的模块加载机制的核心部分,它负责解析模块的文件路径和读取文件内容,并将内容编译成可执行的代码。对Node.js的模块加载机制进行深入的了解,有助于开发者更好地理解Node.js的模块化开发,进而开发出更好的应用程序。

深入浅出:内部模块cjs的加载机制

2023-05-22
js模块规范cjs,js模块规范esm

本文目录一览: 1、在node环境下怎么使用commonjs模块去使用require方法 2、如何理解前端模块化 3、js代码规范问题 JavaScript判断语句规范 4、使用 MockJs — 实

2023-12-08
深入浅出Node.js

2023-05-19
java学习笔记(java初学笔记)

2022-11-14
深入浅出Node.js

2023-05-18
深入python垃圾回收机制:理解gc模块

2023-05-10
cjs和web开发的简单介绍

本文目录一览: 1、在 Node.js 中使用原生 ES 模块方法解析 2、使用 MockJs — 实现真正的前后端分离 3、「官方」总结2021的IPFS:成为Web3主流势头的支柱 4、在node

2023-12-08
深入mysql源码结构的图书(深入浅出mysql第三版pdf

2022-11-10
python课堂整理32(python笔记全)

2022-11-12
cjs乖乖的美拍的简单介绍

本文目录一览: 1、路由器CJS_5G的wife密码是什么? 2、cjs是谁的名字的缩写? 3、CJS深层保湿发热面膜真的会发热么?什么原理? 路由器CJS_5G的wife密码是什么? 路由器CJS_

2023-12-08
python的深浅copy详解(python深浅复制)

2022-11-14
如何使用cjs,如何使用wland看文

2022-11-24
深入浅出php基础笔记,深入理解php

2022-11-30
印象笔记记录java学习(Java成长笔记)

2022-11-12
重学java笔记,java笔记总结

2022-11-23
python中的深浅复制(python中深浅拷贝)

2022-11-14
python模块初接触的简单介绍

2022-11-11
深入理解java,深入理解java虚拟机第四版

2022-11-27
java笔记,大学java笔记

2022-11-28
深入浅出Pandas

2023-05-18