NodeJS วางแผนที่จะสนับสนุนโมดูลนำเข้า / ส่งออก es6 (es2015)


275

ฉันดูทั่วอินเทอร์เน็ตโดยไม่มีคำตอบที่ชัดเจนสำหรับเรื่องนี้

ปัจจุบัน NodeJS ใช้เฉพาะ CommonJS syntax เพื่อโหลดโมดูลและถ้าคุณต้องการใช้ไวยากรณ์โมดูล ES2015 จริงๆคุณต้อง transpile มาก่อนหรือใช้ตัวโหลดโมดูลภายนอกตอนรันไทม์

ปัจจุบันฉันยังไม่มั่นใจที่จะใช้วิธีใดวิธีหนึ่งจากสองวิธีนี้ผู้ดูแลระบบ NodeJS วางแผนที่จะสนับสนุนโมดูล ES2015 หรือไม่? ฉันไม่พบคำใบ้เกี่ยวกับเรื่องนี้เลย

ในขณะนี้ NodeJS 6.x อ้างว่าสนับสนุนคุณสมบัติ 96% ของ ES2015 แต่ไม่มีการอ้างอิงถึงโมดูลใด ๆ ( ลิงก์สนับสนุน NodeJS ES2105 )

คุณรู้หรือไม่ว่า NodeJS จะสนับสนุนโมดูลเหล่านี้นอกกรอบในอนาคตอันใกล้


2
Googling สำหรับnode es2015 modulesการแสดงต่อไปนี้เป็นหนึ่งในผลด้านบน: github.com/nodejs/node/wiki/ES6-Module-Detection-in-Node
เฟลิกซ์

6
โดยส่วนตัวแล้วฉันจะลงคะแนนให้ปิดคำถามนี้ว่า "แปลเป็นภาษาท้องถิ่นมากเกินไป" แต่เหตุผลที่ปิดนั้นไม่มีอยู่อีกต่อไป สมมติว่า Node สามารถใช้งานโมดูล ES6 ได้ในวันพรุ่งนี้ คุณจะลบคำถามของคุณแล้วเพราะมันไม่เกี่ยวข้องอีกต่อไป? หรืออย่างน้อยคุณจะปรับปรุงหรือไม่ ฉันไม่คิดว่าคำถามเหมาะสำหรับ SO หากคุณรู้อยู่แล้วว่าจะล้าสมัยหรือต้องการอัปเดต "เร็ว ๆ นี้" แต่นั่นเป็นเพียงความคิดเห็นของฉันและดูเหมือนว่าจะมีคนอื่น ๆ ที่คิดว่าตรงกันข้ามซึ่งก็โอเคสำหรับฉัน :) (fwiw โดยตัวเองคำถามคือหลักสูตรที่สำคัญและน่าสนใจ)
เฟลิกซ์ Kling

2
ฉันหวังว่าจะมีสถานที่ใน Stack Universe สำหรับคำถามเช่นนี้แม้ว่า มันอาจจะไม่เหมาะกับทางเทคนิคที่นี่ แต่ฉันไม่รู้ว่าฉันเห็นด้วยว่ามันเป็น "ความคิดเห็นตาม" จริงๆ OP กำลังมองหาคำตอบเฉพาะสำหรับคำถามที่เฉพาะเจาะจง แต่คำตอบที่ล้าสมัย (ในบางจุด)
Wonko the Sane

5
การใช้ถ้อยคำทางเลือกของคำถามนี้: "สถานะของ node.js รองรับโมดูล ES6 คืออะไร" คำตอบของคำถาม SO มากมายเปลี่ยนไปตามกาลเวลาเมื่อเทคโนโลยีวิวัฒนาการ ฉันก็มีปัญหาในการหาคำตอบจนกระทั่งฉันลงที่นี่
Joe Lapp

4
@ FelixKling ฉันเดาว่าคุณต้องการปิดคำถามนี้จะเป็นการตัดสินใจที่ผิดมากเพราะมันเป็นปัญหา 211 คนจนถึงขณะนี้พบว่าเป็นปัญหามากพอที่จะลงคะแนน
มูฮัมหมัดอูเมอ

คำตอบ:


302

โหนด 13.2.0 และสูงกว่า

NodeJS 13.2.0ขณะนี้สนับสนุนโมดูล ES โดยไม่มีการตั้งค่าสถานะ🎉อย่างไรก็ตามการนำไปใช้ยังคงถูกทำเครื่องหมายว่าเป็นการทดลองเพื่อใช้ในการผลิตด้วยความระมัดระวัง

หากต้องการเปิดใช้งานการสนับสนุน ESM ใน 13.2.0 ให้เพิ่มรายการต่อไปนี้ของคุณpackage.json:

{
  "type": "module"
}

ทั้งหมด.js,.mjs (หรือไฟล์โดยไม่ต้องขยาย) จะถือว่าเป็น ESM

มีตัวเลือกต่าง ๆ นอกเหนือจากการpackage.jsonเลือกใช้ทั้งหมดซึ่งมีรายละเอียดทั้งหมดในเอกสารประกอบสำหรับ 13.2.013.2.0

โหนด 13.1.0 และด้านล่าง

ผู้ที่ยังใช้ Node รุ่นเก่ากว่าอาจต้องการลองใช้ตัวโหลดโมดูลesmซึ่งเป็นการใช้งานพร้อมใช้งานของ ES Modules Spec สำหรับ NodeJS:

node -r esm main.js

การปรับปรุงโดยละเอียด ...

23 เมษายน 2019

เมื่อเร็ว ๆ นี้ฝ่ายประชาสัมพันธ์ได้ทำการเปลี่ยนวิธีตรวจพบโมดูล ES: https://github.com/nodejs/node/pull/26745

ยังคงอยู่หลังการ--experimental-modulesตั้งค่าสถานะ แต่มีการเปลี่ยนแปลงที่สำคัญในวิธีการโหลดโมดูล:

  • package.typeซึ่งสามารถเป็นได้ทั้งmoduleหรือcommonjs
    • type: "commonjs":
      • .js ถูกแยกวิเคราะห์เป็น commonjs
      • ดีฟอลต์สำหรับ entry point ที่ไม่มีส่วนขยายเป็น commonjs
    • type: "module":
      • .js ถูกแยกวิเคราะห์เป็น esm
      • ไม่รองรับการโหลด JSON หรือ Native Module โดยค่าเริ่มต้น
      • ค่าเริ่มต้นสำหรับจุดเริ่มต้นที่ไม่มีนามสกุลคือ esm
  • --type=[mode]เพื่อให้คุณตั้งค่าชนิดบนจุดเข้าใช้งาน จะแทนที่package.typeสำหรับจุดเข้า
  • .cjsนามสกุลไฟล์ใหม่
    • สิ่งนี้มีไว้เพื่อสนับสนุนการนำเข้า commonjs ในmoduleโหมด
    • นี่เป็นเฉพาะในตัวโหลด esm ตัวโหลด commonjs ยังคงไม่ถูกแตะต้อง แต่ส่วนขยายจะทำงานในตัวโหลดเก่าถ้าคุณใช้พา ธ ไฟล์แบบเต็ม
  • --es-module-specifier-resolution=[type]
    • ตัวเลือกคือexplicit(ค่าเริ่มต้น) และnode
    • ตามค่าเริ่มต้นตัวโหลดของเราจะไม่อนุญาตให้มีส่วนขยายเพิ่มเติมในการนำเข้าพา ธ สำหรับโมดูลจะต้องรวมส่วนขยายหากมี
    • ตามค่าเริ่มต้นโหลดเดอร์ของเราจะไม่อนุญาตให้นำเข้าไดเรกทอรีที่มีไฟล์ดัชนี
    • นักพัฒนาสามารถใช้--es-module-specifier-resolution=nodeเพื่อเปิดใช้งานอัลกอริทึมการแก้ปัญหาตัวระบุ commonjs
    • นี่ไม่ใช่ "คุณสมบัติ" แต่เป็นการใช้งานสำหรับการทดลอง คาดว่าจะมีการเปลี่ยนแปลงก่อนที่จะถูกลบธง
  • --experimental-json-loader
    • วิธีเดียวที่จะนำเข้า json เมื่อ "type": "module"
    • เมื่อเปิดใช้งานทั้งหมดimport 'thing.json'จะผ่านตัวโหลดการทดลองที่ไม่ขึ้นกับโหมด
    • ตามwhatwg / html # 4315
  • คุณสามารถใช้package.mainเพื่อตั้งค่าจุดเข้าใช้งานสำหรับโมดูล
    • นามสกุลไฟล์ที่ใช้ใน main จะได้รับการแก้ไขตามประเภทของโมดูล

17 มกราคม 2019

โหนด 11.6.0ยังคงแสดงรายการโมดูล ES ว่าเป็นการทดลองหลังแฟล็ก

13 กันยายน 2560

NodeJS 8.5.0ถูกวางจำหน่ายพร้อมการสนับสนุนไฟล์ mjs หลังการตั้งค่าสถานะ:

node --experimental-modules index.mjs

แผนการสำหรับสิ่งนี้คือการลบการตั้งค่าสถานะสำหรับการเปิดตัว v10.0 LTS

- ข้อมูลที่เผยแพร่แล้ว เก็บไว้ที่นี่เพื่อวัตถุประสงค์ทางประวัติศาสตร์ -

8 กันยายน 2560

สาขาหลักของ NodeJS ได้รับการปรับปรุงด้วยการสนับสนุนเริ่มต้นสำหรับโมดูล ESM:
https://github.com/nodejs/node/commit/c8a389e19f172edbada83f59944cad7cc802d9d5

ควรจะให้บริการในช่วงกลางคืนล่าสุด (สามารถติดตั้งผ่าน nvmเพื่อทำงานควบคู่กับการติดตั้งปัจจุบันของคุณ):
https://nodejs.org/download/nightly/

และเปิดใช้งานอยู่หลังการ--experimental-modulesตั้งค่าสถานะ:

package.json

{
  "name": "testing-mjs",
  "version": "1.0.0",
  "description": "",
  "main": "index.mjs" <-- Set this to be an mjs file
}

จากนั้นเรียกใช้:

node --experimental-modules .

กุมภาพันธ์ 2560:

https://medium.com/@jasnell/an-update-on-es6-modules-in-node-js-42c958b890c#.6ye7mtn37

พวก NodeJS ตัดสินใจว่าวิธีแก้ปัญหาที่แย่ที่สุดคือการใช้.mjsนามสกุลไฟล์ Takeaway จากนี้คือ:

ในคำอื่น ๆ ที่ได้รับสองไฟล์foo.jsและการbar.mjsใช้import * from 'foo'จะถือว่าfoo.jsเป็น CommonJS ในขณะที่import * from 'bar' จะถือว่าbar.mjsเป็นโมดูล ES6

และสำหรับไทม์ไลน์ ...

ณ จุดเวลาปัจจุบันยังคงมีจำนวนของข้อมูลจำเพาะและปัญหาการใช้งานที่ต้องเกิดขึ้นในด้าน ES6 และเครื่องเสมือนของสิ่งต่าง ๆ ก่อนที่ Node.js จะสามารถเริ่มต้นใช้งานการสนับสนุนโมดูล ES6 ได้ งานอยู่ในระหว่างดำเนินการ แต่จะใช้เวลาสักครู่ - ขณะนี้เรากำลังดูอย่างน้อยปีหนึ่ง

2559 ตุลาคม:

หนึ่งในผู้พัฒนาบน Node.JS เพิ่งเข้าร่วมการประชุม TC-39 และเขียนบทความที่ยอดเยี่ยมเกี่ยวกับตัวบล็อกเกอร์เพื่อนำไปใช้กับ Node.JS:

https://hackernoon.com/node-js-tc-39-and-modules-a1118aecf95e

พื้นฐานการจากไปคือ:

  • โมดูล ES ได้รับการวิเคราะห์แบบคงที่ CommonJS ได้รับการประเมิน
  • โมดูล CommonJS อนุญาตให้มีการส่งออกการปะแก้ลิงขณะนี้โมดูล ES ไม่
  • เป็นการยากที่จะตรวจสอบว่าอะไรคือโมดูล ES และอะไรคือ CommonJS ที่ไม่มีรูปแบบการป้อนข้อมูลของผู้ใช้ แต่พวกเขากำลังพยายาม
  • *.mjs ดูเหมือนว่าเป็นวิธีที่น่าจะเป็นไปได้มากที่สุดเว้นแต่พวกเขาจะสามารถตรวจสอบโมดูล ES ได้อย่างถูกต้องโดยไม่ต้องป้อนข้อมูลจากผู้ใช้

- คำตอบเดิม -

นี่เป็นมันฝรั่งร้อนมาระยะหนึ่งแล้ว บรรทัดล่างคือใช่ในที่สุดโหนดจะสนับสนุนไวยากรณ์ ES2015 สำหรับการนำเข้า / ส่งออกโมดูล - เป็นไปได้มากที่สุดเมื่อข้อมูลจำเพาะสำหรับการโหลดโมดูลถูกสรุปและตกลง

นี่คือภาพรวมที่ดีของสิ่งที่ถือ NodeJS ขึ้น โดยพื้นฐานแล้วพวกเขาจำเป็นต้องตรวจสอบให้แน่ใจว่าสเป็คใหม่ทำงานกับ Node ซึ่งเป็นเงื่อนไขการโหลดแบบซิงโครนัสและ HTML ซึ่งเป็นแบบอะซิงโครนัสเป็นหลัก

ไม่มีใครรู้แน่นอนตอนนี้ แต่ฉันคิดว่าโหนดจะสนับสนุนimport/exportการโหลดแบบคงที่นอกเหนือจากใหม่System.importสำหรับการโหลดแบบไดนามิก - ในขณะที่ยังคงรักษาrequireรหัสเดิม

ต่อไปนี้เป็นข้อเสนอบางประการเกี่ยวกับวิธีที่โหนดอาจประสบความสำเร็จ


38
เกี่ยวกับ.mjsส่วนขยาย: We have affectionately called these “Michael Jackson Script” files in the past. ในกรณีที่คุณได้ยินคนพูดถึงศิลปินป๊อปในระหว่างการพูดคุยของ JS
Jeewes

1
ฉันไม่เห็นสาเหตุที่การเปลี่ยนไวยากรณ์การนำเข้าไม่เพียงพอ หนึ่งไวยากรณ์สำหรับการนำเข้า es (ถูกต้องหนึ่ง) และอีกหนึ่งสำหรับการนำเข้า cjs? กล่าวอีกนัยหนึ่งเมื่อได้รับสองไฟล์ foo.js และ bar.js import * from 'foo'จะปฏิบัติต่อ foo.js เนื่องจาก CommonJS import * as bar from 'bar'จะปฏิบัติต่อ bar.js ในฐานะโมดูล ES6 ใครบางคนอธิบายได้ไหม
Corey Alix

1
โดยทั่วไป @CoreyAlix ไวยากรณ์จะไม่เปลี่ยนแปลงเพื่อสนับสนุนสภาพแวดล้อม สิ่งนี้มีผลกับโหนดหลังจากทั้งหมดเท่านั้น นอกจากนี้ไวยากรณ์ยังใช้งานง่าย ฉันจะเข้าถึงการส่งออกในรูปแบบที่คุณเสนอได้อย่างไร
CodingIntrigue

เพื่อความชัดเจนไม่ใช่ข้อเสนอ "ของฉัน" ฉันกำลังคัดลอกสิ่งที่ตัวพิมพ์ดีดกำลังทำอยู่ ในการตอบคำถามของคุณคุณสามารถเข้าถึงการส่งออกด้วย "bar": bar.foobar () import {foo as Foo} จาก“ ./foo” เป็นกลไกในการระบุโมดูล ES6 var Foo = require (“ ./ foo”) เป็นกลไกในการระบุโมดูล CJS ใน typescript เอาต์พุต commonjs มีลักษณะดังนี้: var mod1_1 = require ("./ mod1"); exports.mod1 = mod1; เอาต์พุต ES6 มีลักษณะดังนี้: import {mod1} จาก“ ./mod1”; ส่งออก {mod1}
Corey Alix

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