import.meta.resolve()

Baseline 已广泛支持

此功能已成熟,并可在许多设备和浏览器版本上运行。自 2023 年 3 月以来,它已在各种浏览器中可用。

import.meta.resolve() 是 JavaScript 模块的 import.meta 对象上定义的内置函数,它使用当前模块的 URL 作为基础,将模块说明符解析为 URL。

语法

js
import.meta.resolve(moduleName)

参数

moduleName

指定一个可能可导入模块的字符串。这可以是一个相对路径(例如 "./lib/helper.js")、一个裸名称(例如 "my-module")或一个绝对 URL(例如 "https://example.com/lib/helper.js")。

返回值

返回一个字符串,该字符串对应于如果将参数传递给 import() 将导入的路径。

描述

import.meta.resolve() 允许脚本访问名称的模块说明符解析算法,如下所示:

js
// 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() 返回将要导入的路径,而不尝试访问该路径。因此,以下两个代码片段实际上是相同的:

js
// 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()。例如,您可以在浏览器中使用导入映射来定义它:

html
<!-- 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()

js
const helperPath = new URL("./lib/helper.js", import.meta.url).href;
console.log(helperPath);

当针对旧版浏览器时,这也是一个有用的替代语法。但是,存在一些差异:

  • import.meta.resolve() 返回一个字符串,而 new URL() 返回一个 URL 对象。可以在构造的 URL 上使用 hreftoString(),但这在某些 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() 也可能在非浏览器环境中可用:

示例

为 Worker() 构造函数解析路径

import.meta.resolve() 对于接受脚本文件路径作为参数的 API 特别有价值,例如 Worker() 构造函数:

js
// main.js
const workerPath = import.meta.resolve("./worker.js");
const worker = new Worker(workerPath, { type: "module" });
worker.addEventListener("message", console.log);
js
// worker.js
self.postMessage("hello!");

这对于计算其他 Worker 的路径也很有用,例如服务 Worker共享 Worker。但是,如果您使用相对路径来计算服务 Worker 的 URL,请记住,已解析路径的目录默认决定了它的注册范围(尽管可以在注册期间指定不同的范围)。

规范

规范
HTML
# import-meta-resolve

浏览器兼容性

另见