자바 스크립트 모듈 로더 - 리 린의 블로그

머리말

여기에 모듈 온다!

사이트는 "인터넷 응용 프로그램"점점 더 크고 더 복잡한 웹 페이지에 포함 된 자바 스크립트 코드가되기로. 웹이 더 데스크톱 프로그램처럼, 당신은 노동, 일정 관리, 단위 테스트 부문의 팀이 필요합니다 ...... 우리는 페이지의 비즈니스 로직을 관리하는 데 사용하는 소프트웨어 엔지니어링 방법에 있습니다.

그래서, 자바 스크립트 모듈 긴급한 필요. ES6 모듈의 출현은, 자바 스크립트는 강력한 커뮤니티 지원을 제공하기 전에, 모듈의 효과를 달성하기 위해 기존 운영 환경에서 시도합니다.

CommonJS 및 노드

자바 스크립트 : 그냥 브라우저에 어떤 이상! - CommonJS Slogen

사실상의 표준 프런트 엔드 모듈 중 하나는, 2009 년 8 월, CommonJS는 출생.

CommonJS 본질적으로 단지 규격 (API 정의) 및 규격의 Node.js를 구현 부분 사용에 대한 문구 CommonJS으로 Module1 때문에 광범위한.

노드의 구현을 살펴 보자 :


    
    
1
2
3
4
5
6
7
8
9
// 由于 Node 原生支持模块的作用域,并不需要额外的 wrapper
// "as though the module was wrapped in a function"

var a = require('./a')  // 加载模块(同步加载)
a.doSomething()         // 等上一句执行完才会执行

exports.b = function(){ // 暴露 b 函数接口
  // do something
}

exportsa는 내장되어 객체처럼 require내장로드 기능 같은. 직접 할당 할 경우 완전한 객체 또는 생성자는 오버라이드 (override) module.exports를.

CommonJS는 이전에, ServerJS라는 환경의 표준화 모듈 테이크 모든 다양한 이름 CommonJS, 다음보다 일반적인 될 기대 될 . CommonJS 처음보다는 브라우저 환경보다 서버 측에 초점을 맞추고, 그 서버 환경 (디스크 I / O를 속도)는 문제가되지는 동기식로드 메커니즘을 사용하지만 브라우저 환경 (망 속도) 아니다 적절한.

따라서, 모듈 형 프레임 워크와 표준에 의해 출생에 적합, 그들은 공통적으로 가지고있는 다양한 브라우저 환경은 다음과 같습니다 :

  • 비동기 로딩 (네트워크 환경 브라우저 모든 종속 모듈의 실행 후 사전로드 콜백)
  • 다른 코딩 스타일이지만, 그러나 사실은 변형 CommonJS 모듈 구문으로 볼 수있다.
  • 우리를 향해있는 공통의 진화의 방향 : 다른 스타일 호환 브라우저와 서버 환경 모두와 호환

통상적 인 실시 예는 여기 설명 된 다음에 설명한다 :

  • RequireJS 및 AMD (비동기 로딩, - 실행을 사전에 미리 기본에 의존하는이 문구 AMD를 권장)
  • SeaJS & CMD (비동기 로딩, 게으른 실행, 근처에 의존하고, 기본 추천 CommonJS 문구)

역사

유 보의에서이 항 참조 그 시점에 프런트 엔드 모듈 개발 역사

09~10년 사이 CommonJS (다음 여전히라고 ServerJS) 지역 사회가 시작 모듈 / 1.0 사양을하고 Node.js를 환경에 아주 좋은 연습을했다.

커뮤니티 CommonJS에 자신의 이름을 변경할 수 있도록 또한, 브라우저에 성공적인 경험을 촉진 ServerJS하려고하는 사람의 2,009 동기 무리의 두 번째 절반 사양의 다음 버전의 동안 열띤 논쟁 모듈. 차이와 충돌이 태어 났으며, 점차적으로 세 가지 주요 학교를 형성 :

  1. 모듈 / 1.x의 장르. 방금 잘 브라우저에 이식만큼, 충분한되었습니다이보기 1.x의 사양. 추가되는 수행 모듈 / 전송 전송 모듈 사양에 맞춰 코드를 변환하는 제 1 변환 도구, 브라우저에서 실행하기 전에, 인 규범을. 주류 대표는 서버 측 개발자입니다. 점점 더 많은 화재 구성 요소 및 ES6 모듈 transpiler의 최전선 : 지금이 달성 주목할있다.
  2. 모듈 / 비동기 장르. 이보기는 브라우저 자체의 특성을 가지고, 모듈 / 1.x의 사양을 사용할 수 없습니다. 이보기의 전형적인 대표 아래 AMD의 규격과 그 구현 RequireJS는 . 이것은 나중에 자세히 설명.
  3. 모듈 / 2.0 장르. 이보기는 브라우저 자체의 특성을 가지고, 모듈 / 1.x의 사양을 사용하지 말아야하지만, 가능한 모듈 / 1.x의 사양과 일치해야합니다. 이보기의 전형적인 대표 아래 BravoJS 및 FlyScript의 저자이다. 지역 사회에 큰 기여 BravoJS CommonJS,이 모듈 / 2.0 초안 스펙은 생각을 많이 보냈다. FlyScript의 저자는 CMD의 전신 사양을 표준화 모듈 / 배치와 사양을 제안했다. 불행하게도 BravoJS 너무 학문적, FlyScript 나중에 조립 라인 오프 셀프 거세, 전체 사이트 (flyscript.org)가되었다. 이 문서에서이보기의 전형적인 대표 SeaJS와 CMD입니다

입 메이크업 : AMD가 매우 유사하지만,와 함께, KMD의 사실을 알리 뽀뽀를 add하고 use기능 YUI 모듈의 이름에서 파생 된 두 개의 교체 definerequire의 가까운 RequireJS을하지만, 원칙이며, YUI 모듈 Y샌드 박스에 연결 메커니즘은 동일하지 않습니다

RequireJS 및 AMD

AMD (비동기 모듈 정의) 승격 프로세스 모듈 정의 정규화 출력 RequireJS이다.

RequireJS는 자바 스크립트 파일과 모듈 로더입니다. 그것은에서 브라우저에 최적화되어 있지만, 다른 자바 스크립트 환경에서 사용할 수 있습니다

주요 문제는 여전히 브라우저이 질문에 맞지 않는 동기로드 스크립트를 CommonJS RequireJS :


    
    
1
2
3
4
5
6
7
8
9
10
11
12
//CommonJS

var Employee = require("types/Employee");

function Programmer (){
    //do something
}  

Programmer.prototype = new Employee();

//如果 require call 是异步的,那么肯定 error
//因为在执行这句前 Employee 模块肯定来不及加载进来

주석 위에서 알 수 있듯이, 경우는이 코드는하지 않습니다 일, () 비동기입니다 필요합니다. 그러나, 브라우저에서 동 기적으로 스크립트를로드하면 성능을 죽인다. 그래서 뭐 할까?

우리가 필요 그래서 포장을 함수 출세와 사전에 스크립트 태그를 통해 부하에 따라하기


    
    
1
2
3
4
5
6
7
8
9
10
11
12
13
14
//AMD Wrapper

define(
    [types/Employee],    //依赖
    function(Employee){  //这个回调会在所有依赖都被加载后才执行

        function Programmer(){
            //do something
        };

        Programmer.prototype = new Employee();
        return Programmer;  //return Constructor
    }
)

모듈이 매우 오랜 시간이 의존하는 경우,이 의존 사전에 AMD는 문법 설탕, 주신 있도록 표현은, 홀수 조금 보인다 간체 CommonJS 포장이 CommonJS에 대해서도 더 편리 CommonJS 가장 가까운 스타일을 필요에 그리기, 호환 모듈,하지만를 :


    
    
1
2
3
4
5
6
define(function (require) {
    var dependency1 = require('dependency1'),
        dependency2 = require('dependency2');

    return function () {};
});

AMD의 로더는 구문 분석됩니다 require('')사용하여 통화를 Function.prototype.toString()한 후 내부적으로 위의 정의 호출 변환 :


    
    
1
2
3
4
5
6
define(['require', 'dependency1', 'dependency2'], function (require) {
    var dependency1 = require('dependency1'),
        dependency2 = require('dependency2');

    return function ()  大专栏  JavaScript Module Loader - 李林的博客{};
});

대한 Function.prototype.toString()호환성과 성능을 고려하여, 가장 좋은 방법은하는 것입니다 최적화 된 빌드

AMD와 CommonJS 핵심 분쟁은 다음과 같습니다 :

1. 执行时机

Modules/1.0:


    
    
1
var a = require("./a") // 执行到此时,a.js 才同步下载并执行

AMD: (使用 require 的语法糖时)


    
    
1
2
3
4
5
define(["require"],function(require)){
    // 在这里,a.js 已经下载并且执行好了
    // 使用 require() 并不是 AMD 的推荐写法
    var a = require("./a") // 此处仅仅是取模块 a 的 exports
})

AMD 里提前下载 a.js 是出于对浏览器环境的考虑,只能采取异步下载,这个社区都认可(Sea.js 也是这么做的)

但是 AMD 的执行是 Early Executing,而 Modules/1.0 是第一次 require 时才执行。这个差异很多人不能接受,包括持 Modules/2.0 观点的人也不能接受。

2. 书写风格

AMD 推荐的风格并不使用require,而是通过参数传入,破坏了依赖就近


    
    
1
2
3
4
5
define(["a", "b", "c"],function(a, b, c){
    // 提前申明了并初始化了所有模块

    true || b.foo(); //即便根本没用到模块 b,但 b 还是提前执行了。
})

不过,在笔者看来,风格喜好因人而异,主要还是预执行懒执行的差异。

另外,require 2.0 也开始思考异步处理软依赖(区别于一定需要的硬依赖)的问题,提出了这样的方案:


    
    
1
2
3
4
5
6
// 函数体内:
if(status){
    async(['a'],function(a){
        a.doSomething()
    })
}

SeaJS & CMD

CMD (Common Module Definition) 是 SeaJS 在推广过程中对模块定义的规范化产出,是 Modules/2.0 流派的支持者,因此 SeaJS 的模块写法尽可能与 Modules/1.x 规范保持一致。

不过目前国外的该流派都死得差不多了,RequireJS 目前成为浏览器端模块的事实标准,国内最有名气的就是玉伯的 Sea.js ,不过对国际的推广力度不够。

CMD 主要有 define, factory, require, export 这么几个东西

  • define define(id?, deps?, factory)
  • factory factory(require, exports, module)
  • require require(id)
  • exports Object

CMD 推荐的 Code Style 是使用 CommonJS 风格的 require

  • 这个 require 实际上是一个全局函数,用于加载模块,这里实际就是传入而已

    
    
1
2
3
4
5
6
7
8
9
10
11
12
13
define(function(require, exports) {

    // 获取模块 a 的接口
    var a = require('./a');
    // 调用模块 a 的方法
    a.doSomething();

    // 对外提供 foo 属性
    exports.foo = 'bar';
    // 对外提供 doSomething 方法
    exports.doSomething = function() {};

});

但是你也可以使用 AMD 风格,或者使用 return 来进行模块暴露


    
    
1
2
3
4
5
6
7
8
9
10
11
define('hello', ['jquery'], function(require, exports, module) {

    // 模块代码...

    // 直接通过 return 暴露接口
    return {
        foo: 'bar',
        doSomething: function() {}
    };

});

Sea.js 借鉴了 RequireJS 的不少东西,比如将 FlyScript 中的 module.declare 改名为 define 等。Sea.js 更多地来自 Modules/2.0 的观点,但尽可能去掉了学院派的东西,加入了不少实战派的理念。

AMD vs CMD

虽然两者目前都兼容各种风格,但其底层原理并不相同,从其分别推荐的写法就可以看出两者背后原理的不同:

  1. 对于依赖的模块,AMD 是提前执行,CMD 是懒执行。(都是先加载)
    • CMD 推崇依赖就近,AMD 推崇依赖前置

看代码:


    
    
1
2
3
4
5
6
7
8
9
// AMD 默认推荐

define(['./a', './b'], function(a, b) {  // 依赖前置,提前执行

    a.doSomething()
    b.doSomething()

})


    
    
1
2
3
4
5
6
7
8
9
10
// CMD

define(function(require, exports, module) {

    var a = require('./a')
    a.doSomething()

    var b = require('./b') // 依赖就近,延迟执行
    b.doSomething()
})

WebPack

working…



추천

출처www.cnblogs.com/lijianming180/p/12401914.html