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


441

我不明白怎么了。节点v5.6.0 NPM v3.10.6

编码:

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

3
使用像Babel这样的transpiler来在Node.js中使用导入,因为Node.js本身不支持它。
BHUVNESH KUMAR

Answers:


481

更新3:Node 13开始,您可以使用.mjs扩展名,也可以在package.json中设置“ type”:“ module”。你并不需要使用--experimental-modules标志。

更新2:Node 12开始,您可以使用.mjs扩展名,也可以"type": "module"在package.json中进行设置。并且您需要运行带有--experimental-modules标志的节点。

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

node --experimental-modules my-app.mjs

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

请参阅有关MDN的浏览器兼容表以及此Node问题

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

工作正在进行中,但将需要一些时间-我们目前至少需要一年左右的时间。

在本机显示支持之前,您必须继续使用经典require语句:

const express = require("express");

如果您确实想在NodeJS中使用ES6 / 7的新功能,则可以使用Babel对其进行编译。这是一个示例服务器


2
有谁知道默认情况下节点10是否会附带支持?(由于将于下个月首次亮相)
Hartmut

2
@Scimonster ......节点--experimental-modules my-app.mjs(node:12176)实验警告:ESM模块加载器是实验性的。{错误:在搜索时找不到模块/C:/Users/WittyParrot/Documents/card-test-project/src/my-app.mjs(内部/模块/esm/DefaultResolve.js:23:12)test-project/ src / my-app.mjs处于搜索状态(内部/模块/esm/DefaultResolve.js:23:12)....抛出警告找不到my-app.js ....请建议.... i已安装的节点版本9.11.1
Leo

51
令人沮丧的是,那里的大多数教程都在谈论使用导入,但是几乎没有对此的支持。(我希望一生恢复2小时,哈哈)
kiwicomb123

9
@ChaimEliyah:在节点v11.0.0中遇到了相同的问题
whoami


60

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

要完成您要尝试执行的操作(导入Express模块​​),此代码就足够了

var express = require("express");

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

$ npm install express

有关学习Node.js的更多信息, Node.js文档


8
import不一定是TypeScript的功能。TypeScript是具有键入功能的ES6。因此,诸如import之类的东西是ES6本机的。
borislemke '16

@borislemke是的,我确实解释了OP有点错误。:)我将其更改。
baranskistad

嗨,我安装了express但在package.json文件的脚本中我们应该写什么?如果我写“ scripts”:{“ start”:“ node index.js”}然后应该显示相同的错误。请帮我。
拉维·沙

node index.js为我工作,但是当我跑步时node dist/main.js我也会得到Unexpected token import
TheFox

@TheFox您可能在该文件中有导入。仅仅因为您index.js过去了并不意味着您dist/main.js也将过去。
baranskistad '18

34

如其他答案所述,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')

现在,您可以编写导入语句而不会出现任何错误。

希望这可以帮助。

编辑:

您需要运行使用上述代码创建的新文件。就我而言config.js。因此,我必须运行:

    node config.js

编辑2:

在进行实验时,我找到了解决此问题的简单方法。

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

添加以下内容(以及您需要的任何其他babel预设,都可以在此文件中添加):

    {
        "presets": ["env"]
    }

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

现在,转到服务器或索引文件所在的文件夹并使用以下命令运行:babel-node fileName.js

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

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

我该如何用电子做到这一点?我是这样尝试的:"start": "babel-node electron .", 但是没有运气
tpbafk

2
@tpbafk我还没有研究电子。但是我发现了与您的问题javascript类似的东西-如何使用'babel-node --presets es2015,stage-3'为电子应用设置npm start。希望对您
有所

33

错误: 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;


1
我希望您能再解释一下出口默认部分。我在那部分上有麻烦。导入非常适合您的答案。
JoeGalind

在我的答案之前有一个答案,里面有一个解释。但是为了澄清起见,Node不支持ES6语法。当您说导入...时,您正在使用ES6语法
supritshah1289 '18

20

esm没有被提及感到震惊。这个小巧但功能强大的软件包允许您使用importrequire

在您的项目中安装esm

$ npm install --save esm

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

node -r esm app.js

esm正常工作。我浪费的时间TON与.mjs--experimental-modules只找出一个.mjs文件无法导入文件使用requiremodule.exports。这是一个很大的问题,但是esm您可以混合搭配,就可以解决问题了esm


17

如果仍然不能使用“导入”,这就是我的处理方式:只需将其转换为对节点友好的需求即可。例:

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

是相同的:

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

4
如果您(可能是)使用export关键字
Daniel Thompson

@DanielThompson抱歉,这可能会引起误解,我只是在这种情况下提供一种解决方法,如果您没有使用export关键字,那么无论如何,感谢您的帮助!
艾伯托

为我工作。谢谢
Ali Azhar

11

babel 7提案 可以添加开发依赖吗

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,例如。

$node -r @babel/register executeMyFileWithESModules.js

1
安装@ babel / preset-env并将其添加到.babelrc中就可以了。在我的情况下,不需要@ babel / register插件。
Marcos R

8

如果可以使用“ babel”,请尝试在package.json(-presets = es2015)中添加构建脚本,如下所示。它可以将导入代码预编译到es2015

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

但是我打来的电话会npm start先执行“构建”还是先执行“开始”?(当前定义开始时间:"nodemon src/app.js --exec \"npm run lint && node\"",
pashute

如果我运行此cmd,则表明服务器不存在错误
kumaresan_sd

6

随着Node.js的V12的(这是现在可能还算稳定,但仍标有“实验性”),你有两个选择使用ESM(ē CMA 小号 CRIPT 中号在Node.js的odules)(的文件,有一个逃避字符串的第三种方法),这就是文档所说的内容:

--experimental-modules标志可用于启用对ECMAScript模块(ES模块)的支持。

启用后,Node.js在node作为初始输入传递给ES模块时,或import在ES模块代码中的语句引用时,会将以下模块 视为ES模块:

  • 以结尾的文件.mjs

  • .js当最近的父package.json文件包含"type"值为的顶级字段时,以 结尾的文件或无扩展名的文件 "module"

  • 带有标志的字符串作为参数传递给--eval或通过--print管道传递给 nodevia 。STDIN--input-type=module

Node.js将所有其他形式的输入视为CommonJS,例如,.js最近的父package.json文件不包含顶级文件的文件"type" 字段的文件,或者不带flag的字符串输入--input-type。此行为是为了保持向后兼容性。但是,既然Node.js同时支持CommonJS和ES模块,那么最好尽可能地做到明确。当node作为初始输入传递或被importES模块代码中的语句引用时,Node.js将把以下内容视为CommonJS :

  • 以结尾的文件.cjs

  • .js当最近的父package.json文件包含顶级字段时,以或无扩展名的文件结尾的文件 "type"值为的,以 "commonjs"

  • 带有标志的字符串作为参数传递给--eval或通过--print管道传递给 nodevia 。STDIN--input-type=commonjs


3

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

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

很多时间走这条线:- Unfortunately, Node.js doesn't support ES6's import yet.

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

1)esm:-

极为简单,无babel,无捆绑的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)Babel js:-

这可以分为2部分

a)解决方案1感谢timonweb.com

b)解决方案2

使用Babel 6babel-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"

这使您可以使用异步/等待

使用Babel 7

需要更新项目中的所有内容,让我们从babel 7开始。

{
  "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

说真的 如果您是新手,这是一个很好的问题。每次您都对启动服务器无所适从的yarn start:dev每个变更,然后自动将每个变更作为重新启动服务器用作开发服务器,以获取关于nodemon的更多信息


2

就我而言,它是在照管.babelrc文件,并且应包含以下内容:

{
  "presets": ["es2015-node5", "stage-3"],
  "plugins": []
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.