关于类库的umd化简单介绍

in 技术 with 0 comment

写在前面

模块化这个概念出现在 js 应用中已经很久了了,在es-module 规范发布以前的在很长的一段时间里大家都在讨论使用怎样的模块化规范来组织自己臃肿的 js 代码,其中最流行主流的规范当属被 node 支持的同步CommonJS规范,以require.js为代表的异步AMD规范和以sea.js为代表的异步CMD规范。而接下来要介绍的umd(Universal Module Definition)规范其实是为了兼容各种规范的一种方案,使我们的模块在多种规范环境下都可以适配使用。

示例

实际上,根据开发者需求的不同,umd 所表现的形式也有不同的变种,官方给出了一些模板,大家可以参考。下面的示例均选取了普遍的兼容 amd,commonjs 和 web 的情况:

AMD 模块

// 这是一个无依赖的匿名AMD模块
define([], function() {
  // do something...
  var module = {
    name: 'exampleModule',
    msg: 'hey, this is exampleModule'
  };
  return module;
});
(function (root, factory) {
    if (typeof define === 'function' && define.amd) {
        // AMD. Register as an anonymous module.
        define([], factory);
    } else if (typeof module === 'object' && module.exports) {
        // Node/CommonJS
        module.exports = factory();
    } else {
        // Browser
        // 这里如果不太明白下面root的输出,可以搜索学习一下js的短路评估
        root = root || self || global;

        root.exampleModule = factory(jQuery);
    }(this, function() {
        // do something...
        var module = {
            name: 'exampleModule',
            msg: 'hey, this is exampleModule'
        };
        return module;
    }));
}

CommonJS 模块

// 这是一个无依赖的CommonJS模块
var exampleModule = {
  name: 'exampleModule',
  msg: 'hey, this is exampleModule'
};

module.exports = exampleModule;

与上文 AMD 模块转化完成后相同

全局模块

// 这是一个无依赖的全局模块
(function(root) {
  var module = {
    name: 'exampleModule',
    msg: 'hey, this is exampleModule'
  };

  root.exampleModule = module;
})(window);

与上文 AMD 模块转化完成后相同

需要注意的是,这里的示例其实只是很多种情况中的一种,大家可以在理解概念以后自发的去拓展有依赖的场景下 umd 化,多导出的场景下 umd 化等等,如果理解了这些概念,那么即使是比较复杂的情况,做起转化来也是比较轻松的。

后记

tc39 已经为我们推出了原生的模块规范,使用 umd 的场景随着历史的发展一定会越来越少,但是在需要直接用到具有一定年代的不同模块规范的 js 库时,umd 规范仍将起到一个承上启下的作用,我们甚至可以将它导入到我们的 es6 项目中,webpack 和 rollup 工具在打包的时候也都有自己的方式来对此进行支持。

相关链接

Responses