Kodokon kodokon.com

ES module: import/export, การจัดโครงสร้างโปรเจกต์

จัดโครงสร้างโปรเจกต์ของคุณด้วย ES module โดยใช้ประโยชน์จากการวิเคราะห์แบบสถิตและหลีกเลี่ยง barrel ที่เป็นพิษและการพึ่งพาแบบวงกลม

8 นาที · 3 คำถาม

เปิดบทเรียนนี้ใน Kodokon

ES module เป็นแบบ สถิต: คำสั่ง import และ export ถูก resolve ตอนที่ไฟล์ถูกแจง (parse) ก่อนที่โค้ดใด ๆ จะทำงาน นั่นคือสิ่งที่ทำให้เกิด tree-shaking (การกำจัดโค้ดที่ไม่เคยถูก import) และจับความผิดพลาดในการตั้งชื่อได้ ณ เวลาบิลด์ named export หรือ default export ดี? named export ชนะแทบทุกด้าน: เปลี่ยนชื่อได้ง่ายเวลา refactor, autocomplete เชื่อถือได้ และไม่มีทางที่จะ import สิ่งเดียวกันด้วยชื่อสิบชื่อที่ต่างกัน เก็บ default ไว้สำหรับกรณีที่โมดูล export สิ่งที่ หนึ่งเดียว ชัดเจน

JAVASCRIPT
export const TAX_RATE = 0.2;

export function applyTax(price) {
  return price * (1 + TAX_RATE);
}

export default class Cart {
  items = [];
  add(item) {
    this.items.push(item);
    return this;
  }
}
cart.js: named export สำหรับยูทิลิตี default สำหรับคลาสหลัก

ในฝั่งผู้บริโภคมีสี่รูปแบบ: named import (พร้อมการตั้งชื่อแทนเสริมผ่าน as), default import, namespace import (* as) และ dynamic import import() ซึ่งคืน promise ของ namespace รูปแบบหลังนี้คือหน่วยพื้นฐานของ code splitting: โหลดโมดูลหนัก ๆ (เอดิเตอร์, ชาร์ต, PDF) เฉพาะเมื่อผู้ใช้ต้องการมันจริง ๆ เท่านั้น

JAVASCRIPT
import Cart, { applyTax, TAX_RATE } from "./cart.js";
import * as cartModule from "./cart.js";

console.log(applyTax(100), TAX_RATE); // 120 0.2
console.log(cartModule.TAX_RATE); // 0.2

const lazy = await import("./cart.js");
const cart = new lazy.default();
console.log(cart instanceof Cart); // true
รูปแบบสถิตและ dynamic import ของโมดูลเดียวกัน

สำหรับการจัดระเบียบ จงเลือกแบ่ง ตามฟีเจอร์ (features/cart/, features/auth/) แทนการแบ่งตามประเภททางเทคนิค (controllers/, helpers/): โค้ดที่เปลี่ยนแปลงไปด้วยกันอยู่ด้วยกัน และการลบฟีเจอร์หนึ่งหมายถึงการลบโฟลเดอร์เดียว เปิดเผยแต่ละฟีเจอร์ผ่านจุดเข้าที่แคบ และถือว่า import ใด ๆ ที่ข้ามจุดเข้านั้นเป็นการละเมิดขอบเขต

ทดสอบความรู้

ตรวจสอบว่าคุณจำประเด็นสำคัญของบทเรียนนี้ได้ครบถ้วน

  1. อะไรทำให้ tree-shaking เป็นไปได้ด้วย ES module?
    • bundler รันโค้ดเพื่อดูว่าอะไรถูกใช้
    • import และ export เป็นแบบสถิตและวิเคราะห์ได้โดยไม่ต้องรันโค้ด
    • ES module บีบอัดโค้ดที่ตายแล้วโดยอัตโนมัติ
  2. นิพจน์ import("./module.js") คืนอะไร?
    • namespace ของโมดูล แบบซิงโครนัส
    • promise ที่ resolve ด้วย namespace ของโมดูล
    • ฟังก์ชันที่โหลดโมดูลเมื่อถูกเรียก
    • เฉพาะ default export ของโมดูลเท่านั้น
  3. ความเสี่ยงหลักของ barrel file (ไฟล์ index ที่ re-export ทั้งโฟลเดอร์) คืออะไร?
    • มันทำให้ named export เป็นไปไม่ได้
    • มันสามารถโหลดทั้งโฟลเดอร์เพียงเพื่อ import ตัวเดียวและขัดขวาง tree-shaking
    • มันป้องกัน dynamic import ของโฟลเดอร์