iis服务器助手广告广告
返回顶部
首页 > 资讯 > 前端开发 > JavaScript >Node.js中的模块路径是怎样的
  • 649
分享到

Node.js中的模块路径是怎样的

2024-04-02 19:04:59 649人浏览 泡泡鱼
摘要

这篇文章主要介绍“node.js中的模块路径是怎样的”,在日常操作中,相信很多人在node.js中的模块路径是怎样的问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Node.j

这篇文章主要介绍“node.js中的模块路径是怎样的”,在日常操作中,相信很多人在node.js中的模块路径是怎样的问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Node.js中的模块路径是怎样的”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

Node.js中的模块路径是怎样的

require案例

  • 当前有一个项目

  • 当前项目路径/Users/rainbow/Documents/前端/脚手架开发/rainbow-test

  • 项目bin目录下有一堆文件

Node.js中的模块路径是怎样的

  • /bin/index.js

console.log(require.resolve("."));
// /Users/rainbow/Documents/前端/脚手架开发/rainbow-test/bin/index.js  输出bin/index.js的绝对路径
console.log(require.resolve.paths("."));
// [ '/Users/rainbow/Documents/前端/脚手架开发/rainbow-test/bin' ] 输出的文件可能在的路径的数组
console.log(require.resolve("yargs"));
// /Users/rainbow/Documents/前端/脚手架开发/rainbow-test/node_modules/yargs/index.cjs
console.log(require.resolve.paths("yargs"));

require解析并找到模块执行文件的流程

1、nodejs项目模块路径解析是通过require.resolve方式实现的。

  • require.resolve就是通过Module._resolveFileName方法实现的

  • Module._resolveFileName核心流程是:

    • 判断该路径是否是内置模块

    • 不是,则通过Module._resolveLookupPahts方法,生成node_modules可能存在的路径,如果传入的路径是’/test/lerna/cli.js’,在每一级路径下加上node_moduels的路径数组

    • 通过Module._findPath查询模块的真实路径,

2、Module._findPath核心流程是:

  • 查询缓存(将request和paths通过\x00合并生成cacheKey)

  • 遍历 Module._resolveLookupPahts方法生成的paths数组,将pathrequest组成文件路径basePath

  • 如果basePath存在则调用fs.realPahtSync获取文件的真实路径

  • 将文件真实路径缓存到Module._pathCache(key为cacheKey)(Module._pathCache就是一个map)

3、fs.realPahtSync核心流程:

  • 查询缓存(缓存的key为p。即Module._findPath中生成的路径)

  • 从左往右遍历路径字符串,查询到/时,拆分路径,判断该路径是否为软链接,如果是软链接则查询真实链接,并生成新路径p,然后继续让后遍历,这里有一个细节:

  • 遍历过程中生成的子路径base会缓存在knownHard和cache中,避免重复查询

  • 遍历完成得到模块对应的真实路径,此时会将原始路径original作为key,真实路径作为value,保存到缓存中

4、require.resolve.paths等价于Module._resolveLookupPaths,该方法获取所有node_modules可能存在的路径组成一个数组。

5、require.resolve.paths实现原理是:

  • 如果是/(根路径)直接返回['/node_modules']

  • 否则,将路径字符串从后往前遍历,查询到/时,拆分路径,在后面加上node_modules,并传入一个paths数组,直到查询不到/后返回paths数组

require使用到内置模块的方法

当我们使用require('yargs')

require方法

  • 实际使用的是Module._load方法

Module.prototype.require = function(id) { //id = 'yargs'
  validateString(id, 'id');
  if (id === '') {
    throw new ERR_INVALID_ARG_VALUE('id', id, 'must be a non-empty string');
  }
  requireDepth++;
  try {
    return Module._load(id, this,  false);
  } finally {
    requireDepth--;
  }
};
// 参数
id = 'yargs'
this={
 paths: Module._nodeModulePaths(process.cwd())
}

Module._nodeModulePaths方法

Node.js中的模块路径是怎样的

// 进入Mac电脑所在的逻辑:
// from => /Users/rainbow/Documents/前端/脚手架开发/lerna源码/lernas  //'from' is the __dirname of the module.
  Module._nodeModulePaths = function(from) {
    from = path.resolve(from);
    // Return early not only to avoid unnecessary work, but to *avoid* returning
    // an array of two items for a root: [ '//node_modules', '/node_modules' ]
    if (from === '/')
      return ['/node_modules'];

    const paths = [];
    
   // 关键算法代码
    for (let i = from.length - 1, p = 0, last = from.length; i >= 0; --i) {
      const code = from.charCodeAt(i);
      if (code === CHAR_FORWARD_SLASH) {
        if (p !== nmLen)
          paths.push(from.slice(0, last) + '/node_modules');
        last = i;
        p = 0;
      } else if (p !== -1) {
        if (nmChars[p] === code) {
          ++p;
        } else {
          p = -1;
        }
      }
    }

    // Append /node_modules to handle root paths.
    paths.push('/node_modules');

    return paths;
  };

for循环的核心算法解析:

Node.js中的模块路径是怎样的

Module._load方法

Module._load(id, this, false)

核心实现代码是:const filename = Module._resolveFilename(request, parent, isMain);

require.resolve

Node.js项目模块路径解析是通过require.resolve方式实现的。

  • require.resolve就是通过Module._resolveFileName方法实现的,

// node.js内置模块require的源代码
function resolve(request, options) {
  validateString(request, 'request');
  return Module._resolveFilename(request, mod, false, options); //核心实现
}

require.resolve = resolve;

function paths(request) {
  validateString(request, 'request');
  return Module._resolveLookupPaths(request, mod); //核心代码
}

resolve.paths = paths;

Module._resolveFileName核心流程

  • 判断该路径是否是内置模块

  • 不是,则通过Module._resolveLookupPahts方法,将paths和环境中的路径结合起来

  • 通过Module._findPath查询模块的真实路径

return Module._resolveFilename(request, parent, isMain);

Node.js中的模块路径是怎样的

Module._resolveFilename = function(request, parent, isMain, options) {
  if (NativeModule.canBeRequiredByUsers(request)) { //是否为内置模块
    return request;
  }

  let paths;
  // 让paths和环境变量中的paths结合
  paths = Module._resolveLookupPaths(request, parent); //核心代码
  
  if (parent && parent.filename) {
    // 读取filename对应的package.JSON文件,看是否有exports字段,当前filename = false
    const filename = trySelf(parent.filename, request);
    if (filename) { //false
      const cacheKey = request + '\x00' +
          (paths.length === 1 ? paths[0] : paths.join('\x00'));
      Module._pathCache[cacheKey] = filename;
      return filename;
    }
  }

 //关键代码,找到本地执行文件 // Look up the filename first, since that's the cache key. 
  const filename = Module._findPath(request, paths, isMain, false);
  if (filename) return filename;
  // ...
};

Module._resolveLookupPahts方法

  • 生成要查找模块的所有路径上可能存在node_modules的路径数组

  • require.resolve.paths("yargs")核心实现方法

生成

[
  '/Users/rainbow/Documents/前端/脚手架开发/rainbow-test/bin/node_modules',
  '/Users/rainbow/Documents/前端/脚手架开发/rainbow-test/node_modules',
  '/Users/rainbow/Documents/前端/脚手架开发/node_modules',
  '/Users/rainbow/Documents/前端/node_modules',
  '/Users/rainbow/Documents/node_modules',
  '/Users/rainbow/node_modules',
  '/Users/node_modules',
  '/node_modules',
  '/Users/rainbow/.node_modules',
  '/Users/rainbow/.node_libraries',
  '/usr/local/Cellar/node/14.3.0_1/lib/node'
]

Node.js中的模块路径是怎样的

Module._resolveLookupPaths = function(request, parent) {
  if (NativeModule.canBeRequiredByUsers(request)) {
    debug('looking for %j in []', request);
    return null;
  }

  // Check for node modules paths.
  if (request.charAt(0) !== '.' ||
      (request.length > 1 &&
      request.charAt(1) !== '.' &&
      request.charAt(1) !== '/' &&
      (!iswindows || request.charAt(1) !== '\'))){
     let paths = modulePaths;
     if (parent != null && parent.paths && parent.paths.length) {
      paths = parent.paths.concat(paths);
    }

    debug('looking for %j in %j', request, paths);
    return paths.length > 0 ? paths : null;
  }
  
  // In REPL, parent.filename is null.
  if (!parent || !parent.id || !parent.filename) {
    // Make require('./path/to/foo') work - nORMally the path is taken
    // from realpath(__filename) but in REPL there is no filename
    const mainPaths = ['.'];

    debug('looking for %j in %j', request, mainPaths);
    return mainPaths;
  }

  debug('RELATIVE: requested: %s from parent.id %s', request, parent.id);

  const parentDir = [path.dirname(parent.filename)];
  debug('looking for %j', parentDir);
  return parentDir;
};

Module._findPath核心流程

  • 查询缓存(将request和paths通过\x00合并生成cacheKey)(\x00是空格的16进制)

  • 遍历Module._resolveLookupPahts方法生成的paths数组,将pathrequest组成文件路径basePath

  • 如果basePath存在则调用fs.realPahtSync获取文件的真实路径

Node.js中的模块路径是怎样的

fs.realPahtSync

Node.js中的模块路径是怎样的

到此,关于“Node.js中的模块路径是怎样的”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注编程网网站,小编会继续努力为大家带来更多实用的文章!

--结束END--

本文标题: Node.js中的模块路径是怎样的

本文链接: https://www.lsjlt.com/news/87783.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Node.js中的模块路径是怎样的
    这篇文章主要介绍“Node.js中的模块路径是怎样的”,在日常操作中,相信很多人在Node.js中的模块路径是怎样的问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Node.j...
    99+
    2024-04-02
  • 解读node.js中的path路径模块
    目录1. 什么是 path 路径模块2. 路径拼接3. 获取路径中的文件名 4. 获取路径中的文件扩展名5. 综合案例 -...
    99+
    2023-01-28
    node.js path path路径模块 path模块
  • Node.js 中常用内置模块(path 路径模块)
    目录前言路径拼接:join方法获取文件名:basename方法获取文件扩展名:extname方法结语前言 进行服务端开发,少不了对各种路径的处理,之前我们是简单粗暴的使用字符串的方法...
    99+
    2024-04-02
  • Node中的fs文件模块和path路径模块怎么使用
    这篇“Node中的fs文件模块和path路径模块怎么使用”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Node中的fs文件模...
    99+
    2023-07-04
  • node的path路径模块怎么使用
    这篇文章主要介绍了node的path路径模块怎么使用的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇node的path路径模块怎么使用文章都会有所收获,下面我们一起来看看吧。node的path模块前言:通过这篇文...
    99+
    2023-07-05
  • 浅析node的path路径模块
    1.path路径模块初认识path 模块是 Node.js 官方提供的、用来处理路径的模块。它提供了一系列的方法和属性,用来满足用户对路径的处理需求。2.path模块的API2.1 path.join()path.join() 方法,用来将...
    99+
    2023-05-14
    node path模块
  • node中path路径模块的API有哪些
    本文小编为大家详细介绍“node中path路径模块的API有哪些”,内容详细,步骤清晰,细节处理妥当,希望这篇“node中path路径模块的API有哪些”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,...
    99+
    2024-04-02
  • Node.js中的HTTP模块与URL模块
    几乎每门编程语言都会包括网络这块,Node.js也不例外。今天主要是熟悉下Node.js中HTTP服务。其实HTTP模块是相当低层次的,它不提供路由、cookie、缓存等,像Web开...
    99+
    2024-04-02
  • Node.js中断路器机制是怎么样的
    这篇文章将为大家详细讲解有关Node.js中断路器机制是怎么样的,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。架构演变带来的问题当我们使用传统的 CS 架构时,服务端由于...
    99+
    2024-04-02
  • 具有多个路径的 Go 模块
    php小编子墨介绍:最近,Go语言中的模块管理工具又迎来了新的功能——多路径模块。这一功能的引入,使得开发者在使用Go模块时可以更加灵活地指定模块的路径。以往,开发者只能将模块安装在固...
    99+
    2024-02-10
    go语言
  • Node.js中的内置模块是什么
    本篇内容主要讲解“Node.js中的内置模块是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Node.js中的内置模块是什么”吧!Node.js 架构图内置...
    99+
    2024-04-02
  • python模块中搜索路径的示例分析
    小编给大家分享一下python模块中搜索路径的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!python有哪些常用库python常用的库:1.reques...
    99+
    2023-06-14
  • Node.js中的path模块怎么用
    这篇文章主要介绍“Node.js中的path模块怎么用”,在日常操作中,相信很多人在Node.js中的path模块怎么用问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Node...
    99+
    2024-04-02
  • Node.js中的模块化概念是什么
    这篇文章主要介绍“Node.js中的模块化概念是什么”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Node.js中的模块化概念是什么”文章能帮助大家解决问题。一、模...
    99+
    2024-04-02
  • Node.js中的模块化方法是什么
    今天给大家介绍一下Node.js中的模块化方法是什么。文章的内容小编觉得不错,现在给大家分享一下,觉得有需要的朋友可以了解一下,希望对大家有所帮助,下面跟着小编的思路一起来阅读吧。一、模块化的基本概念1、什么是模块化模块化是指解决一个复杂问...
    99+
    2023-06-26
  • python文件路径的组成是怎样的
    本文小编为大家详细介绍“python文件路径的组成是怎样的”,内容详细,步骤清晰,细节处理妥当,希望这篇“python文件路径的组成是怎样的”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。组成**文件夹路径:**文...
    99+
    2023-06-30
  • Node.js中path模块,url模块,http模块怎么用
    小编给大家分享一下Node.js中path模块,url模块,http模块怎么用,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!path模块Node.js中,提供了一...
    99+
    2023-06-29
  • Node.js中的EventEmitter模块怎么使用
    本篇内容主要讲解“Node.js中的EventEmitter模块怎么使用”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Node.js中的EventEmitter...
    99+
    2024-04-02
  • Node.js中的http模块怎么使用
    本篇内容介绍了“Node.js中的http模块怎么使用”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!1、什...
    99+
    2024-04-02
  • 怎么理解Node.js中的Buffer模块
    这篇文章主要讲解了“怎么理解Node.js中的Buffer模块”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么理解Node.js中的Buffer模块”吧!...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作