UMD是一种兼容AMD、CommonJS和全局变量的模块定义方式,核心是通过IIFE检测define、module.exports和全局对象(self/window/globalThis)来动态导出模块,支持多环境运行。

UMD(Universal Module Definition)是一种让模块同时兼容 AMD、CommonJS 和全局变量加载方式的写法,核心目标是“一份代码,多端运行”。它在老项目迁移、库开发或需要支持多种构建环境时特别实用。
UMD 的基本结构与判断逻辑
UMD 本质是一个立即执行函数(IIFE),通过检测运行环境来决定模块导出方式。关键在于识别 define(AMD)、module.exports(CommonJS)和全局对象(如 window 或 global)是否存在。
- 先检查
typeof define === 'function' && define.amd→ AMD 环境(如 RequireJS) - 再检查
typeof module === 'object' && module.exports→ Node.js 或 Webpack 的 CommonJS 环境 - 否则挂载到全局对象(
root,通常是window或self,兼顾浏览器和 Web Worker)
标准 UMD 模板写法(含 ES5 兼容)
以下是最常用、兼容性最强的 UMD 封装模板,支持 IE9+、Node.js、RequireJS、Browserify 等:
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD
define(['exports'], factory);
} else if (typeof module === 'object' && module.exports) {
// CommonJS
factory(module.exports);
} else {
// 全局变量(浏览器、Web Worker)
factory(root.myModule = {});
}
}(typeof self !== 'undefined' ? self : typeof window !== 'undefined' ? window : globalThis, function (exports) {
// 模块主体:你的代码放这里
exports.sayHello = function () {
return 'Hello from UMD!';
};
}));
注意:root 使用 self → window → globalThis 的降级链,比直接用 window 更健壮;factory 接收 exports 参数,统一处理导出逻辑,避免重复代码。
立即学习“Java免费学习笔记(深入)”;
ES6+ 代码如何适配 UMD
若你用 ES6 编写模块(如 export const foo = ...),不能直接套用 UMD 模板。需先转译(如 Babel + preset-env),再包裹 UMD 头尾。推荐工作流:
- 源码用 ES6/ES2020 语法编写,使用
export/import - 构建时用 Rollup 或 Webpack 输出 UMD 格式(配置
output.format = 'umd') - 手动维护 UMD 模板仅适用于轻量工具库或需精细控制导出名的场景(如指定
globalName: 'MyLib')
Rollup 示例配置片段:
export default {
input: 'src/index.js',
output: {
file: 'dist/mylib.umd.js',
format: 'umd',
name: 'MyLib',
globals: { lodash: '_' }
}
};
常见兼容性陷阱与规避建议
实际使用中容易忽略但影响兼容性的细节:
-
不要依赖
window判断浏览器环境:SSR(服务端渲染)或 Web Worker 中window未定义,应优先用self或globalThis -
慎用
module.exports =直接赋值:某些旧版 Webpack(v1/v2)对module.exports =和exports.xxx =处理不一致,统一用factory(exports)方式更稳妥 -
避免在 UMD 包裹内做运行时模块探测副作用:比如在 factory 内动态
require或修改define,会破坏预打包确定性 -
测试必须覆盖三类环境:RequireJS 页面、Node.js
require()、直接<script>引入,缺一不可










