语法错误:不能在module外使用导入语句

IT技术 javascript node.js node-modules package.json npm-package
2021-01-17 19:35:36

我有一个ApolloServer项目给我带来了麻烦,所以我想我可能会更新它并在使用最新的 Babel 时遇到问题。我的“index.js”是:

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

当我运行它时,我收到错误

SyntaxError: Cannot use import statement outside a module

首先,我试图说服 TPTB* 这是一个module(但没有成功)。所以我将“导入”更改为“要求”,这奏效了。

但是现在我在其他文件中有大约两打“导入”给了我同样的错误。

*我确定我的问题的根源在于我什至不确定是什么在抱怨这个问题。我有点假设它是 Babel 7(因为我来自 Babel 6,我不得不更改预设)但我不是 100% 确定。

我为解决方案找到的大部分内容似乎不适用于直接 Node.js。就像这里的这个:

ES6 module导入给出“Uncaught SyntaxError: Unexpected identifier”

说它是通过添加“type=module”解决的,但这通常会出现在 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",
6个回答

验证您是否安装了最新版本的 Node.js(或至少 13.2.0+)。然后执行以下操作之一,如文档中所述

选项1

在最近的父package.json文件中,添加"type"值为的顶级字段"module"这将确保所有.js.mjs文件都被解释为 ES module。您可以使用扩展名将单个文件解释为CommonJS.cjs

// package.json
{
  "type": "module"
}

选项 2

使用.mjs扩展名显式命名文件所有其他文件,例如.js将被解释为 CommonJS,如果type未在package.json.

或使用巴别塔!` module.exports = { 预设:['@babel/preset-env'], }; `
2021-03-21 19:35:36
如果我使用这个,然后更改路径以包含所需文件的“js”,然后更改所需文件中export语句的格式,然后将我从“import”更改的所有“require”语句取出——因为现在“require”是未知的——这会起作用,所以我会接受这个答案。
2021-04-02 19:35:36
如果问题出在 node_modules/ 下,这不是一个真正的选择,对吗?在这种情况下如何解决任何想法?
2021-04-03 19:35:36
@Cocuba 的答案是正确的,应该是公认的答案,因为它实际上是转译的。
2021-04-04 19:35:36
如果您正在运行.ts文件,则此解决方案不起作用如果您可以简单地使用nodemon代替来添加它node,根据下面的这个答案stackoverflow.com/a/65058291/11664580,它有望为人们节省我花了半天的时间。或者,安装ts-node似乎是一种解决方案,根据stackoverflow.com/a/61947868/11664580
2021-04-04 19:35:36

如果有人在使用TypeScript 时遇到这个问题,那么为我解决这个问题的关键是改变

    "target": "esnext",
    "module": "esnext",

    "target": "esnext",
    "module": "commonjs",

在我的tsconfig.json. 我的印象是“ esnext”是“最好的”,但这只是一个错误。

如果您正在使用babel-node,那么您还需要使用该--extensions选项,例如babel-node --extensions \".ts,.tsx\" src/index
2021-03-16 19:35:36
该死的,它让我免于许多麻烦。esnext在最好的印象下犯了同样的错误
2021-03-18 19:35:36
是的,这在尝试“类型”时做到了:“module”突然说“需要未定义”。
2021-03-28 19:35:36

对于那些在阅读答案时和我一样困惑的人,在您的 package.json 文件中,"type": "module" 在上层添加 如下所示:

{
  "name": "my-app",
  "version": "0.0.0",
  "type": "module",
  "scripts": { ...
  },
  ...
}
tx,但是你知道我在哪里可以找到 package.json 吗??我正在使用 netbeans。我还在我的 macbook 上搜索了 package.json,但我看到了很多 package.json 文件。有小费吗?
2021-03-13 19:35:36
嗨亚历克斯,自从在 Java 项目中工作已经有一段时间了,但我希望这个链接可以给你一个关于在哪里找到 package.json 文件的线索:stackoverflow.com/questions/41513559/...
2021-04-03 19:35:36

根据官方文档

import 语句只允许在 ES module中使用。有关 CommonJS 中的类似功能,请参阅 import()。

要使 Node.js 将您的文件视为 ES module,您需要(启用):

  • 将 "type": "module" 添加到 package.json
  • 向 Node.js 调用添加“--experimental-modules”标志
@Cullub 应该使用什么?
2021-03-19 19:35:36
你根本不需要任何标志。
2021-03-24 19:35:36
并不是说这个答案是错误的,我看过相同的文档。但是我不明白在 CommonJS 中使用 import() 访问 es6 module的建议是如何有用的。它是异步的,因此不能用于在文件级别导入任何内容。至少可以说,这使得尝试从 CommonJS 访问 es6 module很痛苦。考虑到主要的单元测试框架 Jasmine Jest 等根本不能很好地处理这个问题,这让我认为,除非有更好的互操作支持,否则整个 Node es6 情况对我来说似乎是半成品,但我很想被证明是错误的。
2021-03-29 19:35:36
是我还是这个导入/module的事情变得绝对复杂的一团糟。Somone 只需要按下重置按钮,让所有 JS 框架都使用相同的东西。
2021-04-01 19:35:36
2020 更新:--experimental-modules不再需要。
2021-04-08 19:35:36

我遇到了同样的问题,甚至更糟:我需要“导入”和“需要”

  1. 一些较新的 ES6 module仅适用于import
  2. 一些CommonJS使用require

这是对我有用的:

  1. 按照其他答案中的建议将您的 js 文件转换为 .mjs

  2. ES6 module没有定义“require”,所以你可以这样定义:

    import { createRequire } from 'module'
    const require = createRequire(import.meta.url);
    

    现在'require'可以以通常的方式使用。

  3. 对 ES6 module使用import对 CommonJS使用require

一些有用的链接:Node.js's own documentationimport 和 require 之间的区别Mozilla 有一些关于导入的不错的文档