Node.js - SyntaxError: การนำเข้าโทเค็นที่ไม่คาดคิด


443

ฉันไม่เข้าใจสิ่งที่ผิด โหนด 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

4
ใช้ transpiler เช่น Babel เพื่อใช้ import ใน Nodejs เพราะมันไม่ได้รับการสนับสนุนใน nodejs.There เป็นทางเลือกที่ดีที่สุดในการนำเข้าคือต้องใช้มัน
BHUVNESH KUMAR

คำตอบ:


484

อัพเดต 3:ตั้งแต่โหนด 13คุณสามารถใช้ส่วนขยาย. mjs หรือตั้งค่า "type": "module" ใน package.json ของคุณ คุณไม่จำเป็นต้องใช้--experimental-modulesธง

อัพเดต 2:ตั้งแต่โหนด 12คุณสามารถใช้.mjsส่วนขยายหรือตั้งค่า"type": "module"ใน package.json ของคุณ และคุณต้องเรียกใช้โหนดด้วยการ--experimental-modulesตั้งค่าสถานะ

อัปเดต:ในโหนด 9จะเปิดใช้งานอยู่หลังการตั้งค่าสถานะและใช้.mjsส่วนขยาย

node --experimental-modules my-app.mjs

แม้ว่าimportจะเป็นส่วนหนึ่งของ ES6 แต่ก็ยังไม่ได้รับการสนับสนุนใน NodeJS โดยค่าเริ่มต้นและมีการสนับสนุนในเบราว์เซอร์เมื่อเร็ว ๆ นี้เท่านั้น

ดูเบราว์เซอร์ compat ตาราง MDNและปัญหาโหนดนี้

จากการอัปเดตของ James M Snell สำหรับโมดูล ES6 ใน Node.js (กุมภาพันธ์ 2017):

งานอยู่ในระหว่างดำเนินการ แต่จะใช้เวลาสักครู่ - ขณะนี้เรากำลังดูอย่างน้อยปีหนึ่ง

คุณจะต้องใช้requireคำสั่งแบบคลาสสิคต่อไปก่อน

const express = require("express");

หากคุณต้องการใช้คุณสมบัติ ES6 / 7 ใหม่ใน NodeJS คุณสามารถรวบรวมได้โดยใช้ Babel นี่คือตัวอย่างเช่นเซิร์ฟเวอร์


2
ไม่มีใครรู้ว่าโหนด 10 จะมาพร้อมกับการสนับสนุนการเปิดใช้งานโดยค่าเริ่มต้น? (กำหนดเปิดตัวในเดือนหน้า)
Hartmut

2
@Scimonster ...... โหนด --experimental-modules my-app.mjs (โหนด: 12176) ExperimentalWarning: ตัวโหลดโมดูล ESM กำลังทำการทดลอง {ข้อผิดพลาด: ไม่พบโมดูล /C:/Users/WittyParrot/Documents/card-test-project/src/my-app.mjs ที่การค้นหา (ภายใน / โมดูล / esm / DefaultResolve.js: 23: 12) การทดสอบโครงการ / src / my-app.mjs ที่การค้นหา (ภายใน / modules / esm / DefaultResolve.js: 23: 12) .... การส่งคำเตือนไม่พบ my-app.js .... โปรดแนะนำ .... i โหนดที่ติดตั้งเวอร์ชัน 9.11.1
Leo

52
น่าผิดหวังเพราะบทเรียนส่วนใหญ่นอกนั้นพูดถึงการใช้การนำเข้า แต่แทบจะไม่ได้รับการสนับสนุนเลย (ฉันต้องการชีวิตของฉันกลับมา 2 ชั่วโมง)
kiwicomb123

9
@ChaimEliyah: มีปัญหาเดียวกันในโหนด v11.0.0
whoami

5
ยังคงต้องการแฟล็ก
ABabin

60

แต่น่าเสียดายที่ Node.js ไม่สนับสนุน ES6 เป็นimportเลย

เพื่อให้บรรลุสิ่งที่คุณพยายามจะทำ (นำเข้าโมดูล Express) รหัสนี้ควรจะเพียงพอ

var express = require("express");

ตรวจสอบให้แน่ใจว่าคุณได้ติดตั้ง Express ด้วยการเรียกใช้

$ npm install express

ดูเอกสาร Node.jsสำหรับข้อมูลเพิ่มเติมเกี่ยวกับการเรียนรู้ Node.js


8
importไม่จำเป็นต้องเป็นคุณสมบัติของ TypeScript TypeScript คือ ES6 ที่มีการพิมพ์ ดังนั้นสิ่งที่ชอบการนำเข้าคือ ES6 ดั้งเดิม
borislemke

@borislemke จริงฉันตีความ OP ผิดเล็กน้อย :) ฉันจะเปลี่ยนมัน
baranskistad

สวัสดีฉันติดตั้งด่วน แต่ในสคริปต์ของไฟล์ package.json เราควรเขียนอะไรดี ถ้าฉันเขียน "สคริปต์": {"start": "node index.js"} ดังนั้นมันควรจะแสดงข้อผิดพลาดเดียวกัน โปรดช่วยฉันด้วย
Ravi Shah

node index.jsการทำงานสำหรับฉัน แต่เมื่อฉันเรียกฉันยังได้รับnode dist/main.js Unexpected token import
TheFox

@TheFox คุณอาจมีการนำเข้าในไฟล์นั้น เพียงเพราะคุณindex.jsกำลังผ่านไม่ได้หมายความว่าคุณdist/main.jsจะผ่านเช่นกัน
baranskistad

34

ดังที่กล่าวไว้ในคำตอบอื่น ๆ โหนด JS ปัจจุบันไม่รองรับการนำเข้า ES6

(ณ ตอนนี้อ่านแก้ไข 2)

เปิดใช้งานการนำเข้า ES6 ในโหนด jsเสนอวิธีแก้ไขปัญหานี้ ฉันได้ลองแล้วและมันก็ใช้ได้ผลสำหรับฉัน

เรียกใช้คำสั่ง:

    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โดยใช้คำสั่งnpm install babel-preset-env --saveแล้วติดตั้งbabel-cliโดยใช้คำสั่ง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 ฉันไม่ได้ทำงานกับอิเล็กตรอน แต่ผมพบว่าสิ่งที่คล้ายกับปัญหาของจาวาสคริปต์ - วิธีการตั้งค่าเริ่มต้น NPM สำหรับแอปอิเล็กตรอนด้วย 'Babel โหนด --presets es2015 เวที-3' หวังว่ามันจะช่วยได้
Neerali Acharya

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

มีคำตอบก่อนคำตอบของฉันซึ่งมีคำอธิบาย แต่สำหรับ clarification Node ไม่รองรับไวยากรณ์ ES6 เมื่อคุณพูดนำเข้า ... คุณกำลังใช้ไวยากรณ์ ES6
supritshah1289

22

ฉันช็อคesmไม่ได้ถูกพูดถึง แพคเกจนี้มีขนาดเล็ก แต่ยิ่งใหญ่ช่วยให้คุณสามารถที่จะใช้อย่างใดอย่างหนึ่งหรือimportrequire

ติดตั้ง esm ในโครงการของคุณ

$ npm install --save esm

อัพเดต Node Start Script ของคุณเพื่อใช้ esm

node -r esm app.js

esmเพิ่งได้ผล ผมเสียเวลาตันด้วย.mjsและ--experimental-modulesเพียงเพื่อหา.mjsไฟล์ไม่สามารถนำเข้าไฟล์ที่ใช้หรือrequire module.exportsนี่เป็นปัญหาใหญ่ในขณะที่esmช่วยให้คุณสามารถผสมผสานและจับคู่และเป็นเพียงตัวเลขออกมา ... esmแค่ได้ผล


17

ในกรณีที่คุณยังไม่สามารถใช้ "นำเข้า" นี่คือวิธีที่ฉันจัดการมัน: เพียงแปลมันเป็นโหนดที่ต้องการความเป็นมิตร ตัวอย่าง:

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

เหมือนกับ:

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

4
ไม่เป็นความจริงหากคุณเป็น (ตามที่เป็นไปได้ในกรณีนี้) โดยใช้exportคำหลัก
Daniel Thompson

@DanielThompson ขออภัยหากนี่เป็นความเข้าใจที่ผิดฉันแค่ให้วิธีแก้ปัญหาสำหรับกรณีนี้ถ้าคุณทำงานโดยไม่มีexportคำสำคัญเอาล่ะขอบคุณสำหรับบันทึกที่เป็นประโยชน์ของคุณ!
Alberto

ทำงานให้ฉัน ขอบคุณ
Ali Azhar

11

ข้อเสนอบาเบล 7 คุณสามารถเพิ่มการอ้างอิงของ dev

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

และเพิ่ม .abelabel ในรูท

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

และเพิ่มลงในไฟล์. js

require("@babel/register")

หรือถ้าคุณเรียกใช้ใน cli คุณสามารถใช้ require hook เป็น -r @ babel / register เช่น

$node -r @babel/register executeMyFileWithESModules.js

1
การติดตั้ง @ babel / preset-env และเพิ่มลงใน. babelrc ทำให้มีเคล็ดลับ ไม่จำเป็นต้องใช้ @ babel / register plugin ในกรณีของฉัน
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 ( E CMA S cript M odules odules) ใน Node.js (สำหรับไฟล์มี วิธีที่สามสำหรับ evaling สตริง) นี่คือสิ่งที่เอกสารพูดว่า:

การ--experimental-modulesตั้งค่าสถานะสามารถใช้เพื่อเปิดใช้งานการสนับสนุนสำหรับโมดูล ECMAScript (โมดูล ES)

เมื่อเปิดใช้งานแล้ว Node.js จะถือว่าสิ่งต่อไปนี้เป็นโมดูล ES เมื่อถูกส่งผ่านไปยัง nodeอินพุตเริ่มต้นหรือเมื่ออ้างอิงโดยimportคำสั่งภายในรหัสโมดูล ES:

  • ไฟล์ที่ลงท้าย.mjsด้วย

  • ไฟล์ที่สิ้นสุดใน.jsหรือไฟล์ extensionless เมื่อผู้ปกครองที่ใกล้ที่สุด package.jsonไฟล์ประกอบด้วยเขตข้อมูลระดับบนสุดที่มีค่าของ"type" "module"

  • สตริงที่ส่งผ่านเป็นอาร์กิวเมนต์ไปยัง--evalหรือ--printหรือถูกไพพ์ไปยัง nodeผ่านSTDINด้วยแฟล็--input-type=module

Node.js จะถือว่าเป็น CommonJS รูปแบบการป้อนข้อมูลอื่น ๆ ทั้งหมดเช่น.jsไฟล์ที่ไฟล์พาเรนต์ที่ใกล้ที่สุดpackage.jsonไม่มี"type" ฟิลด์ระดับบนสุดหรืออินพุตสตริงโดยไม่มีแฟล็--input-typeก พฤติกรรมนี้คือการรักษาความเข้ากันได้ย้อนหลัง อย่างไรก็ตามในตอนนี้ Node.js รองรับทั้งโมดูล CommonJS และ ES จึงเป็นการดีที่สุดที่จะต้องมีความชัดเจนเมื่อใดก็ตามที่เป็นไปได้ Node.js จะปฏิบัติต่อไปนี้เป็น CommonJS เมื่อส่งผ่านไปnodeเป็นอินพุตเริ่มต้นหรือเมื่ออ้างอิงโดยimportคำสั่งภายในรหัสโมดูล ES:

  • ไฟล์ที่ลงท้าย.cjsด้วย

  • ไฟล์ที่สิ้นสุดใน.jsหรือไฟล์ extensionless เมื่อผู้ปกครองที่ใกล้ที่สุด package.jsonไฟล์ประกอบด้วยเขตข้อมูลระดับบนสุดที่มีค่าของ"type" "commonjs"

  • สตริงที่ส่งผ่านเป็นอาร์กิวเมนต์ไปยัง--evalหรือ--printหรือถูกไพพ์ไปยัง nodeผ่านSTDINด้วยแฟล็--input-type=commonjs


3

เมื่อฉันเริ่มต้นด้วยด่วนต้องการโซลูชั่นที่จะใช้นำเข้าแทนต้องการ

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

หลายครั้งที่ต้องผ่านสายนี้: - Unfortunately, Node.js doesn't support ES6's import yet.

ตอนนี้เพื่อช่วยเหลือผู้อื่นฉันสร้างสองโซลูชั่นใหม่ที่นี่

1) esm : -

ตัวโหลดโมดูล ECMAScript ที่เรียบง่ายแบบ babel-less, bundle-less มาทำให้มันใช้งานได้

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

Oooh ไม่เราสร้างปัญหาใหม่

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

ข้อผิดพลาดนี้เกิดขึ้นเมื่อคุณใช้ async / รอคอยในรหัสของคุณ จากนั้นใช้ polyfill ที่รวมรันไทม์ของตัวกำเนิดที่กำหนดเองและ core-js เพิ่มที่ด้านบนของindex.js

import "babel-polyfill"

อนุญาตให้คุณใช้ async / คอย

ใช้Babel 7

ต้องอัปเดตทุกสิ่งในโครงการของคุณให้เริ่มด้วย babel 7 .babelrc

{
  "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": []
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.