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() 成为一个同步操作。
它与动态导入不同,因为尽管两者都接受模块说明符作为第一个参数,但 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(导入映射也不尝试),因此无论 ./modules/my-module/index.js 是否实际存在,它都会打印已解析的 URL。
与 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!");
这对于计算其他 Worker 的路径也很有用,例如服务 Worker 和共享 Worker。但是,如果您使用相对路径来计算服务 Worker 的 URL,请记住,已解析路径的目录默认决定了它的注册范围(尽管可以在注册期间指定不同的范围)。
规范
| 规范 |
|---|
| HTML # import-meta-resolve |
浏览器兼容性
加载中…