网站首页 > 技术文章 正文
大家好,我是前端西瓜哥,今天我们来看看 Node.js 模块查找的原理。
模块种类
模块有三种来源。
- 核心模块:Node.js 内置的包。比如 http、fs、path;
- 自定义模块:NPM 包。比如 axios、express,位于 node_modules 目录下的同名目录,并通过 package.json 的 main 字段指定入口文件;
- 文件模块:项目自己的模块文件,使用路径的写法。包括相对路径(比如 "./utils")和绝对路径(比如 "/Users/xigua/project/utils")。
需要注意的是,"a/b" 这种不属于路径写法,它属于前两种,比如 "fs/promises"、"@babel/core"。
这里给一个例子:
const http = require('http'); // Node.js 内置包
const { defaultContent } = require('./default'); // 开发者自己写的模块文件
http.createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end(defaultContent);
}).listen(3200);
模块查找
我们使用 require() 方法,传入一个字符串标识符,模块查找的旅途就开始了。
核心模块
首先分析标识符的风格,如果是不是路径的写法,我们会先找 Node.js 内置的包有没有匹配的,如果匹配,就导入对应模块,比如 require('http') 就能拿到一个 http 对象,可用于创建 web 服务等功能。
NPM 包
如果不匹配,会在当前文件的目录下,找 node_modules 目录,看里面有没有对应的包。如果找不到,就继续往父目录找,直到根目录。如果找不到,会报 Cannot find module '包名' 的错误。
文件模块
包通常是一个文件夹,里面会有 package.json 文件,Node.js 会提取其中 main 字段对应的文件作为模块文件。如果没有,就依次查找该目录下的 index.js、index.json、index.node 文件。
需要查找的目录可以通过 module.paths 变量得到。
如果你熟悉 JavaScript 的原型链,你会发现它们非常相似,可以做类比以加深理解。
如果标识符是路径,会通过计算得到一个绝对路径,然后找到的是个目录,同上面找 npm 包的逻辑。
要是找不到,就加上后缀再找。后缀按顺序添加为:.js 、.json、.node,找到就立即返回。若一个文件没有后缀但被匹配到了,它会被当作 js 文件。
上面没说缓存的情况,其实我们会对模块做缓存,下面详细说明一下。
模块缓存
每当加载一个模块后,这个模块就会被缓存起来。
你可以在随意一个文件中输入得到缓存的内容,是一个哈希表,key 为模块的绝对路径,确保缓存命中,value 则是模块对象。
const { Module } = require("module");
console.log(Module._cache);
也能用 require.cache 变量拿到,它和 Module._cache 指向同一个对象。
Node.js 内置的模块也需要缓存,但它不会记录到 Module._cache 中,而是保存在 Module.
下面是一个例子,index.js 导入了 a.js,a.js 下引入了 lodash.get 包,模块缓存结果为:
因为缓存的存在,所以 一个模块文件只会被执行一次,然后将 module.exports 缓存下来。
之后被多次导入,不会再执行这个模块文件,而是直接取出对应的 module.exports。
总结
画了个流程图,丢掉了一些细节(路径定位到目录后的逻辑)。
我是前端西瓜哥,欢迎关注我,学习更多前端知识。
猜你喜欢
- 2025-02-04 联科云创申请优化Web页面字体文件大小专利,降低前端加载性能消耗
- 2025-02-04 独立开发者产品日刊:AI视频编辑器、代码搜索工具、Figma 插件
- 2025-02-04 IM客服系统(2)活用用户体验要素进行前端设计
- 2025-02-04 TaskBuilder客户端请求前端静态文件的流程
- 2025-02-04 盘点13个优秀前端测试开源框架大全
- 2025-02-04 梳理React常考面试题很全面(react面试题2024)
- 2025-02-04 2023年前端开发者需要掌握的技术和框架有哪些?
- 2025-02-04 2020年Javascript 前端框架google搜索排名
- 2025-02-04 树形结构!别再用递归实现了这才是最佳的方案;更快更强更好用
- 2025-02-04 Web前端基础:二叉查找树、搜索树的应用
你 发表评论:
欢迎- 572℃几个Oracle空值处理函数 oracle处理null值的函数
- 569℃Oracle分析函数之Lag和Lead()使用
- 554℃Oracle数据库的单、多行函数 oracle执行多个sql语句
- 550℃0497-如何将Kerberos的CDH6.1从Oracle JDK 1.8迁移至OpenJDK 1.8
- 549℃Oracle 12c PDB迁移(一) oracle迁移到oceanbase
- 540℃【数据统计分析】详解Oracle分组函数之CUBE
- 529℃最佳实践 | 提效 47 倍,制造业生产 Oracle 迁移替换
- 523℃Oracle有哪些常见的函数? oracle中常用的函数
- 最近发表
- 标签列表
-
- 前端设计模式 (75)
- 前端性能优化 (51)
- 前端模板 (66)
- 前端跨域 (52)
- 前端缓存 (63)
- 前端react (48)
- 前端aes加密 (58)
- 前端脚手架 (56)
- 前端md5加密 (54)
- 前端富文本编辑器 (47)
- 前端路由 (61)
- 前端数组 (73)
- 前端js面试题 (50)
- 前端定时器 (59)
- Oracle RAC (73)
- oracle恢复 (76)
- oracle 删除表 (48)
- oracle 用户名 (74)
- oracle 工具 (55)
- oracle 内存 (50)
- oracle 导出表 (57)
- oracle 中文 (51)
- oracle的函数 (57)
- 前端调试 (52)
- 前端登录页面 (48)
本文暂时没有评论,来添加一个吧(●'◡'●)