最近研究了一下 Vue
和 React
编译出来的版本文件,我发现 Vue
提供了 CommonJS|ES Module|ES Module browser|UMD
四种格式,而 React
提供 CommonJS|UMD
两个版本,对于 CommonJS|ES Module
对应的八股可以说是很多了,而里面夹杂的 UMD
又是什么东西呢?
UMD
UMD (Universal Module Definition)
,希望提供一个前后端跨平台的解决方案(支持AMD
与CommonJS
模块方式)。
好家伙,弄半天原来是 AMD
和 CommonJS
的集成!
那为啥要用 UMD
呢?
CJS 和 AMD
CJS(CommonJS)
和 AMD(Asynchronous Module Definition)
是 JS
的两种模块标准,众所周知,前端入门通常时 HTML/CSS/JavaScript
三板斧一把梭,最早的网站开发其实也这样,但是后面随着浏览器(或者说网站)功能越来越多,JS
的模块化成为了一种必然
早期的模块方案是 IIFE
(立即执行函数),在加载 HTML
的时候给根对象(也就是 window
)去挂载一个属性,这种方案的著名例子就是 Jquery
<script src="http://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
<script>
// window.$
$
</script>
像这种模块使用,结构如下
<head>
<script src="assets/js/jquery.js"></script>
<script src="assets/js/util.js"></script>
</head>
<body></body>
<script>
// your script
</script>
通常此类模块化只是用来抽取一些普通公共函数或者类似 Jquery
等操作 DOM
的框架,因为这个时候前端还是处于前后端分离前,例如 JSP
的编写方式
至于啥时候前后端分离还是幻想时间
2010
年 facebook
工程师提出的 bigpipe
,其中就提到了将模板引擎放到前端,也就是前后端分离
到了 2009
年 Node.js
的诞生,同时 Node.js
作者和模块管理方案(也就是 npm
)作者的结盟为,服务端 JS
带来了模块化标准 CommonJS(CJS)
(终于到本段落的主角了!),Node.js
提高了 JS
的上限,npm
丰富了 Node.js
的生态,但这个时候 JS
的模块化仍然只有后端的模块化也就是 CommonJS
,但是随着前后端分离的提出,而且 Node.js
提供了许多构建工具,前端的模块化也要来!
然后就有了一些专门为浏览器使用的库,模块化使用的就是 CommonJS
,但是在浏览器使用就编译成 IIFE
,但 CommonJS
的模块标准是同步引用,这样会阻塞我们 HTML
的渲染,因此就引发了讨论,也就是后面 AMD
出现的原因,AMD
就是基于 CommonJS
的异步的模块导入,是专门给浏览器使用的,像 RequireJS
就是基于 AMD
标准实现的一个模块加载器
使用
可以通过 Rollup
官网的在线编译器来编译得到 UMD
的格式(AMD|CommonJS
也可以!)
Rollup
是一个基于 ESM
模块方案的打包库 / 工具
// main.js
/* TREE-SHAKING */
import { cube } from './maths.js';
console.log( cube( 5 ) ); // 125
// maths.js
// This function isn't used anywhere, so
// Rollup excludes it from the bundle...
export function square ( x ) {
return x * x;
}
// This function gets included
export function cube ( x ) {
// rewrite this as `square( x ) * x`
// and see what happens!
return x * x * x;
}
最终结果就是
(function (factory) {
typeof define === 'function' && define.amd ? define(factory) :
factory();
})((function () { 'use strict';
// maths.js
// This function gets included
function cube ( x ) {
// rewrite this as `square( x ) * x`
// and see what happens!
return x * x * x;
}
/* TREE-SHAKING */
console.log( cube( 5 ) ); // 125
}));
可以看到 UMD
的实际处理就是先判断一波是不是 AMD
标准然后再去判断是不是 CommonJS
标准,从而正确的使用模块