รับโทเค็นการส่งออกที่ไม่คาดคิด


221

ฉันพยายามเรียกใช้รหัส ES6 ในโครงการของฉัน แต่ฉันได้รับข้อผิดพลาดในการส่งออกโทเค็นที่ไม่คาดคิด

export class MyClass {
  constructor() {
    console.log("es6");
  }
}

5
มีข้อมูลไม่เพียงพอเกี่ยวกับสภาพแวดล้อมหรือการกำหนดค่าของคุณเพื่อให้ความช่วยเหลือใด ๆ ข้อผิดพลาดนี้แนะนำว่า webpack หรือ babel ทำงานไม่ถูกต้องเนื่องจากexportมีเฉพาะใน ES6 และโมดูลเหล่านั้นเป็นสิ่งที่ให้การสนับสนุน ES6
Claies

24
คุณควรใช้module.exports = MyClassไม่ใช่export class MyClass
onmyway133

คำตอบ:


249

คุณกำลังใช้ไวยากรณ์โมดูล ES6

นี่หมายความว่าสภาพแวดล้อมของคุณ (เช่น node.js) ต้องรองรับไวยากรณ์ของโมดูล ES6

NodeJS ใช้ไวยากรณ์ CommonJS Module ( module.exports) ไม่ใช่ไวยากรณ์โมดูล ES6 (exportคำหลัก)

สารละลาย:

  • ใช้ babelแพ็คเกจ npm เพื่อโอน ES6 ของคุณไปยังcommonjsเป้าหมาย

หรือ

  • Refactor ด้วยไวยากรณ์ CommonJS

ตัวอย่างของไวยากรณ์ CommonJS คือ (จากflaviocopes.com/commonjs/ ):

  • exports.uppercase = str => str.toUpperCase()
  • exports.a = 1

15
เมื่อใดที่ nodejs จะให้การสนับสนุนอย่างเป็นทางการimport? ฉันคิดว่า v10.0.0 น่าจะมี แต่ไม่ชัด
chovy

4
การสนับสนุนการทดลอง @chovy สามารถใช้ได้กับแฟล็ก "--experimental-modules" ไฟล์ต้องมีนามสกุล. mjs
Giovanni P.

1
ฉันได้รับข้อผิดพลาดนี้โดยใช้ Chrome 66 พร้อมการสนับสนุนดั้งเดิมสำหรับโมดูล
Tom Russell

BTW: ทราบว่าในขณะที่โมดูล node10 / การสนับสนุนอยู่เบื้องหลัง node12 ธงพวกเขาไม่สนับสนุนในโหมด REPL - แต่มันได้รับการสนับสนุนในโหมด EVAL ใน node12
jakub.g

2
สำหรับบางคนยังไม่ชัดเจนเกี่ยวกับไวยากรณ์ CommonJs กรุณาชำระเงินลิงค์นี้อาจช่วยเล็กน้อย flaviocopes.com/commonjs
LT

142

ในกรณีที่คุณได้รับข้อผิดพลาดนี้อาจเกี่ยวข้องกับวิธีที่คุณรวมไฟล์ javascript ไว้ในหน้า html ของคุณ เมื่อโหลดโมดูลคุณต้องประกาศไฟล์เหล่านั้นอย่างชัดเจน นี่คือตัวอย่าง:

//module.js:
function foo(){
   return "foo";
}

var bar = "bar";

export { foo, bar };

เมื่อคุณรวมสคริปต์เช่นนี้:

<script src="module.js"></script>

คุณจะได้รับข้อผิดพลาด:

Uncaught SyntaxError: การส่งออกโทเค็นที่ไม่คาดคิด

คุณต้องรวมไฟล์ด้วยแอตทริบิวต์ type ที่ตั้งค่าเป็น "module":

<script type="module" src="module.js"></script>

จากนั้นจะทำงานตามที่คาดไว้และคุณพร้อมที่จะนำเข้าโมดูลของคุณในโมดูลอื่น:

import { foo, bar } from  "./module.js";

console.log( foo() );
console.log( bar );

37
แตกต่างจากคำตอบ "สุดขั้ว" นี้แก้ปัญหาได้จริงและอธิบายว่าทำไมมันเกิดขึ้นโดยไม่แนะนำว่าตัวเลือกเดียวคือใช้ประโยชน์จากวิธี CommonJS วิธี APM หรือ transpile รหัสของเรา ... นี่จะเป็นข้อยกเว้น สำหรับมาตรฐาน w3c ซึ่งtypeคาดว่าจะเป็นประเภท mime ที่ถูกต้อง (aka. media type) ดังนั้นนี่จึงเป็นการค้นพบที่ไม่คาดคิด ขอบคุณ!
Shaun Wilson

4
วิธีนี้แก้ไขข้อผิดพลาด แต่ฉันได้รับ "โทเค็นที่ไม่คาดคิด {" ในบรรทัดคำสั่งนำเข้าใน Chrome 67 พร้อมสคริปต์ที่อยู่ในบรรทัดเช่น <script> นำเข้า ... </script>
PandaWood

1
@PandaWood คุณต้องใช้<script type="module">import ...</script>เมื่อคุณนำเข้าจากโมดูล ฉันทดสอบใน Chromium รุ่นล่าสุด
Vladimir S.

สิ่งนี้แก้ไขปัญหาของฉัน :)
user3651476

Pure JS (ES6) รองรับการนำเข้าและสิ่งนี้อธิบายได้อย่างชัดเจนว่าทำไมฉันถึงพบสิ่งนี้
Eric

16

สองเซ็นต์ของฉัน

ส่งออก

ES6

myClass.js

export class MyClass1 {
}
export class MyClass2 {
}

other.js

import { MyClass1, MyClass2 } from './myClass';

CommonJS Alternative

myClass.js

class MyClass1 {
}
class MyClass2 {
}
module.exports = { MyClass1, MyClass2 }
// or
// exports = { MyClass1, MyClass2 };

other.js

const { MyClass1, MyClass2 } = require('./myClass');

ส่งออกค่าเริ่มต้น

ES6

myClass.js

export default class MyClass {
}

other.js

import MyClass from './myClass';

CommonJS Alternative

myClass.js

module.exports = class MyClass1 {
}

other.js

const MyClass = require('./myClass');

หวังว่านี่จะช่วยได้


สำหรับตัวอย่างการส่งออกเริ่มต้นของ ES6 คุณเขียนว่า "การส่งออกเริ่มต้น" แต่ควรเป็น "การส่งออกเริ่มต้น"
IAM_AL_X

@IAM_AL_X ขอบคุณสำหรับการจับ :-)
Barnstokkr

10

เพื่อใช้เพิ่ม ES6 babel-preset-env

และใน.babelrc:

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

ตอบกลับการอัปเดตด้วยความคิดเห็น @ghanbari เพื่อใช้ babel 7


8
คำถามของเขาไม่เกี่ยวกับการอธิบายบาเบล เหตุใดจึงควรตอบสิ่งที่ไม่ต้องการซึ่งอาจทำให้คนอื่นสับสน
Jalal

7
@monsto คำถามนี้ถูกแท็กbabelโดยผู้เขียนแล้ว ในขณะที่คำตอบของ Phil Ricketts จะทำให้ปัญหาชัดเจนขึ้นซึ่งเป็นสิ่งที่ดีคำตอบนี้เป็นวิธีการแก้ปัญหาของผู้เขียนโดยตรง
boycy

"@ babel / preset-env"
ghanbari

6

ไม่จำเป็นต้องใช้ Babel ในขณะนี้ (JS มีประสิทธิภาพมาก) เมื่อคุณสามารถใช้การส่งออกโมดูล JavaScript เริ่มต้นได้ ตรวจสอบการสอนเต็มรูปแบบ

Message.js

module.exports = 'Hello world';

app.js

var msg = require('./Messages.js');

console.log(msg); // Hello World

2
แล้วคุณจะส่งออกชั้นเรียนได้อย่างไร?
Sherwin Ablaña Dapito

1
ฉันกำลังลบคำตอบของฉันเนื่องจากคำถามนี้เป็นจริงสำหรับ ES6 ไม่ใช่ CommonJS ที่ NodeJS ใช้ โปรดตรวจสอบคำตอบข้างต้น
Alvin Konda

@ SherwinAblañaDapito module.exports = คลาส MyClass {} ทำงาน
Marian Klühspies

3

ติดตั้งแพคเกจ babel @babel/coreและ@babel/presetจะแปลง ES6 ไปยังเป้าหมาย commonjs เนื่องจากโหนด js ไม่เข้าใจเป้าหมาย ES6 โดยตรง

npm install --save-dev @babel/core @babel/preset-env

จากนั้นคุณต้องสร้างไฟล์กำหนดค่าหนึ่งไฟล์ที่มีชื่อ.babelrcในไดเรกทอรีรากของโครงการและเพิ่มรหัสนี้ที่นั่น

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


ฉันยังจำเป็นในการติดตั้ง @ Babel / ลงทะเบียนมิฉะนั้นผมก็ยังจะได้รับ "SyntaxError: ไม่สามารถใช้คำสั่งนำเข้านอกโมดูล"
โมเลกุล

3

ฉันแก้ไขสิ่งนี้โดยทำไฟล์จุดเข้าใช้งานเช่น

// index.js
require = require('esm')(module)
module.exports = require('./app.js')

และไฟล์ใด ๆ ที่ฉันนำเข้ามาapp.jsและอื่น ๆ ทำงานร่วมกับimports/exports ตอนนี้คุณเพียงแค่เรียกใช้เช่นnode index.js

หมายเหตุ: หากมีการapp.jsใช้export defaultสิ่งนี้จะกลายเป็นrequire('./app.js').defaultเมื่อใช้ไฟล์ entry point


1
คำตอบที่ดีที่สุดสำหรับโครงการง่าย ๆ ที่ไม่จำเป็นต้องใช้ babel, webpack, พัสดุ ฯลฯ ... ฉันใช้ในโครงการ monorepo ด้วยง่าย / เซิร์ฟเวอร์ด่วนสำหรับโครงการ ทำงานเหมือนจับใจ ...
mattdlockyer

-3

การใช้ไวยากรณ์ ES6 ไม่ทำงานในโหนดโชคไม่ดีที่คุณต้องมี Babel เพื่อทำให้คอมไพเลอร์เข้าใจไวยากรณ์เช่นการส่งออกหรือนำเข้า

npm install babel-cli --save

ตอนนี้เราจำเป็นต้องสร้างไฟล์ .abelrc ในไฟล์ babelrc เราจะตั้งค่า babel ให้ใช้ preset es2015 ที่เราติดตั้งเป็น preset เมื่อทำการคอมไพล์เป็น ES5

ที่รากของแอพของเราเราจะสร้างไฟล์ .abelrc $ npm ติดตั้ง babel-preset-es2015 - บันทึก

ที่รากของแอพของเราเราจะสร้างไฟล์ .abelrc

{  "presets": ["es2015"] }

หวังว่ามันจะทำงาน ... :)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.