JavaScript模块加载器解决import无法运行时决定路径、按需加载及兼容非ES模块的问题;现代用import()动态导入,SystemJS用于加载AMD/UMD等旧模块,RequireJS等已过时。
它不是语法层面的必需品,而是为了解决 import 无法在运行时决定加载路径、无法按需加载、无法兼容非 ES 模块(如 AMD、CommonJS)或无模块环境的问题。现代浏览器原生支持 import() 动态导入,但模块加载器(如 RequireJS、SystemJS、甚至 Webpack 的 runtime)提供更细粒度的控制:比如加载前重写路径、注入 polyfill、处理循环依赖、支持插件化转换(如 JSON、CSS 加载)。
import() 实现最简动态加载这是目前标准、轻量、无需额外库的方式,返回 Promise,适用于大多数现代场景:
const loadModule = async (path) => {
try {
const mod = await import(path);
return mod.default || mod;
} catch (err) {
console.error('动态加载失败:', err);
throw err;
}
};
// 使用示例
loadModule('./utils/math.js').then(math => math.add(2, 3));
path 必须是字符串字面量或模板字符串中的静态部分(如 `./features/${feature}.js`),不能是完全运行时拼接的变量,否则打包工具(如 Vite、Webpack)无法做静态分析和代码分割Access-Control-Allow-Origin
import('./x.js') 同一路径,浏览器会复用已解析/执行的模块实例,不是重复请求当你必须加载 AMD、UMD 或全局变量挂载型脚本(比如某些老版 Chart.js、Loda
sh CDN 版),import() 无能为力,SystemJS 是少数仍维护的通用加载器:
System.config({ map, packages }) 才能处理相对路径、版本别名或包入口System.import 不是 Promise A+ 兼容实现,某些版本 resolve 值不统一;CDN 加载的模块若依赖其他 UMD 模块,需提前 System.register 声明依赖它们是 AMD 规范时代的产物,核心逻辑基于 define/require 回调,而现代开发中:
import() 原生支持,无需学习新 APIimport() 能自动产出独立 chunk,RequireJS 的 require(['a','b'], cb) 在构建期无法优化shim 配置容易出错:比如漏写 exports 导致模块值为 undefined,或 deps 顺序错乱引发执行时序问题真正需要动态加载的复杂场景(如微前端、插件系统),通常用自定义 loader + import() 封装,而不是引入整套历史加载器。