语法错误:无法在模块外部使用导入语句。

639

我有一个 ApolloServer 项目出了些问题,所以我想更新它,并在使用最新的 Babel 时遇到了一些问题。我的 "index.js" 文件如下:

require('dotenv').config()
import {startServer} from './server'
startServer()

当我运行它时,我收到了错误信息:

SyntaxError: Cannot use import statement outside a module

首先,我尝试了一些方法来说服TPTB*这是一个模块(但没有成功)。所以我把"import"改成了"require",这样就可以了。

但现在我有大约两打其他文件中的"imports"也给我同样的错误。

*我确定我的问题的根源是我甚至不知道是什么在抱怨这个问题。我有点假设它是Babel 7(因为我从Babel 6过来,我必须改变预设),但我不是100%确定。

我找到的大部分解决方案似乎都不适用于纯Node。就像这个:

ES6 module Import giving "Uncaught SyntaxError: Unexpected identifier"

说通过添加"type=module"来解决,但这通常会放在HTML中,而我没有HTML。我还尝试使用我的项目的旧预设:

"presets": ["es2015", "stage-2"],
"plugins": []

但是这给我带来了另一个错误:“错误:插件/预设文件不允许导出对象,只能导出函数。”

以下是我开始使用的依赖项:

"dependencies": {
  "@babel/polyfill": "^7.6.0",
  "apollo-link-error": "^1.1.12",
  "apollo-link-http": "^1.5.16",
  "apollo-server": "^2.9.6",
  "babel-preset-es2015": "^6.24.1",

3
你好,我现在遇到了同样的问题。你能否分享一下你的依赖关系?或者甚至提供一下你更新前后的差异。这样我就可以检查一下我的依赖关系,看是否存在可能引起问题的类似软件包。 - stewo
6
我刚刚将所有的“imports”替换为“requires”,现在一切都很好了。虽然有点傻,但目前没必要费力去弄明白它。不过我会更新原来的代码,并加入依赖项。如果你有任何线索,我会与我的原始代码进行核对。 - user3810626
4
CommonJS语法(require和module.exports)是Node的原始格式,Webpack也支持它,但ES6模块语法(export,import)是较新的方式,现在Node和Webpack都支持它。我看到Node现在也支持import,但许多教程仍旧展示require用于纯Node内容,因此在Node中最好使用那个语法。 - Ted Fitzpatrick
8
"type":"module"并不能解决我的问题,而且有超过一百个importsrequire的语法与imports不同,不是很容易替换。你能否给出一个将imports替换为requires的示例? - Jeb50
权力的巨头:这是一种(略微)滑稽的说法,意味着“我不知道这件事在哪里被决定”。 - user3810626
显示剩余6条评论
36个回答

9

步骤1

yarn add esm

或者

npm i esm --save

步骤2

package.json

"scripts": {
  "start": "node -r esm src/index.js",
}

第三步

nodemon --exec npm start

+1 esm似乎是最简单的解决方案,当你无法将"type": "module"添加到package.json文件时。 - Ale Felix

8

如果你正在使用ES6 JavaScript导入:

  1. 安装 cross-env
  2. package.json 中将 "test": "jest" 改为 "test": "cross-env NODE_OPTIONS=--experimental-vm-modules jest"
  3. package.json 中添加以下内容:
    ...,
    "jest": {
        "transform": {}
    },
    "type": "module"

解释:

cross-env 允许在不改变 npm 命令的情况下更改环境变量。接下来,在文件 package.json 中,您可以更改 npm 命令以启用实验性 ES6 支持 Jest,并配置 Jest 来执行它。


7

我是Node.js的新手,在修复AWS Lambda函数(使用Node.js)时遇到了相同的问题。

我发现了一些在CommonJSES6 JavaScript之间的差异:

ES6:

  • package.json文件中添加"type":"module"

  • 使用"import"从库中使用代码。

    Example: import jwt_decode from jwt-decode

  • Lambda处理程序方法代码应该定义如下:

    "exports.handler = async (event) => { }"

CommonJS:

  • 不要在package.json文件中添加"type":"module"

  • 使用"require"从库中使用代码。

    Example: const jwt_decode = require("jwt-decode");

  • Lambda处理程序方法代码应该定义如下:

    "export const handler = async (event) => { }"


6

要使用import语法,请执行以下操作之一。

  1. .js文件重命名为.mjs
  2. package.json文件中添加{type:module}

1
package.json 中不添加 {type:module} 也可以运行该程序。 - Rdimo
哈哈,自从什么时候Nodejs文件必须以“.mjs”而不是“.js”命名。有点奇怪,但对我来说有效。 - Ezequiel Adrian

6
在我的情况下,我认为问题出在标准的node可执行文件上。node target.ts 我用nodemon替换了它,令人惊讶的是它起作用了!
使用标准可执行文件(运行器)的方法:
node target.ts

使用nodemon可执行文件(运行程序)的方式:

nodemon target.ts

别忘了使用 npm install nodemon 安装 nodemon ;P

注意:这对开发非常有用。但是,对于运行时,您可以使用编译后的 js 文件执行 node 命令!

更新:

问题在于 node 不接受 TypeScript 文件。 相反,ts-node 可能是完美的替代品。


2
也许 nodemon 将文件作为模块执行,因此内在的错误消失了。 - nerkn

3

我在手动升级后遇到了这个错误,它发生在我的NX工作空间中。以下是每个jest.config.js文件需要的更改,以解决此问题:

transform: {
  '^.+\\.(ts|js|html)$': 'jest-preset-angular',
},

to

transform: {
  '^.+\\.(ts|mjs|js|html)$': 'jest-preset-angular',
},

可以,谢谢。但是现在我遇到了这个错误:“可注入的'PlatformLocation'需要使用JIT编译器进行编译,但'@angular/compiler'不可用”。 - alambertt

3
如果你想使用BABEL,我有一个简单的解决方案!
记住这个例子是针对nodejs,例如expressJS服务器!
如果你要使用react或另一个框架,请查看babel文档! 首先,安装(不要安装那些只会垃圾你项目的不必要的东西!)
npm install --save-dev @babel/core @babel/node

只需要2步

然后在您的存储库中配置您的 Babel 文件!

express 服务器 node js 和 babel 的示例

文件名:

babel.config.json

{
    "presets": ["@babel/preset-env"]
}

如果您不想使用 Babel 文件,请使用:

在您的控制台中运行,script.js 是您的入口点!

npx babel-node --presets @babel/preset-env -- script.js

没有文件的Babel示例

完整信息在此:https://babeljs.io/docs/en/babel-node


3

当您运行该命令时,也会出现此错误。

node filename.ts

而不是

node filename.js

简单来说,使用 node 命令时我们需要运行 JavaScript 文件 (filename.js),而不是 TypeScript 文件,除非我们正在使用像 ts-node 的包。


2

如果您正在使用 vite-react.js 应用程序与 Speedy Web Compiler(SWC),并尝试导入 jest 测试库的各种方法 ({import { describe, expect, test } from "@jest/globals";),则您的所有测试将单独运行并且在模块外部。因此,您可能会遇到以下错误:

SyntaxError: Cannot use import statement outside a module

由于您正在使用 SWC,babel 配置无法解决该问题。所以可以通过简单地添加开发依赖项来解决:

npm install --save-dev @types/jest

稍后移除 import 语句,直接使用方法(describe、test、expect、afterAll、afterEach、beforeAll、beforeEach、fail、fdescribe、fit、it、jasmine、jest、pending、spyOn、xdescribe、xit、xtest),因为它们被视为全局变量。这里安装链接和其他文档!@types/jest

通过 npm run test 测试您的 sum.test.js 文件,假设在脚本命令中有"test": "jest",并且 jest 是开发依赖项:

const sum = (val1, val2) => {
  return val1 + val2;
};

describe("sum module", () => {
  test("adds 1 + 2 to equal 3", () => {
    expect(sum(1, 2)).toBe(3);
  });
});


1

这份文档不太清晰。我使用Node.js在本地计算机上执行一些任务。

假设我的旧脚本是 test.js。 如果我想要使用它内部的某些代码,那么:

import something from "./mylocalECMAmodule";

它会抛出如下错误:

(node:16012) Warning: To load an ES module, set "type": "module" in the package.json or use the .mjs extension.
SyntaxError: Cannot use import statement outside a module
...

这不是一个模块错误,而是Node.js的错误。禁止加载除了'module'以外的任何内容。

要解决此问题,只需将旧脚本test.js重命名为test.mjs即可。

就是这样。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接