Top-level await 与 ESM 缓存策略:可控的 async 模块加载
利用动态 import() 与模块缓存机制(Module Map),设计一个支持依赖图并行加载、超时控制、循环依赖检测的智能加载器。 · 难度:入门 · +10XP
Top-level await 与 ESM 缓存策略:可控的 async 模块加载
ESM 模块天然支持 top-level await,但 import 语句是静态的。本教程将深入模块加载器的内部:Node.js 的 Module Map 如何缓存模块,以及为什么同一路径的 import() 只执行一次。我们将构建一个 Loader 类,它可以拦截 import() 行为,对特定模块添加超时、重试、甚至用 mock 替换。通过解析 import.meta.resolve 并结合 AbortController,实现一个可取消的模块加载链。同时利用 WeakMap 构建自定义模块缓存,在模块失败时从全局缓存中移除,允许重新加载。
const loader = {
async load(specifier, options = {}) {
const { signal, timeout = 5000 } = options;
const controller = new AbortController();
const timer = setTimeout(() => controller.abort(), timeout);
signal?.addEventListener('abort', () => controller.abort());
try {
return await import(specifier, { signal: controller.signal });
} finally {
clearTimeout(timer);
}
}
};
const mod = await loader.load('./data.mjs', { timeout: 1000 });