requireJS와 jQuery를 함께 사용하려면 어떻게해야합니까?


82

requireJS를 사용하고 싶습니다. jQuery를 사용하고 있습니다. 최신 jQuery 버전을 사용하지 않기 때문에 requireJS와 jQuery의 결합 된 버전을 사용하고 싶지 않습니다. requireJS로 작업하는 가장 좋은 방법은 무엇입니까?


2
최신 jQuery를 사용하지 못하는 이유는 무엇입니까?
Incognito

jQuery 1.3.8을 사용하고 있습니다. 이 버전은 1.4.X와 약간 다르게 작동합니다. 최신 jQuery를 사용하려면 일부 코드를 업데이트해야하는데 지금은 그럴 시간이 없습니다. 게다가 나는 패키지를 결합하는 것이 옳다고 생각하지 않습니다.
Naor

아래의 대답은 좋습니다 .. 왜 올바른 것으로 표시하지 않았습니까?
죄수 ZERO

@Prisoner ZERO : 솔직히, 나는 그것을 테스트하지 못했습니다. 최근에는 Microsoft의 ajax 스크립트 로더를 사용했습니다. 이 답변에 표시하도록 상기시켜 주셔서 감사합니다. 당신이 그것이 훌륭하다고 말했다면-나는 당신을 믿습니다.
Naor

또한 requirejs는 다른 라이브러리와 함께 사용하기가 어렵고 그 반대의 경우도 마찬가지입니다. 그래서 훨씬 사용하기 쉽고 각도로 테스트되는 라이브러리를 만들었습니다. 하단에 데모 애플리케이션이 있습니다. gngeorgiev.github.io/Modulerr.js 또한 Modulerr.js에 대한 종속성없이 모든 스크립트를 하나로 결합 할 수 있습니다
Georgi-it

답변:


130

그것은 내 정확한 질문이기도합니다! 또한 이전 jQuery를 사용해야하지만 더 "전통적인"자바 스크립트 라이브러리도 사용해야합니다. 이를 수행하는 가장 좋은 기술은 무엇입니까? (괜찮으 시다면 질문을 더 광범위하게 수정하실 수 있습니다.) 제가 배운 내용은 다음과 같습니다.

RequireJS 작성자 인 James Burke 는 결합 된 RequireJS + jQuery 파일장점을 설명했습니다 . 두 가지가 있습니다.

  1. , 모듈을 jquery사용할 수 있으며 이는 jQuery 객체입니다. 이것은 안전합니다.

    // My module depends on jQuery but what if $ was overwritten?
    define(["jquery"], function($) {
      // $ is guaranteed to be jQuery now */
    })
    
  2. jQuery를 이미 어떤 전에로드 require()또는 define()물건. 모든 모듈은 jQuery가 준비되었음을 보장합니다. require/order.jsjQuery는 기본적으로 먼저로드하도록 하드 코딩되었으므로 플러그인이 필요하지 않습니다 .

나에게 # 2는별로 도움이되지 않는다. 대부분의 실제 응용 프로그램이 많은 .js 파일이 있어야 올바른 순서 - 슬프지만 진실에로드합니다. Sammy 또는 Underscore.js가 필요하면 결합 된 RequireJS + jQuery 파일이 도움이되지 않습니다.

내 솔루션은 "order"플러그인을 사용하여 기존 스크립트를로드하는 간단한 RequireJS 래퍼를 작성하는 것입니다.

내 앱에 이러한 구성 요소가 있다고 가정합니다 (종속성).

  • 내 앱, greatapp
    • greatapp은 사용자 정의 jquery (사용해야하는 이전 버전) 에 의존 합니다.
    • greatapp은 my_sammy (SammyJS와 내가 사용해야하는 모든 플러그인) 에 의존 합니다. 다음은 순서에 있어야합니다
      1. my_sammy는 jquery에 의존합니다 (SammyJS는 jQuery 플러그인입니다).
      2. my_sammy는 sammy.js에 의존합니다 .
      3. my_sammy는 sammy.json.js에 의존합니다 .
      4. my_sammy는 sammy.storage.js에 의존합니다 .
      5. my_sammy는 sammy.mustache.js에 의존합니다 .

제 생각에는 위의 모든 것이 .js"전통적인"스크립트입니다. 없는 모든 것은 .jsRequireJS 플러그인입니다. 핵심은 높은 수준의 항목 (greatapp, my_sammy)이 모듈이며 더 깊은 수준에서는 기존 .js파일로 대체된다는 것 입니다.

부팅

모든 것은 RequireJS가 시작하는 방법을 알려주는 부팅기로 시작됩니다.

<html>
  <head>
    <script data-main="js/boot.js" src="js/require.js"></script>
  </head>
</html>

에서 js/boot.js나는 단지 설정하는 방법과 응용 프로그램을 시작했습니다.

require( // The "paths" maps module names to actual places to fetch the file.
         // I made modules with simple names (jquery, sammy) that will do the hard work.
         { paths: { jquery: "require_jquery"
                  , sammy : "require_sammy"
                  }
         }

         // Next is the root module to run, which depends on everything else.
       , [ "greatapp" ]

         // Finally, start my app in whatever way it uses.
       , function(greatapp) { greatapp.start(); }
       );

주요 응용

에서 greatapp.js나는 정상적인보고 모듈이있다.

define(["jquery", "sammy"], function($, Sammy) {
  // At this point, jQuery and SammyJS are loaded successfully.
  // By depending on "jquery", the "require_jquery.js" file will run; same for sammy.
  // Those require_* files also pass jQuery and Sammy to here, so no more globals!

  var start = function() {
    $(document).ready(function() {
      $("body").html("Hello world!");
    })
  }

  return {"start":start};
}

기존 파일 주변의 RequireJS 모듈 래퍼

require_jquery.js:

define(["/custom/path/to/my/jquery.js?1.4.2"], function() {
  // Raw jQuery does not return anything, so return it explicitly here.
  return jQuery;
})

require_sammy.js:

// These must be in order, so use the "order!" plugin.
define([ "order!jquery"
       , "order!/path/to/custom/sammy/sammy-0.6.2-min.js"
       , "order!/path/to/custom/sammy/plugins/sammy.json-0.6.2-min.js"
       , "order!/path/to/custom/sammy/plugins/sammy.storage-0.6.2-min.js"
       , "order!/path/to/custom/sammy/plugins/sammy.mustache-0.6.2-min.js"
       ]

       , function($) {
           // Raw sammy does not return anything, so return it explicitly here.
           return $.sammy;
         }
      );

5
이 답변에 대한 좋은 작업 ... 질문자가 이것을 표시 할 것입니다!
죄수 ZERO

실제 jquery 파일에 따라 require_jquery 모듈을 만들지 만 jquery는 전역으로 유지되지 않습니까? 사용자 정의 경로에서로드하는 실제 jquery 파일 1.4.2가 require.js 모듈이 아니십니까? 아니면 그 파일을 감싸 야 했습니까?
Sander

3
최신 버전의 jQuery (1.7)에서는 이미 모듈을 지원하므로 정상적으로 필요하면 정상적으로 작동합니다.
MikeMurko dec.

1
누군가가 AMD를 지원하는 requireJS 2 (w / shim) + jQuery 1.7+를 수행하는 방법을 반영하기 위해이 답변을 업데이트 할 수 있습니까?
헨리

1
AMD가 아닌 자바 스크립트 파일로 종속성 지원을 달성하는 가장 좋은 방법은 이제 RequireJS 2.0+에서 발견 된 shim 구성입니다. Require 1.x를 계속 사용하는 경우 shim에 대한 전구체를 사용할 수 있습니다. , wrapjs
요한

32

이 질문은 이제 최소 2 년이 지났지 만 RequireJS 2.0에서 여전히 문제라는 것을 알았습니다 (require-jquery.js는 jQuery 1.8.0을 사용하지만 최신 버전은 1.8.2 임).

이 질문이 보이면 require-jquery.js가 이제는 require.js와 jquery.js가 합쳐진 것입니다. require-jquery.js를 편집하고 jQuery 부분을 최신 버전으로 바꿀 수 있습니다 .

업데이트 (2013 년 5 월 30 일) : 이제 RequireJS에 경로와 shim이 있으므로 jQuery 및 jQuery 플러그인을 가져 오는 새로운 방법이 있으며 이전 방법은 더 이상 필요하거나 권장 하지 않습니다 . 다음은 현재 메서드의 요약 버전입니다.

requirejs.config({
    "paths": {
      "jquery": "//ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min"
    }
});

define(["jquery"], function($) {
    $(function() {
    });
});

자세한 내용은 http://requirejs.org/docs/jquery.html 을 참조하십시오 .


덕분에,이 :) 아직 관련
Naor

여전히 jQuery 1.3.8을 사용하고 있습니까? :)
Chris

지적 해주셔서 감사합니다. 1.8의 이전 버전에는 최신 버전에서 해결 된 문제가 있다고 읽었습니다.
Blaine Mucklow 2012 년

과연. curCSS의 jQueryUI 문제가 아니 었습니까?
크리스

1
@AHMED : 둘 다 작동합니다. 차이점은 define이 명시 적으로 모듈을 지정한다는 것입니다. 나는 경로에 대해 더 명시 적이기 때문에 거의 독점적으로 define을 사용하는 것을 선호합니다. stackoverflow.com/questions/16087635/…
Chris

9

가장 좋은 방법은 jQuery를 RequireJS 빌드 외부에 유지하는 것입니다.

HTML에 jquery.min.js를 포함하기 만하면됩니다. 그런 다음 다음과 같은 jquery.js 파일을 만듭니다.

define([], function() {
    return window.$;
});

전통적으로 스크립트 태그를 사용하여로드해야하는 일부 JS 파일이 있고 jQuery에 의존하기 때문에 이것은 좋은 해결 방법입니다.
jingtao

3

JasonSmith의 답변이 RequireJS의 문서보다 훨씬 도움이되었을 것입니다.

그러나 (작은) 정의 선언 모듈 ( "require_jquery" "require_sammy")에 대해 별도의 AJAX 요청을하지 않도록 최적화하는 방법이 있습니다. r.js가 최적화 단계에서 수행 할 것이라고 생각하지만 Path, BaseURI 시스템과 싸우지 않기 위해 미리 수행 할 수 있습니다.

index.html :

<html>
  <head>
    <script data-main="js/loader.js" src="js/require.js"></script>
  </head>
</html>

loader.js :

// We are going to define( dependencies by hand, inline.
// There is one problem with that through (inferred from testing):
// Dependencies are starting to load (and execute) at the point of declaring the inline
// define, not at the point of require(
// So you may want to nest the inline-defines inside require( 
// this is, in a way, short replacement for Order plug in, but allows you to use
// hand-rolled defines, which the Order plug in, apparently does not allow.

var jQueryAndShims = ['jquery']

if(window.JSON == null){
    jQueryAndShims.push('json2')
    define(
        'json2'
        , ['js/libs/json2.min.js']
        , function() {
            return window.JSON
        }
    )
}
// will start loading the second we define it.
define(
    'jquery'
    , ['js/libs/jquery_custom.min.js']
    , function() {
        // we just pick up global jQuery here. 
        // If you want more than one version of jQuery in dom, read a more complicated solution discussed in
        // "Registering jQuery As An Async-compatible Module" chapter of
        // http://addyosmani.com/writing-modular-js/
        return window.jQuery 
    }
)

// all inline defines for resources that don't rely on other resources can go here.

// First level require(
// regardless of depends nesting in 'myapp' they will all start downloading 
// at the point of define( and exec whenever they want, 
// async in many browsers. Actually requiring it before the nested require makes
// sure jquery had *executed and added jQuery to window object* before
// all resolved depends (jquery plugins) start firing.
require(jQueryAndShims, function($) {

    // will start loading the second we define it.        
    define(
        'sammy_and_friends'
        , ['jquery','js/libs/jquery_pluginone.min.js','js/libs/jquery_plugintwo.min.js','js/libs/sammy.min.js']
        , function($) {
            // note, all plugins are unaltered, as they are shipped by developers.
            // in other words, they don't have define(.. inside.
            // since they augment global $ (window.jQuery) anyway, and 'jquery' define above picks it up
            // , we just keep on returning it.
            // Sammy is attached to $ as $.sammy, so returning just Sammy makes little sense
            return $
        }
    )

    // second level require - insures that Sammy (and other jQuery plugins) - 'sammy_and_friends' - is
    // loaded before we load Sammy plugins. I normally i would inline all sammy plugins i need 
    // (none, since i use none of them preferring jQuery's direct templating API
    // and no other Sammy plug in is really of value. )  right into sammy.js file. 
    // But if you want to keep them separate:
    require(['sammy_and_friends'], function() {

        // will start loading the second we define it.
        define(
            'sammy_extended'
            , ['sammy_and_friends','js/libs/sammy_pluginone.min.js','js/libs/sammy_plugintwo.min.js']
            , function($) {
                // as defined above, 'sammy_and_friends' actually returns (globall) jQuery obj to which
                // Sammy is attached.  So we continue to return $
                return $
            }
        )
        // will start loading the second we define it.
        define(
            'myapp'
            , ['sammy_extended', 'js/myapplication_v20111231.js'] 
            , function($, myapp_instantiator) {
                // note, myapplication may, but does not have to contain RequireJS-compatible define
                // that returns something. However, if it contains something like 
                // "$(document).ready(function() { ... " already it MAY fire before 
                // it's depends - 'sammy_extended' is fully loaded.
                // Insdead i recommend that myapplication.js returns a generator 
                // (app-object-generating function pointer)
                // that takes jQuery (with all loaded , applied plugins) 
                // The expectation is that before the below return is executed, 
                // all depends are loaded (in order of depends tree)
                // You would init your app here like so:
                return myapp_instantiator($)
                // then "Run" the instance in require( as shown below
            }
        )

        // Third level require - the one that actually starts our application and relies on
        // dependency pyramid stat starts with jQuery + Shims, followed by jQuery plugins, Sammy, 
        // followed by Sammy's plugins all coming in under 'sammy_extended'
        require(['jquery', 'myapp'], function($, myappinstance) {
            $(document).ready(function() {myappinstance.Run()})
        })
    }) // end of Second-level require
}) // end of First-level require

마지막으로 myapplication.js :

// this define is a double-wrap.
// it returns application object instantiator that takes in jQuery (when it's available) and , then, that
// instance can be "ran" by pulling .Run() method on it.
define(function() {
    // this function does only two things:
    // 1. defines our application class 
    // 2. inits the class and returns it.
    return function($) {
        // 1. defining the class
        var MyAppClass = function($) {
            var me = this
            this._sammy_application = $.sammy(function() {
                this.raise_errors = true
                this.debug = true
                this.run_interval_every = 300
                this.template_engine = null
                this.element_selector = 'body'
                // ..
            })
            this._sammy_application.route(...) // define your routes ets...
            this.MyAppMethodA = function(blah){log(blah)}  // extend your app with methods if you want
            // ...
             // this one is the one we will .Run from require( in loader.js
            this.Run = function() {
                me._sammy_application.run('#/')
            }
        }
        // 2. returning class's instance
        return new MyAppClass($) // notice that this is INITED app, but not started (by .Run) 
        // .Run will be pulled by calling code when appropriate
    }
})

이 구조는 RequireJS의 Order 플러그인을 느슨하게 대체 (중복?) 할 수있게하여 AJAX에 필요한 파일 수를 잘라내어 종속 및 종속 트리의 정의에 더 많은 제어를 추가 할 수 있습니다.

또한 jQuery를 별도로로드하는 것에는 큰 보너스가 있습니다 (보통 100k로 제공됨)-서버에서 캐싱을 제어하거나 jQuery를 브라우저의 localStorage에 캐시 할 수 있습니다. https://github.com/jensarps/AMD-cache 에서 AMD-Cache 프로젝트를 살펴본 다음 define (문에 "cache!"를 포함하도록 변경하면 (영원히 :)) 사용자 브라우저에 멈 춥니 다.

define(
    'jquery'
    , ['cache!js/libs/jquery_old.min.js']
    , function() {
        // we just pick up global jQuery here. 
        // If you want more than one version of jQuery in dom, read a more complicated solution discussed in
        // "Registering jQuery As An Async-compatible Module" chapter of
        // http://addyosmani.com/writing-modular-js/
        return window.jQuery 
    }
)

jQuery 1.7.x +에 대한 참고 사항 더 이상 창 개체에 연결되지 않으므로 위의 내용은 수정되지 않은 jQuery 1.7.x + 파일에서 작동하지 않습니다. 닫는 "}) (window);"앞에 이것을 포함하도록 jquery **. js를 사용자 정의해야합니다.

;window.jQuery=window.$=jQuery

콘솔에 "jQuery undefined"오류가있는 경우 사용중인 jQuery 버전이 자신을 창에 연결하지 않는 것입니다.

코드 라이선스 : 공개 도메인.

공개 : 위의 자바 스크립트는 훨씬 더 상세한 생산 코드를 패러 프레이징 (수작업)하기 때문에 "의사 코드"냄새가납니다. 위에 제시된 코드는 작동을 보장하지 않으며 제시된대로 작동하도록 테스트되지 않았습니다. 감사하고 테스트하십시오. 세미콜론은 JS 사양에 따라 필요하지 않으며 코드가 없으면 코드가 더 좋아 보이기 때문에 의도적으로 생략되었습니다.


RequireJS와 싸운 후 (정의를 존중하지 않고 순서가 맞지 않고로드되는 것, 중첩이 필요합니다. 기타 마법의 잘못된 행동) Curl.JS로 전환하고 밤에 잠을 잘 자기 시작했습니다. 과장된 것은 아니지만 젠장, 안정적이고 작업하기 쉽습니다!
ddotsenko 2012

1

jhs의 답변 외에도 README.md 파일 의 require-jquery github 페이지 에 대한 최신 지침을 참조 하십시오. 결합 된 jquery / require.js 파일을 사용하는 가장 간단한 방법과 별도의 jquery.js를 사용하는 방법을 모두 다룹니다.

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