shim 구성을 사용하는 이유와시기


97

여기 API 에서 requirejs 문서를 읽었습니다.

requirejs.config({
    shim: {
        'backbone': {
            //These script dependencies should be loaded before loading
            //backbone.js
            deps: ['underscore', 'jquery'],
            //Once loaded, use the global 'Backbone' as the
            //module value.
            exports: 'Backbone'
        },
        'underscore': {
            exports: '_'
        },
        'foo': {
            deps: ['bar'],
            exports: 'Foo',
            init: function (bar) {
                //Using a function allows you to call noConflict for
                //libraries that support it, and do other cleanup.
                //However, plugins for those libraries may still want
                //a global. "this" for the function will be the global
                //object. The dependencies will be passed in as
                //function arguments. If this function returns a value,
                //then that value is used as the module export value
                //instead of the object found via the 'exports' string.
                return this.Foo.noConflict();
            }
        }
    }
});

그러나 나는 그것의 부분을 얻지 못하고 있습니다. shim을 사용해야하는 이유와 구성 방법에 대한 설명이 더 필요합니다.

우리가 shim을 사용해야하는 이유와시기를 예를 들어 설명해주십시오. 감사.

답변:


110

shim의 주된 용도는 AMD를 지원하지 않는 라이브러리에 있지만 종속성을 관리해야합니다. 예를 들어 위의 Backbone 및 Underscore 예제에서 Backbone에 Underscore가 필요하다는 것을 알고 있으므로 다음과 같이 코드를 작성했다고 가정합니다.

require(['underscore', 'backbone']
, function( Underscore, Backbone ) {

    // do something with Backbone

}

RequireJS는 Underscore와 Backbone 모두에 대한 비동기 요청을 시작하지만 어떤 것이 먼저 돌아올 지 모르기 때문에 Backbone이로드되기 전에 Underscore로 무언가를 시도 할 수 있습니다.

참고 : 이 밑줄 / 백본 예제는 두 라이브러리가 AMD를 지원하기 전에 작성되었습니다. 그러나 원칙은 오늘날 AMD를 지원하지 않는 모든 라이브러리에 적용됩니다.

"init"훅을 사용하면 다른 고급 작업을 수행 할 수 있습니다. 예를 들어 라이브러리가 일반적으로 두 가지 다른 항목을 전역 네임 스페이스로 내보내지만 단일 네임 스페이스에서 재정의하려는 경우입니다. 또는로드중인 라이브러리의 메서드에 대해 원숭이 패치를 수행하고 싶을 수도 있습니다.

더 많은 배경 :


예제 코드와 마찬가지로, UnderscoreBackbone여기에서는 일반적인 방식으로 사용합니다 shim.이 경우에는 무엇을해야합니까? 사용할 수 있습니까 require( function() { _.extend({}); })? 이해 _합니까?
Stiger 2014-08-14

"RequireJS는 Underscore와 Backbone 모두에 대한 비동기 요청을 시작합니다."-> 라이브러리가 이미로드 된 경우이를 방지 할 수 있습니까?
Codii

1
@Codii 맞습니다. 라이브러리가 이미로드되어 있으면 다른 서버 요청이 시작되지 않지만 RequireJS의 요점은 코드가 그 일이 발생하는지 / 어떻게 발생하는지에 대해 신경 쓸 필요가 없다는 것입니다. 특정 사용 사례에 대한 새로운 질문을 시작 하시겠습니까?
explunit

63

RequireJS API 문서에 따라 shim을 사용하면

종속성을 선언하고 모듈 값을 설정하기 위해 define ()을 사용하지 않는 기존의 기존 "브라우저 전역"스크립트에 대한 종속성, 내보내기 및 사용자 정의 초기화를 구성하십시오.

-종속성 구성

2 개의 자바 스크립트 모듈 (moduleA 및 moduleB)이 있고 그중 하나 (moduleA)가 다른 하나 (moduleB)에 의존한다고 가정 해 보겠습니다. 둘 다 자신의 모듈에 필요하므로 require () 또는 define ()에 종속성을 지정하십시오.

require(['moduleA','moduleB'],function(A,B ) {
    ...
}

그러나 자체적으로 AMD를 따르도록 요구하기 때문에 어느 것이 조기에 가져올 지 알 수 없습니다. 이것은 심이 구출하는 곳입니다.

require.config({
    shim:{
       moduleA:{
         deps:['moduleB']
        } 
    }

})

이렇게하면 moduleA가로드되기 전에 항상 moduleB를 가져옵니다.

-내보내기 구성

Shim 내보내기는 RequireJS에게 전역 개체 (물론 브라우저에 있다고 가정하는 창)의 구성원이 실제 모듈 값인지 알려줍니다. moduleA가 자신을 window'modA'(jQuery와 underscore가 각각 $ 및 _ 로하는 것처럼)에 추가 하고 내보내기 값을 'modA'로 만듭니다.

require.config({
    shim:{
       moduleA:{
         exports:'modA'
        } 
    }

RequireJS에이 모듈에 대한 로컬 참조를 제공합니다. 글로벌 modA는 페이지에도 여전히 존재합니다.

-이전 "브라우저 전역"스크립트에 대한 사용자 정의 초기화

이것은 아마도 우리 자신의 모듈에서 종속성으로 '브라우저 전역', '비 AMD'스크립트 (모듈 패턴을 따르지 않음)를 추가 할 수있는 shim 구성의 가장 중요한 기능 일 것입니다.

moduleB가 funcA () 및 funcB () 함수 두 개만있는 평범한 오래된 자바 스크립트라고 가정 해 보겠습니다.

function funcA(){
    console.log("this is function A")
}
function funcB(){
    console.log("this is function B")
}

이 두 함수는 모두 창 범위에서 사용할 수 있지만 RequireJS는 혼란을 피하기 위해 전역 식별자 / 핸들을 통해 사용할 것을 권장합니다. 따라서 심을 다음과 같이 구성하십시오.

shim: {
    moduleB: {
        deps: ["jquery"],
        exports: "funcB",
        init: function () {
            return {
                funcA: funcA,
                funcB: funcB
            };
        }
    }
}

init 함수의 반환 값은 'exports'문자열을 통해 찾은 객체 대신 모듈 내보내기 값으로 사용됩니다. 이렇게하면 자체 모듈에서 funcB를 다음과 같이 사용할 수 있습니다.

require(["moduleA","moduleB"], function(A, B){
    B.funcB()
})

이것이 도움이 되었기를 바랍니다.


3
이해하기 쉬운! 한 가지 질문 : 마지막 예에서 "exports"속성이 단순히 무시됩니까?
Niko Bellic 2015 년

아니요, 무시되지 않습니다. 마지막 예제에서 "exports"속성을 무시했다면, moduleB가 AMD 규격이 아니고 RequireJS가 사용할 객체를 반환하지 않았기 때문에 매개 변수 (이 경우 'B')로 전달하는 객체는 정의되지 않습니다. 따라서 'B.funcB'는 작동하지 않습니다).
nalinc

흠. init 함수에서 반환 된 개체가 내보내기 값을 덮어 쓸 것이라고 생각했습니다. 따라서 매개 변수 B는 단순히 funcB 자체가 아니라 {funcA : funcA, funcB : funcB} 객체가됩니다. 사실이 아닙니까?
Niko Bellic 2015 년

4
Niko Bellic이 맞고 수출은 무시됩니다 (방금 테스트했습니다). Object B는 'init'부분에 지정된 함수에 의해 반환되는 객체입니다. 'init'부분을 제거하면 객체 B가 함수 funcB가되므로 B.funcB () 대신 B ()를 수행하면됩니다. 그리고 분명히 funcA는이 경우 접근 할 수 없게 될 것입니다.
user4205580

-2

선언하려면 requirejs.config에 경로를 추가해야합니다. 예 :

requirejs.config({
    paths: {
          'underscore' : '.../example/XX.js' // your JavaScript file
          'jquery' : '.../example/jquery.js' // your JavaScript file
    }
    shim: {
        'backbone': {
            deps: ['underscore', 'jquery'],
            exports: 'Backbone'
        },
        'underscore': {
            exports: '_'
        },
        'foo': {
            deps: ['bar'],
            exports: 'Foo',
            init: function (bar) {
                return this.Foo.noConflict();
            }
        }
    }
});

1
이 답변은 "shim config를 사용하는 이유와시기"를 설명하지 않는 코드 덤프입니다. 설명을 제공하기 위해 답변을 편집하는 경우 이전 답변에서 아직 다루지 않은 새로운 내용을 추가하고 있는지 확인하십시오
Louis

임의의 양의 피드백없이 복사하여 붙여
william.eyidi

shim 앞에 쉼표가 있어야합니다.
Scott
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.