借助 ES 模块的静态分析来组织你的项目,并避开有害的桶文件和循环依赖。
在 Kodokon 中打开本课ES 模块是静态的:import 和 export 语句在文件被解析时就得到解析,早于任何代码运行。正是这一点使得tree-shaking(移除从未被导入的代码)成为可能,并能在构建时就捕获命名错误。是用具名导出还是默认导出?具名导出几乎在每一方面都更胜一筹:便于重构时重命名、自动补全可靠,而且没法把同一个东西用十个不同的名字导入。默认导出留给模块导出一个显而易见的东西的情况。
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;
}
}在消费方,有四种形式:具名导入(可通过 as 选择性地起别名)、默认导入、命名空间导入(* as),以及动态导入 import(),它返回一个关于命名空间的 promise。后者是代码分割的基本构件:只在用户真正需要的那一刻,才去加载一个笨重的模块(编辑器、图表、PDF)。
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在组织结构上,优先按功能拆分(features/cart/、features/auth/),而不是按技术类型拆分(controllers/、helpers/):一起变动的代码放在一起,删除一个功能就意味着删掉一个文件夹。通过一个狭窄的入口点来暴露每个功能,并把任何绕过该入口点的导入都视为一次边界违规。
import("./module.js") 返回什么?