当前位置: 首页 > article >正文

node模块查找策略

在路径 Y 中引入 X 模块:

  1. 如果 X 是核心模块

    a. 返回核心模块

    b. 停止

  2. 如果 X 以 / 开头

    a. 将 Y 设置为文件系统根目录

  3. 如果 X 以 .//../ 开头

    a. LOAD_AS_FILE(Y + X)

    b. LOAD_AS_DIRECTORY(Y + X)

    c. THROW “not found”

  4. 如果 X 以 # 开头

    a. LOAD_PACKAGE_IMPORTS(X, dirname(Y))

  5. LOAD_PACKAGE_SELF(X, dirname(Y))

  6. LOAD_NODE_MODULES(X, dirname(Y))

  7. 抛出 “not found” 错误

LOAD_AS_FILE(X)

  1. 如果 X 是一个文件,则按照其文件扩展名格式加载 X。 停止

  2. 如果 X.js 是一个文件
    a. 找到距离 X 最近的包作用域 SCOPE。
    b. 如果没有找到 scope

    1. MAYBE_DETECT_AND_LOAD(X.js)

    c. 如果 SCOPE/package.json 包含 type 字段

     1. 如果 `type` 字段为 `module` ,则将 X.js 作为 ECMAScript 模块加载。停止。
     2. 如果 `type` 字段为 `commonjs` ,则将 X.js 作为 commonjs 模块加载。停止。
    

    d. MAYBE_DETECT_AND_LOAD(X.js)

  3. 如果 X.json 是一个文件,则将 X.json 加载为一个 JavaScript 对象。停止。

  4. 如果 X.node 是一个文件,则将 X.node 作为二进制插件加载。停止。

LOAD_INDEX(X)

  1. 如果 X/index.js 是一个文件
    a. 找到距离 X 最近的包作用域 SCOPE。
    b. 如果没有找到 scope, 则将 X/index.js 作为 commonjs 模块加载。停止。
    c. 如果 SCOPE/package.json 包含 type 字段
    1. 如果 type 字段为 module ,则将 X/index.js 作为 ECMAScript 模块加载。停止。
    2. 如果 type 字段为 commonjs ,则将 X/index.js 作为 commonjs 模块加载。停止。
  2. 如果 X/index.json 是一个文件,则将 X/index.json 加载为一个 JavaScript 对象。停止。
  3. 如果 X/index.node 是一个文件,则将 X/index.node 作为二进制插件加载。停止。

LOAD_AS_DIRECTORY(X)

  1. 如果 X/package.json 是一个文件
    a. 解析 X/package.json ,查找 main 字段。
    b. 如果 main 是一个假值,则跳到第 2 步
    c. let M = X + (json main field)
    d. LOAD_AS_FILE(M)
    e. LOAD_INDEX(M)
    f. LOAD_INDEX(X) DEPRECATED
    g. THROW “not found”
  2. LOAD_INDEX(X)

LOAD_PACKAGE_IMPORTS(X, DIR)

  1. 找到与 DIR 最近的包作用域 SCOPE。
  2. 如果没有找到 scope,返回。
  3. 如果 SCOPE/package.json 中的 importsnullundefined,则返回。
  4. let MATCH = PACKAGE_IMPORTS_RESOLVE(X, pathToFileURL(SCOPE), [“node”, “require”])
  5. RESOLVE_ESM_MATCH(MATCH).

LOAD_PACKAGE_SELF(X, DIR)

  1. 找到与 DIR 最近的包作用域 SCOPE。
  2. 如果没有找到 scope,返回。
  3. 如果 SCOPE/package.json 中的 exportsnullundefined,则返回。
  4. 如果 SCOPE/package.json 中的 name 不是 X 的第一个部分,则返回。
  5. let MATCH = PACKAGE_EXPORTS_RESOLVE(pathToFileURL(SCOPE), “.” + X.slice(“name”.length), `package.json` “exports”, [“node”, “require”])
  6. RESOLVE_ESM_MATCH(MATCH)

LOAD_NODE_MODULES(X, START)

  1. let DIRS = NODE_MODULES_PATHS(START)
  2. for each DIR in DIRS:
    a. LOAD_PACKAGE_EXPORTS(X, DIR)
    b. LOAD_AS_FILE(DIR/X)
    c. LOAD_AS_DIRECTORY(DIR/X)

RESOLVE_ESM_MATCH(MATCH)

  1. let RESOLVED_PATH = fileURLToPath(MATCH)
  2. 如果 RESOLVED_PATH 中的文件存在,则按其扩展名格式加载 RESOLVED_PATH。停止。
  3. THROW “not found”

MAYBE_DETECT_AND_LOAD(X)

  1. 如果 X 解析为 CommonJS 模块,则将 X 加载为 CommonJS 模块。停止。

  2. 否则,如果启用了--experimental-require-module选项,并且 X 的源代码可以被解析为 ECMAScript 模块

    a. 加载 X 为 ECMAScript 模块。停止。

  3. 在 1 步中抛出尝试将 X 解析为 CommonJS 时的 SyntaxError,停止。

NODE_MODULES_PATHS(START)

  1. let PARTS = path split(START)
  2. let I = count of PARTS - 1
  3. let DIRS = []
  4. while I >= 0,
    a. if PARTS[I] = “node_modules” CONTINUE
    b. DIR = path join(PARTS[0 … I] + “node_modules”)
    c. DIRS = DIR + DIRS
    d. let I = I - 1
  5. return DIRS + GLOBAL_FOLDERS

模块查找策略粗略图解

graph TB
A(模块查找策略) --> B{是否以 ./ 或 ../ 开头}
B --是--> C{是否带文件扩展名}
C --是--> D{根据路径查找文件}
C --否--> E{加上 .js 或 .json 
后缀查找文件}
D --找到--> I(成功)
D --找不到--> J(失败)
E --找到--> F(成功)
E --找不到--> G{
	当成文件夹
	查找文件夹内的
	package.json 文件
}
G --找到--> H{是否有 main 字段}
H --是--> M{根据 main 字段查找文件}
H --否--> L
M --找到--> N(成功)
M -- 找不到--> O(失败)
G --找不到--> L{
    文件夹内是否有
    inexd.js 文件
}
L --找到--> P(成功)
L --找不到--> Q(失败)

B --否--> R{是否为核心模块}
R --是--> S(成功)
R --否--> T(进入 node_module 文件夹查找)
T --> E
Created with Raphaël 2.3.0 模块查找策略开始 是否以 ./ 或 ../ 开头 是否带文件扩展名 根据路径查找文件 成功 失败 加上 .js 或 .json 后缀查找文件 成功 当成文件夹 查找文件夹内的 package.json 文件 是否有 main 字段 根据 main 字段查找文件 成功 失败 文件夹内是否有 index.js 文件 成功 失败 是否为核心模块 成功 进入 node_module 文件夹查找 yes no yes no yes no yes no yes no yes no yes no yes no yes no

http://www.kler.cn/a/530727.html

相关文章:

  • pytorch实现基于Word2Vec的词嵌入
  • 线性数据结构:单向链表
  • [权限提升] Windows 提权 维持 — 系统错误配置提权 - Trusted Service Paths 提权
  • 基于Java的林业盗砍盗伐监测算法研究与实现——读取Shp文件并比较
  • 使用朴素贝叶斯对散点数据进行分类
  • 标准IO与文件IO 进程与线程
  • MQTT 术语表
  • Windows和苹果MacOS上的vscode翻页及上下滚动行快捷键
  • 给AI加知识库
  • WPF进阶 | WPF 动画特效揭秘:实现炫酷的界面交互效果
  • Vulkan 学习(13)---- Vulkan Framebuffercommand buffer
  • 修复使用unplugin-auto-import和unplugin-vue-components后tsc-vue报错的问题
  • 寒假day10
  • 一文讲解Spring中应用的设计模式
  • Swoole如何进行错误处理
  • Linux下安装Redis详细教程
  • 6. 【Vue实战--孢子记账--Web 版开发】-- 主币种设置
  • 强化学习、深度学习、深度强化学习的区别是什么?
  • PySPARK带多组参数和标签的SparkSQL批量数据导出到S3的程序
  • Unity Shader Graph 2D - 跳动的火焰
  • 大语言模型深度研究功能:人类认知与创新的新范式
  • Pyside6异步通信测试
  • Java设计模式:行为型模式→状态模式
  • 【R语言】R语言安装包的相关操作
  • Linux第105步_基于SiI9022A芯片的RGB转HDMI实验
  • 体系自适应的物联网漏洞挖掘系统研究背景及意义:物联网漏洞挖掘概述之物联网漏洞现状及问题