V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐关注
Meteor
JSLint - a JavaScript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
JavaScript 权威指南第 5 版
Closure: The Definitive Guide
bramblex
V2EX  ›  JavaScript

同时兼容 AMD, CommandJS 和全局变量的模块化定义的一个通用实现

  •  
  •   bramblex · 2015-07-10 12:10:29 +08:00 · 3717 次点击
    这是一个创建于 3424 天前的主题,其中的信息可能已经有所发展或是发生改变。

    最近围观了一下UMD,发现虽然不错,但是其实并不是非常通用,所以自己尝试折腾了一个来玩玩,发现还不错,就拿来给大家围观一下。水平渣渣,请轻拍。

    先不废话,先看个实例。一共是三个文件,example.js、lib1.js和lib2.js。其中example.js依赖lib1.js和lib2.js,同时也就是意味着example模块依赖lib1模块和lib2模块。

    -
    |-example.js
    |-lib1.js
    |-lib2.js
    

    首先,来看看example.js。如下所示,example.js定义一个example模块输出"example",并且调用lib1()和lib2(),依赖当前目录下的lib1模块和lib2模块。

    //example.js
    (function (r, n, d, f) {
      if (typeof define === 'function' && define.amd)
        define(n, d, f);
      else if (typeof exports === 'object')
        module.exports = f.apply(r, d.map(function(m){return require(m)}));
      else
        r[n] = f.apply(r, d.map(function(m){return r[m]}));
    }(this, 'example', ['./lib1', './lib2'], function (lib1, lib2) {
    
      var myFunc = function myFunc(){
        console.log('example');
        lib1();
        lib2();
      };
    
      return myFunc;
    }));
    

    接下来是lib1.js和lib2.js。下面是lib1.js的代码,定义一个lib1模块输出"lib1",没有依赖。lib2.js的代码一样,定义一个lib2模块,输出"lib2"。

    // lib1.js
    (function (r, n, d, f) {
      if (typeof define === 'function' && define.amd)
        define(n, d, f);
      else if (typeof exports === 'object')
        module.exports = f.apply(r, d.map(function(m){return require(m)}));
      else
        r[n] = f.apply(r, d.map(function(m){return r[m]}));
    }(this, 'lib1', [], function () {
    
      var myFunc = function myFunc(){
        console.log('lib1');
      };
    
      return myFunc;
    }));
    

    来,最后来看看效果。

    //在node里加载
    var example = require('./example');
    example();
    
    //在浏览器中使用require.js加载
    require(['example'], function(example){example();});
    
    <!-- 在浏览器中通过script标签加载 -->
    <script src="lib1.js"></script>
    <script src="lib2.js"></script>
    <script src="example.js"></script>
    <script>
      example();
    </script>
    

    上面三种方式都能正确输出如下结果

    //=> "example"
    //=> "lib1"
    //=> "lib2"
    
    第 1 条附言  ·  2015-07-10 13:17:38 +08:00
    因为代码是从老版本那里复制出来的,所以出了一点问题。
    修改为 r[n] = f.apply(r, d.map(function(m){return r[m.replace(/^.*\//, '')]})); 才对
    9 条回复    2015-07-12 16:57:44 +08:00
    magicdawn
        1
    magicdawn  
       2015-07-10 21:35:47 +08:00
    umd 哪里不通用请说明...
    amrio
        2
    amrio  
       2015-07-11 09:15:06 +08:00 via iPhone
    你这不支持 CJS 啊,UMD 都没你这绕 ┑( ̄Д  ̄)┍
    bramblex
        3
    bramblex  
    OP
       2015-07-11 10:21:06 +08:00
    @amrio

    1. 支持 CommandJS 你可以自己测试一下。我在node里面跑的无压力。我不支持的是CMD……不过感觉CMD有些坑,正在想办法加通用壳。

    2. 你该不会觉得你要手写这大串蛋疼东西吧?我折腾这套通用壳就是为了让它足够通用到直接用工具包装一下就能用的程度。这种重复无聊的工作请留给机器做。

    昨晚已完成把一个AMD模块直接包装成UMD模块的工具,我从来没想过这种蛋疼的东西需要人手工来做。 https://github.com/bramblex/UMDT
    bramblex
        4
    bramblex  
    OP
       2015-07-11 10:23:50 +08:00
    @magicdawn

    我说的不通用并不是指标准不通用,而是代码不通用。不能简单的进行转换,仅此而已。

    我现在选用AMD做基准,然后通过用工具加通用壳来保证一处编写,到处运行的目的。而不需要到处写一大段重复代码。
    bramblex
        5
    bramblex  
    OP
       2015-07-11 11:10:33 +08:00
    @amrio
    @magicdawn

    最新的代码模板,只需要把AMD模块套上这个壳,就可以同时兼容AMD,CommandJS和全局变量加载了,不需要多谢一行代码 https://github.com/bramblex/UMDT/blob/master/template
    amrio
        6
    amrio  
       2015-07-11 11:59:06 +08:00   ❤️ 1
    @bramblex 好吧,我想说的就是 CMD。要支持其实不复杂,CMD 也是支持 `define(deps, factory)` 的,只不过 `factory` 的实参是 `require, exports, module`

    代码:

    ``` js
    if (typeof __define__ === 'function' && __define__.cmd) {
    __define__(dependencies, function (require, exports, module) {
    module.exports = factory.apply(__root__, dependencies.map(function(m){
    return require(m);
    }));
    })
    }```

    简单测了下,没啥问题
    bramblex
        7
    bramblex  
    OP
       2015-07-11 13:00:29 +08:00
    @amrio

    我加上试试OwO ,谢啦~~~
    sodatea
        8
    sodatea  
       2015-07-12 08:27:19 +08:00 via iPhone
    CommonJS 不是 CommandJS……
    bramblex
        9
    bramblex  
    OP
       2015-07-12 16:57:44 +08:00 via Smartisan T1
    @sodatea
    嗯…打错了
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1331 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 17:42 · PVG 01:42 · LAX 09:42 · JFK 12:42
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.