Node.js - SyntaxError:意外的令牌导入

我不明白是怎么回事。 节点v5.6.0 NPM v3.10.6 < / p > < p >代码:

function (exports, require, module, __filename, __dirname) {
import express from 'express'
};

错误:

SyntaxError: Unexpected token import
at exports.runInThisContext (vm.js:53:16)
at Module._compile (module.js:387:25)
at Object.Module._extensions..js (module.js:422:10)
at Module.load (module.js:357:32)
at Function.Module._load (module.js:314:12)
at Function.Module.runMain (module.js:447:10)
at startup (node.js:140:18)
at node.js:1001:3
797850 次浏览

不幸的是,Node.js还不支持ES6的import

要完成您要做的事情(导入Express模块),这段代码应该足够了

var express = require("express");

另外,确保通过运行安装了Express

$ npm install express

有关学习Node.js的更多信息,请参阅node . js文件

由于节点13,你可以使用.mjs扩展,或者在package.json中设置{"type": "module"}。你需要使用--experimental-modules标志。Modules现在在node.js中被标记为稳定

由于节点12,你可以使用.mjs扩展,或者在package.json中设置"type": "module"。你需要运行带有--experimental-modules标志的node。

节点9中,它在标志后面启用,并使用.mjs扩展。

node --experimental-modules my-app.mjs

虽然import确实是ES6的一部分,但不幸的是,默认情况下NodeJS还不支持它,直到最近才在浏览器中获得支持。 . c是ES6的一部分

参见浏览器compat表上的MDN本节点问题

摘自James M Snell的Node.js中ES6模块的更新(2017年2月):

工作正在进行中,但需要一些时间——我们目前预计至少需要一年。

直到支持显示本机(现在标记为稳定的节点13+), 你将不得不继续使用经典的require语句:

const express = require("express");

如果你真的想在NodeJS中使用新的ES6/7特性,你可以使用Babel编译它。下面是一个服务器示例

错误: SyntaxError:意外令牌进口或SyntaxError:意外令牌出口


以更改所有导入为例

const express               = require('express');
const webpack               = require('webpack');
const path                  = require('path');
const config                = require('../webpack.config.dev');
const open                  = require('open');

并将你的export default = foo;更改为module.exports = foo;

如果你可以使用'babel',试着在package.json(——presets=es2015)中添加构建脚本,如下所示。它可以预编译导入代码到es2015

"build": "babel server --out-dir build --presets=es2015 && webpack"

在我的例子中,它是在查找.babelrc文件,它应该包含如下内容:

{
"presets": ["es2015-node5", "stage-3"],
"plugins": []
}

正如在其他回答中提到的,Node JS目前不支持ES6导入。

(从现在开始,请阅读EDIT 2)

在节点js中启用ES6导入为这个问题提供了一个解决方案。我试过这个方法,对我很有效。

执行如下命令:

    npm install babel-register babel-preset-env --save-dev

现在需要创建一个新文件(config.js),并向其中添加以下代码。

    require('babel-register')({
presets: [ 'env' ]
})
// Import the rest of our application.
module.exports = require('./your_server_file.js')

现在您可以编写import语句而不会得到任何错误。

希望这能有所帮助。

编辑:

您需要运行使用上述代码创建的新文件。在我的例子中,它是config.js。所以我得跑了:

    node config.js

编辑2:

在试验过程中,我发现了一个简单的解决方法。

在项目的根目录中创建.babelrc文件。

添加以下(和任何其他你需要的babel预设,可以添加在这个文件中):

    {
"presets": ["env"]
}

使用命令npm install babel-preset-env --save安装babel-preset-env,然后使用命令npm install babel-cli -g --save安装babel-cli

现在,进入服务器或索引文件所在的文件夹,使用以下命令运行: babel-node fileName.js < / p >

或者你可以通过在你的package.json文件中添加以下代码来运行npm start:

    "scripts": {
"start": "babel-node src/index.js"
}

如果你仍然不能使用“import”,这里是我如何处理它: 只需将其转换为节点友好的要求。例子:< / p >

import { parse } from 'node-html-parser';

等于:

const parse = require('node-html-parser').parse;

babel 7 proposal 你能添加开发依赖

npm i -D @babel/core @babel/preset-env @babel/register

并在根目录中添加。babelrc

{
"presets": [
[
"@babel/preset-env",
{
"targets": {
"node": "current"
}
}
]
]
}

并添加到.js文件中

require("@babel/register")

或者如果你在cli中运行它,你可以使用require钩子作为-r @babel/register, ex。

$node -r @babel/register executeMyFileWithESModules.js

截至Node.js v12(现在这可能相当稳定,但仍然标记为“实验”),你有两个选项来使用ESM (ECMA年代cript odules)在Node.js(文件,有第三种方法来计算字符串),下面是的文档说的:

--experimental-modules标志可用于启用对 ECMAScript模块(ES模块) 一旦启用,Node.js将把以下模块作为ES模块传递给 node作为初始输入,或者当被import语句引用时 ES模块代码:

  • .mjs结尾的文件。

  • .js结尾的文件,或无扩展名文件,当最近的父文件 package.json文件包含一个顶级字段"type",值为 "module" . < / p >

  • 作为参数传入--eval--print的字符串,或通过管道传入 node通过STDIN,带有标志--input-type=module.

Node.js将把所有其他形式的输入视为CommonJS,比如.js文件 其中最近的父package.json文件不包含顶级"type" 字段,或不带--input-type标志的字符串输入。这种行为是 保持向后兼容性。然而,现在Node.js两者都支持 CommonJS和ES模块,最好尽可能显式。node . js 将把下面的作为CommonJS作为初始输入传递给node, 或ES模块代码中的import语句引用时:

  • .cjs结尾的文件。

  • .js结尾的文件,或无扩展名文件,当最近的父文件 package.json文件包含一个顶级字段"type",值为 "commonjs" . < / p >

  • 作为参数传入--eval--print的字符串,或通过管道传入 node通过STDIN,带有标志--input-type=commonjs.

当我开始使用express时,我总是想要一个使用import而不是require的解决方案

const express = require("express");
// to
import express from "express"

很多时候都要经过这一行:- Unfortunately, Node.js doesn't support ES6's import yet.

现在为了帮助其他人,我在这里创建了两个新的解决方案

1) < >强esm < / >强: -

精彩的简单,babel-less, bundle-less ECMAScript模块加载器。 让我们让它工作

  yarn add esm / npm install esm

创建start.js或使用您的命名空间

 require = require("esm")(module/*, options*/)
// Import the rest of our application.
module.exports = require('./src/server.js')
// where server.js is express server start file

改变你的package.josn路径start.js

  "scripts": {
"start": "node start.js",
"start:dev": "nodemon start.js",
},
"dependencies": {
+    "esm": "^3.2.25",
},
"devDependencies": {
+   "nodemon": "^1.19.2"
}

2) < >强巴别塔js < / >强: -

这可以分为两部分

a) <强>解决方案1 < / >强感谢timonweb.com

b) 解决方案2

使用< >强巴别塔6 < / >强(旧版本的babel-preset-stage-3 ^ 6.0) 创建.babelrc文件在根文件夹

{
"presets": ["env", "stage-3"]
}

安装babel-preset-stage-3

yarn add babel-cli babel-polyfill babel-preset-env bable-preset-stage-3 nodemon --dev

package.json中的变化

"scripts": {
+   "start:dev": "nodemon --exec babel-node -- ./src/index.js",
+   "start": "npm run build && node ./build/index.js",
+   "build": "npm run clean && babel src -d build -s --source-maps --copy-files",
+   "clean": "rm -rf build && mkdir build"
},
"devDependencies": {
+    "babel-cli": "^6.26.0",
+    "babel-polyfill": "^6.26.0",
+    "babel-preset-env": "^1.7.0",
+    "babel-preset-stage-3": "^6.24.1",
+    "nodemon": "^1.19.4"
},

启动服务器

yarn start / npm start

哦,不,我们制造了新问题

regeneratorRuntime.mark(function _callee(email, password) {
^
ReferenceError: regeneratorRuntime is not defined

此错误仅当您在代码中使用async/await时出现。 然后使用包含自定义再生器运行时和core-js的polyfill。 添加到index.js

import "babel-polyfill"

这允许您使用async/await

使用巴别塔7

需要更新你项目中的每一件事 让我们从巴别塔7开始 .babelrc < / p >
{
"presets": ["@babel/preset-env"]
}

package.json中的一些变化

"scripts": {
+  "start:dev": "nodemon --exec babel-node -- ./src/index.js",
+  "start": "npm run build && node ./build/index.js",
+  "build": "npm run clean && babel src -d build -s --source-maps --copy-files",
+  "clean": "rm -rf build && mkdir build",
....
}
"devDependencies": {
+   "@babel/cli": "^7.0.0",
+   "@babel/core": "^7.6.4",
+   "@babel/node": "^7.0.0",
+   "@babel/polyfill": "^7.0.0",
+   "@babel/preset-env": "^7.0.0",
+   "nodemon": "^1.19.4"
....
}

并在起始点上使用import "@babel/polyfill"

import "@babel/polyfill"
import express from 'express'
const app = express()


//GET request
app.get('/', async (req, res) {
// await operation
res.send('hello world')
})
app.listen(4000, () => console.log('🚀 Server listening on port 400!'))

你在想为什么start:dev

< p >认真。如果你是新手,这是个好问题。每次改变你都是野猪与启动服务器的每一次 然后使用yarn start:dev作为开发服务器,每次更改自动重新启动服务器,以获得nodemon

的更多信息

我很惊讶esm没有被提到。这个小而强大的包允许你使用importrequire

在项目中安装esm

$ npm install --save esm

更新您的节点启动脚本以使用esm

node -r esm app.js

esm只是工作。我在.mjs--experimental-modules上浪费了大量的时间,却发现.mjs文件不能导入使用requiremodule.exports的文件。这是一个大问题,而esm允许你混合和匹配,它只是解决它…esm只是工作。

我要在最初的问题中解决另一个问题,没有人问过这个问题。最近在我自己的NodeJS项目中从CommonJS转换到ESM后,我很少看到关于你不能像require那样把导入放在你想要的任何地方的讨论。我的项目现在使用导入工作得很好,但是当我使用问题中的代码时,我首先得到一个没有命名函数的错误。命名函数后,我收到以下…

import express from 'express'
^^^^^^^


SyntaxError: Unexpected identifier
at Loader.moduleStrategy (internal/modules/esm/translators.js:88:18)

您不能像需要的那样在函数中导入。它们必须放在文件的顶部,在代码块之外。我自己在这个问题上也浪费了不少时间。

因此,虽然上面所有的答案都能很好地帮助您在项目中导入,但没有一个能解决原始问题中的代码不能像编写的那样工作的问题。

只需安装更高版本的Node。直到Node v10 es6不支持。您需要禁用一些标志或使用

自版本14起,Node的稳定版本支持import语句。x LTS。

你所需要做的就是在package.json中指定"type": "module"

我的项目使用节点v10.21.0,它仍然不支持ES6 import关键字。有多种方法可以让节点识别import,其中之一是用node --experimental-modules index.mjs开始节点(这里的一个答案已经涵盖了mjs扩展名)。但是,这样,你就不能在你的代码中使用特定于节点的关键字,比如require。如果需要同时使用nodejs的require关键字和ES6的import,那么解决方法是使用esm npm包。在添加esm包作为依赖项后,节点需要使用特殊配置启动,例如:node -r esm index.js

我一直想把它修好。以下是有效的方法:

  1. 使用最新的节点版本。我使用的是v14.15.5。运行:node——version来验证你的版本
  2. 命名文件,使它们都以.mjs而不是.js结尾

例子:

mod.mjs

export const STR = 'Hello World'

test.mjs

import {STR} from './mod.mjs'
console.log(STR)

运行:节点test.mjs

你应该看到“Hello world”。