SyntaxError: import declarations may only appear at top level of a module

JavaScript 异常 "import declarations may only appear at top level of a module"(import 声明只能出现在模块的顶层)发生在 import 声明没有出现在模块的顶层时。这可能是因为 import 声明嵌套在其他结构(函数、块等)中,或者更常见的是因为当前文件没有被当作模块处理。

消息

SyntaxError: Cannot use import statement outside a module (V8-based)
SyntaxError: import declarations may only appear at top level of a module (Firefox)
SyntaxError: Unexpected identifier 'x'. import call expects one or two arguments. (Safari)

错误类型

SyntaxError

哪里出错了?

你可能有一个嵌套在其他结构(例如函数或块)中的 import 声明。import 声明必须位于模块的顶层。如果你想有条件地导入模块,或者按需延迟导入模块,请改用动态 import

如果 import 已经位于代码的顶层,那可能是因为文件未被解释为模块。运行时需要外部提示来确定文件是否为模块,以下是提供此类提示的几种方法:

  • 如果文件直接从 HTML 加载,请确保 <script> 标签具有 type="module" 属性。
  • 如果文件在 Node 中运行,请确保文件具有 .mjs 扩展名,或者最近的 package.json 文件具有 "type": "module" 字段。
  • 如果文件作为 worker 运行,请确保在调用 Worker() 构造函数时带有 type: "module" 选项。
  • 从另一个模块导入此文件。

另一个原因可能是当你使用编译器(如 TypeScript)编写 import 时,你不小心运行了源文件。由于 import 声明通常出现在程序的开头,它们是解析器首先看到并抱怨的东西。请确保编译源文件并执行编译后的文件。

示例

条件导入

你不能像在 Python 中那样在其他结构内部使用 import

js
if (writeOutput) {
  import fs from "fs"; // SyntaxError
}

要么将 import 移动到顶层,要么使用动态 import。

js
if (writeOutput) {
  import("fs").then((fs) => {
    // use fs
  });
}

在非模块脚本中导入

如果你从 HTML 加载脚本,请务必将 type="module" 属性添加到 <script> 标签。

html
<script type="module" src="main.js"></script>

如果由于某种原因你无法将脚本迁移到模块,则可以使用动态 import。

js
async function main() {
  const myModule = await import("./my-module.js");
  // use myModule
}

main();

另见