การใช้ Node.js ต้องการกับการนำเข้า / ส่งออก ES6


930

ในโครงการที่ฉันร่วมมือกันเรามีสองตัวเลือกสำหรับระบบโมดูลที่เราสามารถใช้ได้:

  1. การนำเข้าโมดูลการใช้requireและการส่งออกโดยใช้และmodule.exportsexports.foo
  2. การนำเข้าโมดูลโดยใช้ ES6 importและการส่งออกโดยใช้ ES6export

มีประโยชน์ด้านประสิทธิภาพการใช้หนึ่งมากกว่าอีก มีอะไรอีกบ้างที่เราควรรู้ถ้าเราจะใช้โมดูล ES6 เหนือโหนด


9
node --experimental-modules index.mjsให้คุณใช้importโดยไม่ใช้Babel และทำงานใน Node 8.5.0+ คุณสามารถ (และควร) เผยแพร่แพคเกจ npm ของคุณเป็น ESModule ดั้งเดิมพร้อมความเข้ากันได้แบบย้อนหลังสำหรับrequireวิธีเก่า
Dan Dascalescu

คำตอบ:


728

มีประโยชน์ด้านประสิทธิภาพการใช้หนึ่งมากกว่าอีก

โปรดทราบว่าไม่มีเอ็นจิ้น JavaScript แต่ยังสนับสนุนโมดูล ES6 โดยพื้นฐาน คุณพูดว่าตัวเองกำลังใช้บาเบล Babel แปลงimportและexportประกาศเป็น CommonJS ( require/ module.exports) ตามค่าเริ่มต้นแล้ว ดังนั้นแม้ว่าคุณจะใช้ไวยากรณ์โมดูล ES6 คุณจะใช้ CommonJS ภายใต้ประทุนหากคุณเรียกใช้รหัสในโหนด

มีความแตกต่างทางเทคนิคระหว่างโมดูล CommonJS และ ES6 เช่น CommonJS ช่วยให้คุณสามารถโหลดโมดูลแบบไดนามิกได้ ES6 ไม่อนุญาตนี้แต่มี API ในการพัฒนาสำหรับการที่

เนื่องจากโมดูล ES6 เป็นส่วนหนึ่งของมาตรฐานฉันจึงใช้มัน


16
ฉันพยายามใช้ES6 importด้วยrequireแต่พวกเขาทำงานต่างกัน CommonJS ส่งออกชั้นเรียนของตัวเองในขณะที่มีเพียงชั้นเดียว การส่งออก ES6 เหมือนมีหลายคลาสดังนั้นคุณต้องใช้.ClassNameเพื่อรับคลาสที่ส่งออก มีความแตกต่างอื่น ๆ อีกหรือไม่ซึ่งมีผลต่อการนำไปใช้จริง
Thellimist

78
@Entei: ดูเหมือนว่าคุณต้องการส่งออกเริ่มต้นไม่ใช่การส่งออกที่มีชื่อ เทียบเท่ากับmodule.exports = ...; เทียบเท่ากับ; export default ...exports.foo = ...export var foo = ...
เฟลิกซ์คลิง

10
เป็นที่น่าสังเกตว่าแม้ว่า Babel ในที่สุดimportจะเปลี่ยนไปใช้ CommonJS ใน Node ซึ่งใช้ร่วมกับ Webpack 2 / Rollup (และ Bundler อื่น ๆ ที่ช่วยให้ต้นไม้ ES6 สั่น) ก็เป็นไปได้ที่จะจบลงด้วยไฟล์ที่เล็กกว่ารหัส Node crunches ผ่านการใช้งานrequireอย่างแน่นอนเพราะ ES6 ช่วยให้การวิเคราะห์แบบคงที่ของการนำเข้า / ส่งออก แม้ว่าสิ่งนี้จะไม่สร้างความแตกต่างให้กับ Node แต่ก็สามารถทำได้หากรหัสในท้ายที่สุดจะเป็นชุดเบราว์เซอร์เดียว
Lee Benson

5
ถ้าคุณไม่จำเป็นต้องนำเข้าแบบไดนามิก
chulian

3
โมดูล ES6 อยู่ใน V8 ล่าสุดและจะมาถึงในเบราว์เซอร์อื่น ๆ หลังธง ดู: medium.com/dev-channel/ …
Nexii Malthus

180

มีการใช้งาน / ความสามารถหลายอย่างที่คุณอาจต้องการพิจารณา:

จำเป็นต้อง:

  • คุณสามารถโหลดแบบไดนามิกโดยที่ชื่อโมดูลที่โหลดไม่ได้ถูกกำหนดไว้ล่วงหน้า / คงที่หรือที่คุณโหลดโมดูลแบบมีเงื่อนไขก็ต่อเมื่อ "จำเป็นต้องใช้" อย่างแท้จริง (ขึ้นอยู่กับการไหลของโค้ดบางอย่าง)
  • กำลังโหลดแบบซิงโครนัส นั่นหมายความว่าถ้าคุณมีหลายrequires พวกเขาจะถูกโหลดและประมวลผลทีละคน

การนำเข้า ES6:

  • คุณสามารถใช้การอิมพอร์ตที่มีชื่อเพื่อเลือกโหลดเฉพาะส่วนที่คุณต้องการ ที่สามารถบันทึกความจำ
  • การนำเข้าสามารถเป็นแบบอะซิงโครนัส (และในปัจจุบันโหลดโมดูล ES6 จริง ๆ แล้ว) และสามารถทำงานได้ดีขึ้นเล็กน้อย

นอกจากนี้ระบบโมดูลจำเป็นต้องใช้ไม่ได้มาตรฐาน มันไม่น่าเป็นไปได้อย่างมากที่จะกลายเป็นมาตรฐานในขณะนี้ที่โมดูล ES6 มีอยู่ ในอนาคตจะมีการสนับสนุนพื้นเมืองสำหรับโมดูล ES6 ในการใช้งานที่หลากหลายซึ่งจะเป็นข้อได้เปรียบในแง่ของประสิทธิภาพ


16
อะไรทำให้คุณคิดว่าการนำเข้า ES6 นั้นไม่ตรงกัน?
เฟลิกซ์คลิง

5
@ FelixKling - การรวมกันของการสังเกตต่างๆ การใช้ JSPM (ES6 Module Loader ... ) ฉันสังเกตเห็นว่าเมื่อการอิมพอร์ตแก้ไขเนมสเปซโกลบอลจะไม่ได้รับผลกระทบจากการอิมพอร์ตอื่น (เนื่องจากเกิดขึ้นแบบอะซิงโครนัส .. ซึ่งสามารถเห็นได้ในรหัส transpiled) นอกจากนี้เนื่องจากพฤติกรรม (การนำเข้า 1 รายการไม่ส่งผลกระทบต่อผู้อื่น) ไม่มีเหตุผลที่จะไม่ทำดังนั้นจึงอาจขึ้นอยู่กับการใช้งาน
Amit

35
คุณพูดถึงบางสิ่งที่สำคัญมาก: โหลดเดอร์โมดูล ในขณะที่ ES6 จัดเตรียมการนำเข้าและส่งออกไวยากรณ์มันไม่ได้กำหนดวิธีการโหลดโมดูล ส่วนที่สำคัญคือการประกาศจะวิเคราะห์แบบคงที่เพื่อให้สามารถอ้างอิงได้โดยไม่ต้องดำเนินการรหัส สิ่งนี้จะช่วยให้โหลดเดอร์โมดูลสามารถโหลดโมดูลแบบซิงโครนัสหรือแบบอะซิงโครนัส แต่โมดูล ES6 ด้วยตัวเองไม่ได้เป็นแบบซิงโครนัสหรือแบบอะซิงโครนัส
เฟลิกซ์คลิง

5
@FelixKling ES6 โมดูลตัวโหลดถูกติดแท็กใน OP ดังนั้นฉันคิดว่ามันเกี่ยวข้องกับคำตอบ นอกจากนี้ฉันยังระบุด้วยว่าการสังเกต async เป็นพฤติกรรมปัจจุบันรวมถึงความเป็นไปได้ในอนาคต (ในการดำเนินการใด ๆ ) ดังนั้นจึงเป็นประเด็นที่ต้องพิจารณา คุณคิดว่ามันผิดหรือเปล่า?
Amit

10
ฉันคิดว่ามันสำคัญที่จะไม่ทำให้ระบบโมดูล / ไวยากรณ์กับโมดูลโหลดเดอร์สับสน เช่นถ้าคุณพัฒนาสำหรับโหนดคุณก็น่าจะรวบรวมโมดูล ES6 ไว้requireแล้วดังนั้นคุณจึงใช้ระบบโมดูลและโหลดเดอร์อยู่แล้ว
เฟลิกซ์คลิง

41

ข้อได้เปรียบหลักคือวากยสัมพันธ์:

  • ไวยากรณ์เพิ่มเติมที่ประกาศ / กระชับ
  • โดยทั่วไปแล้วโมดูล ES6 จะทำให้ UMD (Universal Module Definition) ล้าสมัย - โดยหลักแล้วจะเป็นการลบความแตกต่างระหว่าง CommonJS และ AMD (เซิร์ฟเวอร์กับเบราว์เซอร์)

คุณไม่เห็นประโยชน์ด้านประสิทธิภาพใด ๆ กับโมดูล ES6 คุณจะยังคงต้องการไลบรารีเพิ่มเติมเพื่อรวมโมดูลแม้ว่าจะมีการสนับสนุนคุณสมบัติ ES6 อย่างเต็มรูปแบบในเบราว์เซอร์


4
คุณสามารถอธิบายได้หรือไม่ว่าเหตุใดจึงต้องใช้ตัวรวมแม้ว่าเบราว์เซอร์รองรับโมดูล ES6 แบบสมบูรณ์
E. Sundin

1
ขอโทษแก้ไขให้เหมาะสมมากขึ้น ฉันหมายความว่าคุณสมบัติโมดูลนำเข้า / ส่งออกไม่ได้ถูกนำไปใช้ในเบราว์เซอร์ใด ๆ ยังจำเป็นต้องมี transpiler
snozza

16
ดูเหมือนจะขัดแย้งกับฉันเล็กน้อย หากได้รับการสนับสนุนอย่างเต็มที่แล้วจุดประสงค์ของผู้รวบรวมคืออะไร มีบางสิ่งที่ขาดหายไปในข้อมูลจำเพาะ ES6 หรือไม่ สิ่งที่จะ Bundler จริงทำอย่างนั้นไม่ได้อยู่ในสภาพแวดล้อมที่ได้รับการสนับสนุนอย่างเต็มที่ ?
E. Sundin

1
ดังที่ @snozza กล่าวว่า ... "คุณลักษณะโมดูลนำเข้า / ส่งออกไม่ได้ดำเนินการในเบราว์เซอร์ใด ๆ อย่างไร้เดียงสายังจำเป็นต้องมี
transpiler

2
คุณไม่ต้องการไลบรารีเพิ่มเติมอีกต่อไป ตั้งแต่ v8.5.0 (วางจำหน่ายมากกว่าหนึ่งปีที่ผ่านมา) node --experimemntal-modules index.mjsให้คุณใช้งานได้importโดยไม่ต้อง Babel คุณสามารถ (และควร) เผยแพร่แพคเกจ npm ของคุณเป็น ESModule ดั้งเดิมพร้อมความเข้ากันได้แบบย้อนหลังสำหรับrequireวิธีเก่า เบราว์เซอร์จำนวนมากยังรองรับการนำเข้าแบบไดนามิกด้วย
Dan Dascalescu

38

มีประโยชน์ด้านประสิทธิภาพการใช้หนึ่งมากกว่าอีก

คำตอบปัจจุบันคือไม่เพราะไม่มีเบราว์เซอร์เอ็นimport/exportจิ้นปัจจุบันที่ใช้จากมาตรฐาน ES6

ชาร์ตเปรียบเทียบบางตัวhttp://kangax.github.io/compat-table/es6/อย่านำสิ่งนี้ไปพิจารณาดังนั้นเมื่อคุณเห็นเกือบทุกสนามสำหรับ Chrome โปรดระวัง importคำหลักจาก ES6 ยังไม่ได้รับการพิจารณา

เครื่องมือเบราว์เซอร์ปัจจุบันรวมถึง V8 ไม่สามารถนำเข้าไฟล์ JavaScript ใหม่จากไฟล์ JavaScript หลักผ่านทางคำสั่ง JavaScript ใด ๆ

(เราอาจจะยังห่างกันไม่กี่ข้อหรือหลายปีจนกว่า V8 จะดำเนินการตามข้อกำหนด ES6)

เอกสารนี้เป็นสิ่งที่เราต้องการและเอกสารนี้เป็นสิ่งที่เราต้องเชื่อฟัง

และมาตรฐาน ES6 บอกว่าควรมีการพึ่งพาโมดูลก่อนที่เราจะอ่านโมดูลเช่นในภาษาการเขียนโปรแกรม C ที่เรามี (ส่วนหัว) .hไฟล์

นี่เป็นโครงสร้างที่ดีและผ่านการทดสอบมาอย่างดีและฉันมั่นใจว่าผู้เชี่ยวชาญที่สร้างมาตรฐาน ES6 นั้นจะต้องคำนึงถึง

นี่คือสิ่งที่ช่วยให้ Webpack หรือแพคเกจแพ็คเกจอื่น ๆ ปรับบันเดิลในบางกรณีพิเศษและลดการพึ่งพาบางอย่างจากบันเดิลที่ไม่จำเป็น แต่ในกรณีที่เรามีการพึ่งพาที่สมบูรณ์แบบสิ่งนี้จะไม่เกิดขึ้น

จะต้องใช้เวลาสักครู่จนกว่าimport/exportการสนับสนุนดั้งเดิมจะพร้อมใช้งานและrequireคำหลักจะไม่ไปที่ใดก็ได้เป็นเวลานาน

คือrequireอะไร

นี่เป็นnode.jsวิธีโหลดโมดูล ( https://github.com/nodejs/node )

โหนดใช้วิธีการระดับระบบเพื่ออ่านไฟล์ requireคุณพื้นพึ่งพาว่าเมื่อใช้ requireจะสิ้นสุดในการเรียกของระบบบางอย่างเช่นuv_fs_open(ขึ้นอยู่กับระบบปลายทาง, Linux, Mac, Windows) เพื่อโหลดไฟล์ / โมดูล JavaScript

หากต้องการตรวจสอบว่าเป็นความจริงพยายามที่จะใช้ Babel.js และคุณจะเห็นได้ว่าคำหลักจะถูกแปลงเป็นimportrequire

ป้อนคำอธิบายรูปภาพที่นี่


2
ที่จริงมีพื้นที่หนึ่งที่สามารถปรับปรุงประสิทธิภาพได้ - ขนาดมัด การใช้importในกระบวนการสร้าง Webpack 2 / Rollup สามารถลดขนาดไฟล์ผลลัพธ์โดย 'tree shaking' โมดูล / รหัสที่ไม่ได้ใช้ซึ่งอาจเป็นผลมาจากชุดสุดท้าย ไฟล์เล็กลง = เร็วกว่าในการดาวน์โหลด = เร็วกว่าเพื่อเริ่มต้น / เรียกใช้บนไคลเอนต์
Lee Benson

2
เหตุผลคือไม่มีเบราว์เซอร์ปัจจุบันบนดาวเคราะห์โลกจึงอนุญาตให้ใช้import คำหลักได้ หรือหมายความว่าคุณไม่สามารถนำเข้าไฟล์ JavaScript อื่นจากไฟล์ JavaScript นี่คือเหตุผลที่คุณไม่สามารถเปรียบเทียบผลประโยชน์ด้านประสิทธิภาพของสองสิ่งนี้ แต่แน่นอนว่าเครื่องมือเช่น Webpack1 / 2 หรือ Browserify สามารถจัดการกับการบีบอัดได้ พวกเขาเป็นคอถึงลำคอ: gist.github.com/substack/68f8d502be42d5cd4942
prosti

4
คุณกำลังมอง 'เขย่าต้นไม้' ไม่มีที่ใดในลิงค์ส่วนสำคัญของคุณที่ได้กล่าวถึงการเขย่าต้นไม้ การใช้โมดูล ES6 ช่วยให้สามารถทำได้เนื่องจากimportและexportเป็นการประกาศแบบคงที่ที่นำเข้าเส้นทางรหัสที่เฉพาะเจาะจงในขณะที่requireสามารถเป็นแบบไดนามิกและทำให้มัดในรหัสที่ไม่ได้ใช้ ข้อดีด้านประสิทธิภาพคือทางอ้อม - Webpack 2 และ / หรือ Rollup อาจส่งผลให้ขนาดของชุดข้อมูลขนาดเล็กลงซึ่งดาวน์โหลดได้เร็วกว่าดังนั้นผู้ใช้จึงเห็นว่าผู้ใช้ปลายทาง (ของเบราว์เซอร์) ใช้ได้เฉพาะในกรณีที่รหัสทั้งหมดถูกเขียนในโมดูล ES6 ดังนั้นจึงสามารถวิเคราะห์การนำเข้าแบบคงที่ได้
Lee Benson

2
ฉันอัปเดตคำตอบ @LeeBenson ฉันคิดว่าถ้าเราพิจารณาการสนับสนุนดั้งเดิมจากเครื่องมือเบราว์เซอร์ที่เรายังไม่สามารถเปรียบเทียบได้ สิ่งที่มาพร้อมกับตัวเลือกการเขย่าสามแบบที่ใช้งานง่ายโดยใช้ Webpack อาจทำได้ก่อนที่เราจะตั้งค่าโมดูล CommonJS เนื่องจากสำหรับแอปพลิเคชันส่วนใหญ่ที่เรารู้ว่าควรใช้โมดูลใด
prosti

1
คำตอบของคุณถูกต้องทั้งหมด แต่ฉันคิดว่าเรากำลังเปรียบเทียบคุณสมบัติที่แตกต่างกันสองอย่าง ทั้งหมด import/exportถูกแปลงเป็นrequireได้รับ แต่สิ่งที่เกิดขึ้นก่อนขั้นตอนนี้อาจถือได้ว่าเป็นการเพิ่มประสิทธิภาพ ตัวอย่าง: ถ้าlodashเขียนใน ES6 และคุณimport { omit } from lodashบันเดิลขั้นสุดท้ายจะมีเพียง 'ละเว้น' และไม่ใช่ยูทิลิตี้อื่น ๆ ในขณะที่วิrequire('lodash')จะนำเข้าทุกอย่างอย่างง่าย สิ่งนี้จะเพิ่มขนาดของบันเดิลใช้เวลาดาวน์โหลดนานกว่าและลดประสิทธิภาพลง แน่นอนว่าใช้ได้ในบริบทเบราว์เซอร์เท่านั้น
Lee Benson

31

การใช้โมดูล ES6 มีประโยชน์สำหรับ 'การเขย่าต้นไม้'; เช่นการเปิดใช้งาน Webpack 2, Rollup (หรือตัวรวมอื่น ๆ ) เพื่อระบุเส้นทางของรหัสที่ไม่ได้ใช้ / นำเข้าและดังนั้นจึงไม่ได้ทำให้มันเป็นบันเดิลที่เกิดขึ้น สิ่งนี้สามารถลดขนาดไฟล์ลงได้อย่างมากโดยการกำจัดรหัสที่คุณไม่ต้องการ แต่ด้วย CommonJS จะถูกรวมเป็นค่าเริ่มต้นเพราะ Webpack และคณะไม่มีวิธีการที่จะรู้ว่าจำเป็นหรือไม่

สิ่งนี้ทำโดยใช้การวิเคราะห์แบบสแตติกของโค้ดพา ธ

ตัวอย่างเช่นการใช้:

import { somePart } 'of/a/package';

... ให้คำแนะนำแก่บันเดิลซึ่งpackage.anotherPartไม่จำเป็น (หากไม่ได้นำเข้าจะไม่สามารถใช้งานได้ใช่ไหม) ดังนั้นมันจะไม่รบกวนการรวมกลุ่ม

ในการเปิดใช้งานสิ่งนี้สำหรับ Webpack 2 คุณต้องตรวจสอบให้แน่ใจว่า transpiler ของคุณไม่กระจายโมดูล CommonJS หากคุณใช้es2015ปลั๊กอินกับ Babel คุณสามารถปิดการใช้งานได้ในสิ่งที่.babelrcชอบ:

{
  "presets": [
    ["es2015", { modules: false }],
  ]
}

การยกเลิกและอื่น ๆ อาจทำงานแตกต่างกัน - ดูเอกสารหากคุณสนใจ


2
ยังยอดเยี่ยมสำหรับการเขย่าต้นไม้2ality.com/2015/12/webpack-tree-shaking.html
prosti

25

เมื่อพูดถึง async หรือ lazy loading import ()มันมีประสิทธิภาพมากกว่า ดูเมื่อเราต้องการองค์ประกอบในทางตรงกันแล้วเราจะใช้importในลักษณะ async บางส่วนในขณะที่ตัวแปรใช้constawait

const module = await import('./module.js');

หรือถ้าคุณต้องการที่จะใช้require()แล้ว

const converter = require('./converter');

สิ่งที่เป็นimport()จริง async ในธรรมชาติ ตามที่กล่าวไว้โดย neehar venugopal ในReactConfคุณสามารถใช้มันเพื่อโหลดส่วนประกอบการตอบสนองแบบไดนามิกสำหรับสถาปัตยกรรมฝั่งไคลเอ็นต์

นอกจากนี้ยังเป็นวิธีที่ดีกว่าเมื่อมันมาถึงการกำหนดเส้นทาง นั่นคือสิ่งพิเศษอย่างหนึ่งที่ทำให้บันทึกเครือข่ายเพื่อดาวน์โหลดส่วนที่จำเป็นเมื่อผู้ใช้เชื่อมต่อกับเว็บไซต์เฉพาะไปยังองค์ประกอบเฉพาะ เช่นหน้าเข้าสู่ระบบก่อนแดชบอร์ดจะไม่ดาวน์โหลดส่วนประกอบทั้งหมดของแดชบอร์ด เพราะสิ่งที่จำเป็นในปัจจุบันคือองค์ประกอบการเข้าสู่ระบบนั่นจะถูกดาวน์โหลดเท่านั้น

กันไปสำหรับexport: ES6 exportจะตรงเช่นเดียวกับ module.exportsCommonJS

หมายเหตุ - หากคุณมีการพัฒนาโครงการ Node.js แล้วคุณจะต้องใช้อย่างเคร่งครัดrequire()เป็นโหนดจะโยนความผิดพลาดข้อยกเว้นเป็นถ้าคุณจะใช้invalid token 'import' importดังนั้นโหนดไม่สนับสนุนการนำเข้าคำสั่ง

อัปเดต - ตามคำแนะนำของDan Dascalescu : ตั้งแต่ v8.5.0 (เผยแพร่เมื่อกันยายน 2017) node --experimental-modules index.mjsให้คุณใช้งานได้importโดยไม่ต้อง Babel คุณสามารถ (และควร) เผยแพร่แพคเกจ npm ของคุณเป็น ESModule ดั้งเดิมพร้อมความเข้ากันได้แบบย้อนหลัง สำหรับrequireวิธีเก่า

ดูสิ่งนี้สำหรับการกวาดล้างเพิ่มเติมที่จะใช้การนำเข้า async - https://www.youtube.com/watch?v=bb6RCrDaxhw


1
ดังนั้นจะต้องมีการซิงค์และรอ?
baklazan

1
พูดได้จริง!
พบกับ Zaveri

15

สิ่งที่สำคัญที่สุดที่ควรทราบคือโมดูล ES6 นั้นเป็นมาตรฐานอย่างเป็นทางการในขณะที่โมดูล CommonJS (Node.js) ไม่ใช่

ในปี 2019 โมดูล ES6 รองรับเบราว์เซอร์84% ในขณะที่ Node.js วางไว้ข้างหลัง- แฟล็ก --experimental-modulesนอกจากนี้ยังมีแพ็คเกจโหนดที่สะดวกที่เรียกว่าesmซึ่งทำให้การรวมราบรื่น

ปัญหาอื่นที่คุณอาจพบระหว่างระบบโมดูลเหล่านี้คือตำแหน่งรหัส Node.js ถือว่าแหล่งข้อมูลถูกเก็บไว้ในnode_modulesไดเรกทอรีในขณะที่โมดูล ES6 ส่วนใหญ่จะปรับใช้ในโครงสร้างไดเรกทอรีแบน สิ่งเหล่านี้ไม่ใช่เรื่องง่ายที่จะกระทบยอด แต่สามารถทำได้โดยการแฮ็กpackage.jsonไฟล์ของคุณด้วยสคริปต์ก่อนและหลังการติดตั้ง นี่คือตัวอย่างโมดูล isomorphicและบทความอธิบายวิธีการทำงาน


8

ฉันใช้การอิมพอร์ตเป็นการส่วนตัวเนื่องจากเราสามารถอิมพอร์ตเมธอดที่ต้องการสมาชิกโดยใช้การอิมพอร์ต

import {foo, bar} from "dep";

ชื่อไฟล์: dep.js

export foo function(){};
export const bar = 22

เครดิตไปที่ Paul Shan ข้อมูลเพิ่มเติม



6
คุณสามารถทำเช่นเดียวกันกับต้องการ!
สวิส

4
const {a,b} = require('module.js'); ทำงานได้ดีเช่นกัน ... หากคุณส่งออกaและb
BananaAcid

module.exports = { a: ()={}, b: 22 }- ส่วนที่สองของ @BananaAcid respones
Seth McClaine

7

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

ES6 → import, export default, export

CommonJS → require, module.exports, exports.foo

ด้านล่างเป็นการใช้งานทั่วไปของสิ่งเหล่านั้น

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

// hello.js
function hello() {
  return 'hello'
}
export default hello

// app.js
import hello from './hello'
hello() // returns hello

ES6 ส่งออกหลายรายการและนำเข้าหลายรายการ

// hello.js
function hello1() {
  return 'hello1'
}
function hello2() {
  return 'hello2'
}
export { hello1, hello2 }

// app.js
import { hello1, hello2 } from './hello'
hello1()  // returns hello1
hello2()  // returns hello2

CommonJS module.exports

// hello.js
function hello() {
  return 'hello'
}
module.exports = hello

// app.js
const hello = require('./hello')
hello()   // returns hello

CommonJS module.exports หลายรายการ

// hello.js
function hello1() {
  return 'hello1'
}
function hello2() {
  return 'hello2'
}
module.exports = {
  hello1,
  hello2
}

// app.js
const hello = require('./hello')
hello.hello1()   // returns hello1
hello.hello2()   // returns hello2

0

ไม่แน่ใจว่าทำไม (อาจเป็นการเพิ่มประสิทธิภาพ - การโหลดแบบขี้เกียจ) ทำงานเช่นนั้น แต่ฉันสังเกตเห็นว่าimportอาจไม่แยกวิเคราะห์รหัสหากไม่ได้ใช้โมดูลที่นำเข้า
ซึ่งอาจไม่เป็นไปตามพฤติกรรมที่คาดหวังในบางกรณี

เข้าร่วมชั้นเรียน Foo ที่เกลียดชังเป็นตัวอย่างของเรา

foo.ts

export default class Foo {}
console.log('Foo loaded');

ตัวอย่างเช่น:

index.ts

import Foo from './foo'
// prints nothing

index.ts

const Foo = require('./foo').default;
// prints "Foo loaded"

index.ts

(async () => {
    const FooPack = await import('./foo');
    // prints "Foo loaded"
})();

ในทางกลับกัน:

index.ts

import Foo from './foo'
typeof Foo; // any use case
// prints "Foo loaded"
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.