import.meta.resolve()
import.meta.resolve()
是在 JavaScript 模块的 import.meta
对象上定义的内置函数,它使用当前模块的 URL 作为基准,将模块说明符解析为 URL。
语法
import.meta.resolve(moduleName)
参数
moduleName
-
指定一个可能可导入的模块的字符串。这可能是一个相对路径(例如
"./lib/helper.js"
),一个裸名称(例如"my-module"
),或一个绝对 URL(例如"https://example.com/lib/helper.js"
)。
返回值
返回一个字符串,对应于如果将参数传递给 import()
将导入的路径。
描述
import.meta.resolve()
允许脚本访问名称的模块说明符解析算法,如下所示
// Script at https://example.com/main.js
const helperPath = import.meta.resolve("./lib/helper.js");
console.log(helperPath); // "https://example.com/lib/helper.js"
请注意,import.meta.resolve()
只执行解析,而不尝试加载或导入结果路径。(规范说明 描述了此行为的原因。)因此,无论返回的路径是否对应于存在的文件,以及该文件是否包含有效的模块代码,其返回值都相同。
它与动态导入不同,因为尽管两者都接受模块说明符作为第一个参数,但import.meta.resolve()
返回将要导入的路径,而不会尝试访问该路径。因此,以下两个代码段实际上是相同的
// Approach 1
console.log(await import("./lib/helper.js"));
// Approach 2
const helperPath = import.meta.resolve("./lib/helper.js");
console.log(await import(helperPath));
但是,即使无法成功导入 "./lib/helper.js"
,第二个代码段也不会遇到错误,直到它尝试在第 2 行执行导入操作。
裸模块名称
您可以将裸模块名称(也称为裸模块说明符)传递给 import.meta.resolve()
,只要为该名称定义了模块解析即可。例如,您可以在浏览器内部使用 导入映射 来定义它
<!-- index.html -->
<script type="importmap">
{
"imports": {
"my-module": "./modules/my-module/index.js"
}
}
</script>
<script type="module">
const moduleEntryPath = import.meta.resolve("my-module");
console.log(moduleEntryPath);
</script>
同样,由于此代码段没有尝试导入 moduleEntryPath
——导入映射也没有——因此它会打印解析后的 URL,而不管 ./modules/my-module/index.js
是否实际存在。
与 new URL() 的比较
URL()
构造函数接受第二个基本 URL 参数。当第一个参数是相对路径并且基本 URL 是 import.meta.url
时,其效果类似于 import.meta.resolve()
。
const helperPath = new URL("./lib/helper.js", import.meta.url).href;
console.log(helperPath);
在针对较旧的浏览器时,这也是一个有用的替代语法。但是,也存在一些差异
import.meta.resolve()
返回一个字符串,而new URL()
返回一个URL
对象。可以在构造的URL
上使用href
或toString()
,但这在某些 JavaScript 环境中或使用捆绑器等工具静态分析代码时可能仍然无法产生完全相同的结果。import.meta.resolve()
了解其他解析配置,例如使用导入映射解析裸模块名称,如上所述。new URL()
不了解导入映射,并将裸模块名称视为相对路径(即new URL("my-module", import.meta.url)
表示new URL("./my-module", import.meta.url)
)。
某些工具将 new URL("./lib/helper.js", import.meta.url).href
识别为对 "./lib/helper.js"
的依赖项(类似于导入),并将其考虑在内,用于捆绑、重写移动文件的导入、"转到源代码" 功能等功能。但是,由于 import.meta.resolve()
歧义性更小,并且专门设计用于指示模块路径解析依赖项,因此对于这些用例,应尽可能使用 import.meta.resolve(moduleName)
而不是 new URL(moduleName, import.meta.url)
。
不是 ECMAScript 功能
import.meta.resolve()
并未在 JavaScript 模块的 ECMAScript 规范 中指定或记录。相反,规范定义了 import.meta
对象,但 将所有其属性留为“主机定义的”。WHATWG HTML 标准在 ECMAScript 标准结束的地方接手,并 使用其 模块说明符解析 定义了 import.meta.resolve
。
这意味着并非所有符合 JavaScript 实现都必须实现 import.meta.resolve()
。但是,import.meta.resolve()
也可能在非浏览器环境中可用
- Deno 实现 与浏览器行为的兼容性。
- Node.js 也实现了
import.meta.resolve()
函数,但如果您使用--experimental-import-meta-resolve
标志,则会添加额外的parent
参数。
示例
为 Worker() 构造函数解析路径
import.meta.resolve()
对于将脚本文件路径作为参数的 API(例如 Worker()
构造函数)特别有价值
// main.js
const workerPath = import.meta.resolve("./worker.js");
const worker = new Worker(workerPath, { type: "module" });
worker.addEventListener("message", console.log);
// worker.js
self.postMessage("hello!");
这对于计算其他工作线程(例如 服务工作线程 和 共享工作线程)的路径也很有用。但是,如果您使用相对路径来计算服务工作线程的 URL,请记住,解析路径的目录默认情况下会确定其 注册范围(尽管可以在 注册期间 指定不同的范围)。
规范
规范 |
---|
HTML 标准 # hostgetimportmetaproperties |
浏览器兼容性
BCD 表格仅在启用 JavaScript 的浏览器中加载。