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

더 많은 배경 :


예제 코드와 마찬가지로, Underscore및 Backbone여기에서는 일반적인 방식으로 사용합니다 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.