如何修复JavaScript错误“Cannot Use Import Statement Outside a Module”

如何修复JavaScript错误“Cannot Use Import Statement Outside a Module”

如果在配置不当的 JavaScriptTypeScript 模块中遇到 import 关键字,就会出现 “无法在模块外使用 import 语句” 的错误消息。

在 JavaScript 服务器端运行时环境中,当 Node.js 期望使用 CommonJS 模块系统使用的 require 关键字时,使用 ECMAScript (ES) 编写的模块的 import 语法通常会导致该错误。

TypeScript 支持不同的模块格式,但混淆 ES 和 CommonJS 模块导入方法的编码错误也会导致此错误。

在浏览器方面,当您没有为 JavaScript 代码文件使用捆绑程序时,通常会出现此错误。

本文探讨了这三种错误来源,并详细介绍了针对每种环境的解决方案。

如何在服务器端 JavaScript 环境中解决错误

本节演示如何在服务器端 JavaScript 环境中解决错误。

背景介绍

Node.js 默认使用 CommonJS 系统的 require 关键字。因此,除非将 Node.js 配置为支持 ES 模块语法,否则您将收到熟悉的错误。同样,Node.js 需要 .mjs 扩展名才能识别和使用 ES 模块。

解决方案

除了使用 .mjs 之外,您还可以通过使用捆绑程序或使用 --experimental-modules 标志运行 Node.js 来使旧版本的 Node.js 与当前的 ES 模块兼容。否则,您可以将 package.json 文件中的 type 字段设置为 module,如下所示:

{
"name": "test-package",
"version": "1.0.0",
"type": "module",
"main": "app.js",
"dependencies": { }
}

(注意:您应在所有软件包的 package.json 文件中包含 type 属性。这种做法便于识别所使用的模块系统,并确保库之间的一致性)。

另一种避免错误的方法是确保 import 和 export 语法正确并能正确加载。关键是要始终使用相对文件路径、命名导出、导出文件扩展名,并避免默认导出。

下面是一个例子:

//module import 
import { sampleFunction } from './sampleModule.js';
// function export
export function sampleFunction() {
// code goes here
}

最后,应确保所有第三方库与 ES 模块兼容。有关信息,请参阅 package.json 文件中的库文档。或者,使用捆绑程序转译代码,以便 JavaScript 环境可以理解。

如何在 TypeScript 环境中解决错误

本节演示如何在 TypeScript 环境中解决错误信息。

模块背景

通过模块,您可以在一个项目中的多个文件之间重用、组织和共享代码。ES 支持使用 import 和 export 关键字在不同文件间共享代码的外部模块。

当使用 ES 模块语法而未配置 TypeScript 以使用它时,通常会在 TypeScript 环境中出现此错误。由于 TypeScript 是 JavaScript 的超集,它默认使用 CommonJS 语法进行导入,即使用 require 而不是 import。在这种情况下, import 语句会导致错误。尽管如此,正确配置 TypeScript 对它支持 ES 模块还是很有必要的。

如果使用了不正确的文件扩展名,也可能会遇到此错误。例如,在使用 ES 模块语法的 Node.js 环境中使用 TypeScript 时,要导入的模块必须使用 .mjs 文件扩展名,而不是普通的 .js

另一个常见的错误原因是,在使用 Webpack 等捆绑程序时,tsconfig.jsonpackage.json 文件中的 module 字段配置不当。不过,您可以通过将 tsconfig.json 文件中的模块和目标字段设置为 ECMAScript,在 TypeScript 中使用捆绑程序捆绑 ES 模块。这样,Webpack 就能理解目标环境,并在转译代码时使用正确的文件扩展名。

解决方案

要使用 RequireJS 等模块加载器或 Webpack 等捆绑程序加载 ES 模块,请在 tsconfig.json 文件中添加以下内容:

{
"compilerOptions": {
"module": "es20215",
"target": "es20215",
"sourceMap": true
}
}

在上面代码的 compilerOptions 部分,module 和 target 字段被设置为使用 es20215 模块。有了这些补充,你就可以在 TypeScript 环境中使用 importexport 语句,而不会导致错误。

由于 TypeScript 默认使用 CommonJS,如果没有相应修改 tsconfig.json 文件,就会导致错误信息。

幸运的是,一旦你将 module 和 target 字段设置为使用 ECMAScript 模块,你就可以使用 export 语句从一个模块导出函数或变量,并使用 import 语句将另一个模块加载到当前模块的作用域中。这一过程在下面的代码中出现:

// sum.ts
export function sum(a: number, b: number, c: number): number {
return a + b + c;
}
// main.ts
import { sum } from './sum';
console.log(add(4, 4, 9));

如果您使用的是旧版本的 Node.js,可以使用 --experimental-modules 标志运行代码,从而启用 ES 模块支持。您还应该使用 Webpack、Browserify 或 Rollup 等捆绑程序捆绑所有 ES 代码,并将其输出到一个文件中。确保它是浏览器和旧版 Node.js 可以理解的版本,并在项目根目录下设置一个 Webpack.config.js 文件,指定模块类型。

下面是从 Webpack 文档中摘录的一个示例:

module.exports = {
entry: './src/index.ts',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
},
resolve: {
extensions: ['.ts', '.js', '.mjs']
},
module: {
rules: [
{
test: /.ts$/,
use: 'ts-loader',
exclude: /node_modules/
}
]
},
experiments: {
outputModule: true
}
};

编译后的代码会输出到项目根目录下 dist 目录中的 bundle.js 文件中。

您还可以使用 es-module-shims 等多填充程序,以不支持 ES 模块 import 和 export 语句的旧版浏览器为目标。

如何解决浏览器端 JavaScript 中的错误

本节将介绍如何在浏览器端 JavaScript 环境中解决错误。

浏览器背景

大多数现代浏览器(包括 Chrome、Firefox、Edge 和 Safari)都支持 ES 模块,因此不需要使用浏览器多填充程序、捆绑程序或转译程序。

如果您使用基于 React 或 Vue JavaScript 的前端库,也不需要这些工具,因为它们默认支持 ES imports 和 exports 字段。不过,旧版浏览器不支持 ES 语法,因此需要这些工具来实现跨平台兼容性。

在旧版浏览器中最常见的错误原因是页面的 HTML 文件不包含 type="module" 属性。在这种情况下,出现错误的原因是网络上运行的 JavaScript 不支持 ES 模块语法。对于通过网络发送的 JavaScript 代码,当尝试从不同域加载 ES 模块时,可能会遇到跨源资源共享错误。

解决方案

为防止在旧版浏览器中出现模块错误,请确保在 HTML 根文件中使用正确的 script 标记属性 – type="module" 。或者,也可以使用 Webpack 对代码进行转译,以便旧版浏览器能够理解。

要使用 type="module" 属性,请在 HTML 根文件中加入以下一行:

<script type="module" src="app.js"></script>

确保 import 文件路径有效和使用正确的 import 语法同样重要。

此外,还可以访问 Can I Use 等网站,确认 ES 模块的浏览器兼容性。

最后,由于使用 .js 文件扩展名是常见做法,作为一种变通方法,您可以在模块的 HTML 文件 script 标记中设置 type 属性。将此属性设置为 module,浏览器就会忽略 .js 扩展名,将文件视为模块。

小结

“Cannot use import statement outside a module”错误出现的原因有很多,具体取决于您是在浏览器端还是服务器端 JavaScript 环境中。语法错误、配置不当和不支持的文件扩展名仍然是该错误最常见的几种原因。

虽然大多数现代浏览器都支持 ES 模块,但您必须确保与旧版浏览器兼容。通过 Webpack 等捆绑程序,您可以将所有源代码及其依赖项编译为旧版浏览器可以理解的单一输出。

记得在 HTML 文件中添加 type="module" 属性,以告知浏览器该模块是 ES 模块。最后,虽然 CommonJS 默认使用 .js 扩展名,但您也可以使用 .mjs

评论留言