Web端JavaScript模块化的历史是什么样子的?
发布于 12 年前 作者 island205 6915 次浏览 最后一次编辑是 8 年前

Web端JavaScript模块化并不是横空出世,凭空捏造的,目前的这些SeaJS,RequireJS,AMD以及CMD标准是怎么形成的呢?

14 回复

感觉dojo是比较早模块化的,然后yui3也开始模块化了。标准都是晚于这些探索者,而SeaJS和RequireJS则是提供了基于某些标准的实现。标准被广泛接受之后,又影响到dojo之类的框架。 我最早接触到的模块化解决方案是国内的JSI,比以上所有这些都要更早。

确实,之前我只用extjs,后来接触dojo的时候发现他提供了require方法,dojo也是之前很早发行的,所以想想应该是比较早的

@imzshh @aa272121742 Web端JavaScript模块化并不是横空出世,凭空捏造的,目前的这些SeaJS,RequireJS,AMD以及CMD标准是怎么形成的呢?

据我所知,Web端的模块化并不是一开始就有的。泛泛地讲,jQuery其实也是一个模块,通过全局与其他模块(业务模块)通信;

Dojo是一个比较重的库,Dojo的开发者开发Loader来加载和组织Dojo的脚本;但初期的Dojo Loader是采用同步的XHR加载的,不能加载不同域下的模块,且性能不行;Loader的主要贡献者James Burke开发了Dojo XD Loader,采用script标签的方式,可以加载其他域下的模块。由于Dojo的历史原因和Dojo模块的复杂性(国际化)James开始开发一个叫做RunJS的独立模块加载器;

其实同时代还有其他一些脚本加载器,比如LABjs,Twitter都在使用,它以并行加载高性能为优。模块化加载并不是一开始就有的,最开始,更多的是脚本加载器。

James在开发RunJS的同时,CommonJS标准制定出来,且由NodeJS加以实现。当然NodeJS的模块无法直接在浏览器中使用(require()),于是James在CommonJS社区中给出了自己Web端的模块定义提案(其实同时其他人也给出了提案,而且我觉得不比他的查),主要就是从Dojo Loader中借用过来的,RunJS实现的接口。再不断交流和摸索过程中,逐渐形成了AMD规范,James把RunJS更名为了RequireJS,继续实现并支持AMD。但AMD并不是完美无缺的。

SeaJS是淘宝的玉伯开发的,我想是脱胎于Kissy,而在KIssy之前,淘宝是在使用YUI的,YUI3实现了seed模式的模块加载器,很多东西来自于Dojo。

虽然看到过JSI一些相关的信息,但具体就不太清楚了,有没有相关的文档?

谢谢你的回复,学到了新的东西。

JSI太小众,作者比较低调,文档也比较少。如果就想要一个模块加载方案的话,那就seaJS或者requireJS吧。。。

@imzshh JSI估计就没流行起来过,我主要是想了解一下历史

以前用RequireJS,现在放弃不用了,文本合并压缩一下一个更好

可以模块化开发,压缩打包上线。

@island205 CoffeeScript browser端里用的是什么?看也有require?

@logicthink 难道是 browserify… 我都怀疑 Jade 和 Stylus 也是用这东西做的 有一次看 Jade 的那个浏览器断脚本, 里面有 require… 然后有一次看视频里演示在浏览器端用 Node 的模块, 就这个命令

@logicthink 这个问题稍稍有点复杂。不过可以看这里:https://github.com/jashkenas/coffee-script/blob/master/Cakefile#LC97。

首先,CoffeeScript的源码是Node.js,即有require exports什么的,那怎么把这些代码包裹起来在客户端使用呢,下面是CoffeeScript的方法,给浏览器用到coffee-script.js的整体结构:

(function (root) {
    var CoffeeScript = function () {
        function require(path) {
            return require[path];
        }
        require['./helpers'] = new function () {
            var exports = this;
            (function () {
                var extend, flatten, _ref;

                exports.starts = function (string, literal, start) {
                    return literal === string.substr(start, literal.length);
                }

            }).call(this);

        };
        /* ..... */
        /* require ['./coffee-script'] = new function(){} */
        /* ..... */
        return require['./coffee-script'];
    }();

    if (typeof define === 'function' && define.amd) {
        define(function () {
            return CoffeeScript;
        });
    } else {
        root.CoffeeScript = CoffeeScript;
    }
}(this))

它使用了型如:

require['./helpers'] = new function () {
    var exports = this;
    (function () {
        //node code start
        var extend, flatten, _ref;

        exports.starts = function (string, literal, start) {
            return literal === string.substr(start, literal.length);
        }
        //node code end

    }).call(this);

};

把每一个node文件打包到了客户端。虽然有出现require这个关键字,但是并没有采用什么框架,而只是一个共享的命名空间,来在各个node文件之间共享,传递模块。

另外一方面:

if (typeof define === 'function' && define.amd) {
    define(function () {
        return CoffeeScript;
    });
} else {
    root.CoffeeScript = CoffeeScript;
}

这段代码就是让coffee-script.js兼容AMD模块标准,可以使用AMD加载器来加载。

回到顶部