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

当 import 声明不在模块的顶层时,就会出现 JavaScript 异常“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)

错误类型

哪里出错了?

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

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

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

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

示例

条件导入

您不能在其他结构中使用 import,就像您在 Python 中可能做的那样。

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

import 移动到顶层,或使用动态导入。

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

在非模块脚本中导入

如果您从 HTML 加载脚本,请确保向 <script> 标签添加 type="module" 属性。

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

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

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

main();

另请参阅