import...from... 和 require 如何找到模块位置?

本文探讨了JavaScript中的模块导入机制,通过分析`import`和`require`如何找到模块位置。内容涉及Node.js模块查找规则,包括以`./`、`../`开头的相对路径以及模块名称的情况。同时,文章提到了ES Module的查找规则,并指出在`package.json`中设置`type`字段为`module`的重要性。最后,文章以一个实际例子说明了在不同打包工具如Webpack下,模块解析的最终目标。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

import Vue from "vue"; 

为什么不用写相对地址和绝对地址就能够导出 Vue 呢?似乎也没有配置路径?也没有配置映射,那么究竟 from "vue"; 对应的究竟是那个路径呢?

先提出两个可能的方案

1.VS Code/WebStorm 这些 IDE 自己编撰的映射,并缓存了
2.Webpack/Vite 这些开发工具自带的映射

关于上面这两个方案其实很容易验证,基于终端/命令行去运行项目并且不使用 WebpackVite 这两个库

1.第一步,执行以下语句

npm init
# shelljs 是一个可以使用 node 执行 shell 脚本的库
# 例子中使用 shelljs 测试输出
npm install shelljs 

2.第二步,在 package.json 同目录下创建 index.js,内容如下

const shelljs = require("shelljs");

shelljs.exec("echo Hello World"); 

3.第三步,测试运行 node index.js,输出如下

即证与 IDEWebpack/Vite 无关

那究竟是怎么找到的呢?

node 模块

仔细观察 node index.js 是通过 node 执行的,所以有没有可能是通过 node 去找到的模块呢?

那么 node 执行 .js 文件时是按照什么规则来寻找的呢?

假设在 Y 路径执行 index.js

// index.js
const module = require(X) 

X 以 或 ‘./’ 或 ‘…/’ 开头

判断 Y + X 是文件还是目录

Y + X 是文件

1.如果 X 是一个文件,加载 X 作为 JavaScript 文本。结束
2.如果 X.js 是一个文件,加载 X.js 作为 JavaScript 文本。结束
3.如果 X.json 是一个文件,解析 X.json 成一个 JavaScript 对象。结束
4.如果 X.node 是一个文件,加载 X.node 作为二进制插件。结束

例子

// index.js
const shelljs = require("./X");

shelljs.exec("echo Hello World"); 
// X.js
module.exports = {exec: () => {console.log("Hello World");}
} 
├── index.js
└── X.js 

注意,有文档称,require(/X) 这种方式也可以找到对于的模块,但在 node@16.15.1 的版本中已经不行,是无法找到的

Y + X 是目录

判断是否有名称为 index 的文件

Y + X 目录下有名为 index 的文件

1.如果 X/index.js 是一个文件,加载 X/index.js 作为 JavaScript 文本。结束
2.如果 X/index.json 是一个文件,解析 X/index.json 成一个 JavaScript 对象。结束
3.如果 X/index.node 是一个文件,加载 X/index.node 作为二进制插件。结束

Y + X 目录下没有名为 index 的文件

根据 Y + X 目录下的 package.json"main" 字段找到对应的文件

没有 package.json 怎么办?当然是报错咯

X 是模块名称

1.先去系统模块寻找
2.系统模块没有找到就去执行环境的同目录下找 node_modules,查看有无同名的 .js 文件1.没有同名的 .js 文件就去找同名目录1.如果找到了,就查看文件夹里有没有 index.js2.没有找到就查看 package.json"main" 属性来确定2.没有同名目录,抛出错误
3.同目录找不到 node_modules 就去父目录找,父目录找不到就找父目录的父目录,直至找到全局 node_modules

关于 node 更加详细的‘寻模块’规则,可以去查阅这个文档,里面有一个伪代码,非常详细和清晰

ES Module

上面讲了 require 的寻找规则,但是没讲 ES Module 的寻找规则(即 import),其实它们的寻址方式是一致的,不过 ES Module 需要在 package.json 设置 "type" 字段为 module 才可以开启,而且找的是package.json"module" 字段对应的文件

// package.json
{"type": "module"
} 

那么回到文章一开始提到的 import Vue from "vue";,它最终找到的模块是什么呢?因为 Vue 本身提供多种打包文件(Commen.jsES Module

如上图所示 import Vue from "vue"; 最终找的是 vue.runtime.esm.js,这也就解释了为什么导出来的 Vue 是不带编译时只有运行时的了

最后

整理了一套《前端大厂面试宝典》,包含了HTML、CSS、JavaScript、HTTP、TCP协议、浏览器、VUE、React、数据结构和算法,一共201道面试题,并对每个问题作出了回答和解析。

有需要的小伙伴,可以点击文末卡片领取这份文档,无偿分享

部分文档展示:



文章篇幅有限,后面的内容就不一一展示了

有需要的小伙伴,可以点下方卡片免费领取

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值