CommonJS, AMD와 RequireJS의 관계는 무엇입니까?


840

많이 읽은 후에도 CommonJS, AMDRequireJS 에 대해 여전히 혼란 스럽습니다 .

CommonJS (이전의 ServerJS )는 언어가 브라우저 외부에서 사용될 때 JavaScript 사양 (예 : 모듈) 을 정의하기위한 그룹 이라는 것을 알고 있습니다. CommonJS 모듈 사양에는 Node.js 또는 RingoJS 와 같은 구현이 있습니다.

CommonJS , 비동기식 모듈 정의 (AMD) 및 RequireJS 의 관계는 무엇입니까 ?

RequireJS는 의 구현 CommonJS의 모듈 정의? 그렇다면 AMD 는 무엇입니까?


31
requirejs.org/docs/whyamd.html 을 읽으면 모든 내용을 언급하는 것처럼 많은 내용 이 명확 해집니다. (나는 이것이 완전한 답변이라고 생각하지 않기 때문에 의견으로 게시).
mmutilva

5
더 묻거나 추가 할 수 있습니까? ES2015 수입 명세서는 이들 모두에 어떻게 또는 어디에 적용됩니까? 예 : 'ember'에서 Ember 가져 오기;
testndtv

(CommonJS, UMD, AMD, ES6)와 같은 지원되는 JS 모듈 형식을로드하는 systemjs도 있습니다.
Andy

답변:


770

RequireJSAMD API (소스)를 구현합니다 .

CommonJSexports모듈 컨텐츠를 정의 하는 오브젝트 의 도움으로 모듈을 정의하는 방법입니다 . 간단히 말해 CommonJS 구현은 다음과 같이 작동 할 수 있습니다.

// someModule.js
exports.doSomething = function() { return "foo"; };

//otherModule.js
var someModule = require('someModule'); // in the vein of node    
exports.doSomethingElse = function() { return someModule.doSomething() + "bar"; };

기본적으로 CommonJS는 require()종속성을 가져 오기 위한 함수, exports모듈 컨텐츠를 내보내는 변수 및 종속성을 요구하는 데 사용되는 모듈 식별자 (이 모듈과 관련하여 문제가있는 모듈의 위치를 ​​설명하는)가 있어야 함을 지정합니다 ( source ). CommonJS에는 Node.js를 포함하여 다양한 구현 이 있습니다.

CommonJS는 브라우저를 염두에두고 특별히 설계되지 않았으므로 브라우저 환경에 잘 맞지 않습니다 ( 실제로 소스가 없습니다 . RequireJS 사이트를 포함 하여 모든 곳에서 사용 가능 합니다 ) . 비동기 로딩 등으로 수행

반면에 RequireJS는 브라우저 환경 ( source ) 에 맞게 설계된 AMD를 구현 합니다. 분명히, AMD는 CommonJS Transport 형식의 분사로 시작하여 자체 모듈 정의 API로 발전했습니다. 따라서 둘 사이의 유사점. AMD의 새로운 기능 define()은로드하기 전에 모듈이 종속성을 선언 할 수 있도록하는 기능입니다. 예를 들어, 정의는 다음과 같습니다.

define('module/id/string', ['module', 'dependency', 'array'], 
function(module, factory function) {
  return ModuleContents;  
});

따라서 CommonJS와 AMD는 구현이 서로 다른 JavaScript 모듈 정의 API이지만 둘 다 동일한 출처에서 나옵니다.

  • AMD 는 모듈 종속성의 비동기 로딩을 지원하므로 브라우저에 더 적합합니다.
  • RequireJSAMD 의 구현이며 , 동시에 CommonJS 의 정신 (주로 모듈 식별자) 을 유지하려고합니다 .

RequireJS는 AMD를 구현하는 동안 CommonJS 래퍼를 제공하므로 RequireJS와 함께 사용하기 위해 CommonJS 모듈을 거의 직접 가져올 수 있습니다.

define(function(require, exports, module) {
  var someModule = require('someModule'); // in the vein of node    
  exports.doSomethingElse = function() { return someModule.doSomething() + "bar"; };
});

이것이 문제를 명확히하는 데 도움이되기를 바랍니다.


7
두 가지 형식의 격차를 메우는 uRequire.org 프로젝트를 확인하십시오 – 둘 중 하나를 쓰거나 두 가지 간단한 <script> 중 하나에 배포하십시오
Angelos Pikoulas

51
FYI Browserify 는 이제 브라우저에서 CommonJS를 사용할 수있게합니다.
Eruant

9
@Eruant 그러나 여전히 AMD와 같은 비동기식은 아닙니다.
Inanc Gumus

8
RequireJS 문서에 언급 된대로 CommonJS가 브라우저에 맞지 않는 이유- "CommonJS require ()는 동기 호출이므로 모듈을 즉시 리턴 할 것으로 예상됩니다. 브라우저에서 제대로 작동하지 않습니다 . " 자세한 내용은 여기를 참조하십시오 .
msenni

4
@aaaaaa 사용자 요청에 따라 일부 기능을 활성화 할 수 있습니다. 따라서 AMD의 비동기 특성이 유용 할 수 있습니다.
Inanc Gumus

199

CommonJS 는 그 이상입니다. JavaScript를위한 공통 API와 에코 시스템을 정의하는 프로젝트입니다. CommonJS의 한 부분은 모듈 스펙입니다. Node.js 및 RingoJS는 서버 측 JavaScript 런타임이며, 둘 다 CommonJS 모듈 스펙을 기반으로 모듈을 구현합니다.

AMD (비동기 모듈 정의)는 모듈의 또 다른 사양입니다. RequireJS 는 아마도 가장 널리 사용되는 AMD의 구현 일 것입니다. CommonJS와의 주요 차이점은 AMD가 모듈이 비동기식 으로로드되도록 지정한다는 것 입니다. 즉,로드가 완료 될 때까지 대기하여 실행을 차단하는 대신 모듈이 병렬로로드됩니다.

AMD는 일반적으로 이로 인해 클라이언트 측 (브라우저) JavaScript 개발에 더 많이 사용되며 CommonJS 모듈은 일반적으로 서버 측에 사용됩니다. 예를 들어, RequireJS 제공의 - 그러나, 당신은 어느 환경에서 각 모듈의 사양을 사용할 수 있습니다 Node.js를 실행하기위한 방향browserify는 브라우저에서 실행할 수있는 CommonJS 모듈 구현입니다.


20
CommonJS 홈페이지가 왜 그렇게 끔찍한가 ... 나는 단지 공식적인 사양을 보려고합니다. 구문 오류가 있고 문서가 불완전하며 위키 페이지가 해결되지 않습니다.
taco

7
그것은 모듈을 비동기 적으로로드한다는 의미가 아닙니다. 동적 / 지연 로딩에 대해 이야기하고있을 수 있습니다. 비동기를 사용하면 파일을로드 할 것을 제안한 다음 나중에로드가 완료되면 다시 호출됩니다. sync를 사용하면로드 할 파일을 제안한 다음 해당 파일로드가 완료 될 때까지 전체 스레드가 차단됩니다. 파일이로드 될 때까지 더 이상 코드가 실행되지 않습니다. 전자는 예측할 수없는 비용으로 더 나은 성능을 제공 할 수있는 반면 후자는 매번 동일한 결과를 산출 할 수 있으므로 더 예측 가능합니다. 이러한 단점은 다양한 최적화를 통해 완화 될 수 있습니다.
perry

답변 해주셔서 감사합니다. 이제 ES2015와 함께 JS에서 모듈이 공식화되었으므로 AMD 또는 일반적인 JS보다 더 많은 모듈이 선호됩니까?
Akhoy

그들이 선호한다는 것을 의미하지는 않습니다. 모두 개발자의 요구에 달려 있습니다. 옵션을 남기지 않고 ES6 모듈을 사용하는 것이 특히 좋은 생각이라고 생각하지 않습니다. 그러나 좋은 UMD를 사용하면 해당 문제를 해결할 수 있습니다. AMD와 동기화 된 CommonJS 번들을로드하는 것이 일반적으로 (성능 향상을위한) 좋은 아이디어입니다. 더 많은 통제력이 필요하다고 느끼면 분명히. 그리고 당신은해야합니다.
Maciej Sitko 12

187

짧은 대답은 다음과 같습니다.

CommonJS AMD 는 자바 스크립트 응용 프로그램에서 모듈과 해당 종속성을 선언하는 방법에 대한 사양 (또는 형식)입니다.

RequireJS 는 AMD와 호환되는 스크립트 로더 라이브러리이며 curljs 가 또 다른 예입니다.

CommonJS 준수 :

Addy Osmani의 책 에서 발췌 .

// package/lib is a dependency we require
var lib = require( "package/lib" );

// behavior for our module
function foo(){
    lib.log( "hello world!" );
}

// export (expose) foo to other modules as foobar
exports.foobar = foo;

AMD 호환 :

// package/lib is a dependency we require
define(["package/lib"], function (lib) {

    // behavior for our module
    function foo() {
        lib.log( "hello world!" );
    }

    // export (expose) foo to other modules as foobar
    return {
        foobar: foo
    }
});

다른 곳에서 모듈을 사용할 수 있습니다 :

require(["package/myModule"], function(myModule) {
    myModule.foobar();
});

일부 배경 :

실제로 CommonJS 는 API 선언 그 이상이며 그 일부만 처리합니다. AMD는 CommonJS 목록에서 모듈 형식에 대한 초안 사양으로 시작했지만 완전한 합의에 도달하지 못했으며 형식의 추가 개발이 amdjs 그룹 으로 이동했습니다 . CommonJS가 광범위한 관심사를 다루려고 시도하고 동 기적 특성을 고려하여 서버 측 개발에 더 적합하고 AMD가 비동기 적 특성 및 사실 Dojo의 모듈 선언 구현에 뿌리가 있습니다.

출처 :


1
설명보다는 코드를 보는 것이 도움이됩니다! :) AMD compliant실제로 RequireJS입니까?
Asim KT

내가 누락되었거나 잘못 입력 한 것이 있습니까? "package / lib"를 정의한 다음 "package / myModule"이 필요합니다.
RullDawg

나는 왜 무언가가 왜 그런지에 대한 역사를 조금 읽고 싶습니다! 그 배경을 제공해 주셔서 감사합니다!
Andru

@RullDawg 아니요, "package / lib"는 여기에 정의되어 있지 않으며 여기에서 사용되는 타사 종속성 입니다.
Robert Siemer

28

인용

AMD :

  • 하나의 브라우저 우선 접근
  • 비동기 동작 선택 및 이전 버전과의 호환성 단순화
  • File I / O라는 개념이 없습니다.
  • 객체, 함수, 생성자, 문자열, JSON 및 기타 여러 유형의 모듈을 지원합니다.

CommonJS :

  • 하나의 서버 우선 접근
  • 동기 동작 가정
  • I / O, 파일 시스템, 약속 등과 같은 광범위한 문제를 다룹니다.
  • 래핑되지 않은 모듈을 지원하며 ES.next/Harmony 사양에 약간 더 가깝게 느껴지므로 define () 래퍼가 필요 없습니다 AMD.
  • 객체를 모듈로만 지원하십시오.

17

JavaScript 프로그램을 모듈 식으로 여러 파일로 구성하고에서 호출 child-modules하는 것이 일반적 main js module입니다.

문제는 JavaScript가 이것을 제공하지 않는다는 것입니다. 최신 브라우저 버전의 Chrome 및 FF에서는 오늘날에도 마찬가지입니다.

그러나 JavaScript에 다른 JavaScript 모듈을 호출하는 키워드가 있습니까?

이 질문은 답이 ' 아니오' 이기 때문에 많은 사람들에게 완전히 붕괴되었을 수 있습니다 .


ES5 (2009 년에 릴리스)에서 JavaScript는 다음과 같은 키워드를 갖지 않았습니다. import , include 또는 require .

ES6는 가져 오기 키워드를 제안하는 날 (2015 년에 릴리스 됨)을 저장 하지만 ( https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Statements/import ) 브라우저에서이를 구현하지 않습니다.

Babel 6.18.0을 사용하고 ES2015 옵션 만 사용하는 경우

import myDefault from "my-module";

당신은 require다시 얻을 것이다 .

"use strict";
var _myModule = require("my-module");
var _myModule2 = _interopRequireDefault(_myModule);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

이는 require모듈이 Node.js에서로드됨을 의미 하기 때문 입니다. Node.js는 시스템 레벨 파일 읽기에서 함수를 모듈로 랩핑하는 것까지 모든 것을 처리합니다.

JavaScript 함수는 모듈을 나타내는 유일한 래퍼이기 때문입니다.

CommonJS와 AMD에 대해 많은 혼란이 있습니까?

CommonJS와 AMD는 모두 JavaScript "결함"을 극복하여 모듈을 스마트하게로드하는 방법에 대한 두 가지 기술입니다.


3
이제 모든 때문에 답변을 업데이트해야합니다 최신 브라우저 지원 import
수직 동기화

@vsync, 예, 한동안이 세그먼트를 따르지 않았으므로 자유롭게 답변을 편집하십시오.
prosti
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.