กำลังโหลด Backbone และ Underscore โดยใช้ RequireJS


172

ฉันกำลังพยายามโหลด Backbone และ Underscore (รวมถึง jQuery) ด้วย RequireJS ด้วย Backbone และ Underscore เวอร์ชันล่าสุดดูเหมือนว่าจะยุ่งยาก สำหรับอันเดอร์ Underscore จะลงทะเบียนตัวเองโดยอัตโนมัติในฐานะโมดูล แต่ Backbone ถือว่า Underscore นั้นสามารถใช้ได้ทั่วโลก ฉันควรทราบด้วยว่า Backbone ดูเหมือนจะไม่ลงทะเบียนตัวเองเป็นโมดูลซึ่งทำให้มันไม่สอดคล้องกับ libs อื่น ๆ นี่คือ main.js ที่ดีที่สุดที่ฉันสามารถคิดได้:

require(
{
    paths: {
        'backbone': 'libs/backbone/backbone-require',
        'templates': '../templates'
    }
},
[
    // jQuery registers itself as a module.
    'http://cdnjs.cloudflare.com/ajax/libs/jquery/1.7/jquery.min.js',

    // Underscore registers itself as a module.
    'http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.2.1/underscore-min.js'
], function() {

    // These nested require() calls are just due to how Backbone is built.  Underscore basically says if require()
    // is available then it will automatically register an "underscore" module, but it won't register underscore
    // as a global "_".  However, Backbone expects Underscore to be a global variable.  To make this work, we require
    // the Underscore module after it's been defined from within Underscore and set it as a global variable for
    // Backbone's sake.  Hopefully Backbone will soon be able to use the Underscore module directly instead of
    // assuming it's global.
    require(['underscore'], function(_) {
        window._ = _;
    });

    require([
        'order!http://cdnjs.cloudflare.com/ajax/libs/backbone.js/0.5.3/backbone-min.js',
        'order!app'
    ], function(a, app) {
        app.initialize();
    })
});

ฉันควรพูดถึงเรื่องนี้ในขณะที่มันใช้งานได้ ฉันได้รับสิ่งต่อไปนี้:

Tracing dependencies for: main
js: "/home/httpd/aahardy/requirejs/r.js", line 7619: exception from uncaught JavaScript throw: Error: Error: Error evaluating module "undefined" at location "/home/httpd/aahardy/phoenix/trunk/ui/js/../../ui-build/js/underscore.js":
JavaException: java.io.FileNotFoundException: /home/httpd/aahardy/phoenix/trunk/ui/js/../../ui-build/js/underscore.js (No such file or directory)
fileName:/home/httpd/aahardy/phoenix/trunk/ui/js/../../ui-build/js/underscore.js
lineNumber: undefined
http://requirejs.org/docs/errors.html#defineerror
In module tree:
    main

มีวิธีจัดการที่ดีกว่านี้ไหม ขอบคุณ!


คุณใช้บทช่วยสอนหรือไม่?
kaha

1
ฉันดูบทเรียนต่าง ๆ เช่นbackbonetutorials.com/organizing-backbone-using-modulesแต่ดูเหมือนว่าพวกเขาจะล้าสมัยไปแล้วด้วยรุ่นล่าสุดของขีดเส้นใต้และกระดูกสันหลัง
Aaronius

ฉันพบว่าต้องใช้ยากกับห้องสมุดอื่นและในทางกลับกัน นั่นคือเหตุผลที่ฉันสร้างห้องสมุดที่ใช้งานได้ง่ายกว่ามากและผ่านการทดสอบกับเชิงมุม มีแอปพลิเคชันตัวอย่างที่ด้านล่าง: gngeorgiev.github.io/Modulerr.jsคุณยังสามารถรวมสคริปต์ทั้งหมดเข้าเป็นหนึ่งเดียวโดยไม่ต้องพึ่งพา Modulerr.js
Georgi-it

btw คำจำกัดความโมดูลแบบอะซิงโครนัส btw เป็น kinda oxymoron :)
Strajk

ฮา! จุดดี. แก้ไข
Aaronius

คำตอบ:


294

RequireJS 2.X ในตอนนี้สามารถจัดการกับโมดูลที่ไม่ใช่ของ AMD เช่น Backbone & Underscore ได้ดียิ่งขึ้นโดยใช้การshimกำหนดค่า ใหม่

การshimกำหนดค่าใช้งานง่าย: (1) หนึ่งระบุการพึ่งพา ( deps) ถ้ามี (ซึ่งอาจมาจากการpathsกำหนดค่าหรืออาจเป็นเส้นทางที่ถูกต้องด้วยตนเอง) (2) (เป็นทางเลือก) ระบุชื่อตัวแปรส่วนกลางจากไฟล์ที่คุณกำลังปรับแต่งซึ่งควรจะส่งออกไปยังฟังก์ชันโมดูลที่ต้องการ (หากคุณไม่ได้ระบุการส่งออกคุณจะต้องใช้งานโกลบอลเพราะจะไม่มีสิ่งใดถูกส่งผ่านไปยังฟังก์ชั่นที่ต้องการ / กำหนด)

นี่คือตัวอย่างการใช้งานอย่างง่ายของshimการโหลด Backbone นอกจากนี้ยังเพิ่มการส่งออกสำหรับขีดล่างแม้ว่ามันจะไม่มีการอ้างอิงใด ๆ

require.config({
  shim: {
    underscore: {
      exports: '_'
    },
    backbone: {
      deps: ["underscore", "jquery"],
      exports: "Backbone"
    }
  }
});

//the "main" function to bootstrap your code
require(['jquery', 'underscore', 'backbone'], function ($, _, Backbone) {   // or, you could use these deps in a separate module using define

});

หมายเหตุ:รหัสที่เข้าใจง่ายนี้ถือว่า jquery, backbone และ underscore อยู่ในไฟล์ชื่อ "jquery.js", "backbone.js" และ "underscore.js" ในไดเรกทอรีเดียวกันกับรหัส "main" นี้ (ซึ่งกลายเป็น baseURL สำหรับต้องการ ) ถ้าไม่ได้เป็นกรณีที่คุณจะต้องใช้การตั้งค่าเส้นทาง

โดยส่วนตัวฉันคิดว่ามีshimฟังก์ชั่นการใช้งานในตัวข้อดีของการไม่ใช้ Backbone & Underscore รุ่น forked นั้นดีกว่าประโยชน์ของการใช้ AMD fork ที่แนะนำในคำตอบที่ได้รับความนิยมอื่น ๆ แต่ก็ใช้ได้ทั้งสองวิธี


ควรใช้รหัสนี้กับSample RequireJS 2.0.1 + jQuery 1.7.2 project requirejs.org/docs/download.html#samplejqueryหรือไม่
Henry

ถ้าฉันเข้าใจคุณถูกต้อง Henry คุณกำลังถามว่า shim จำเป็นสำหรับ $ plugins หรือไม่ ไม่ใช่ถ้าคุณใช้ไฟล์ require-jquery.js แบบรวมจากโปรเจ็กต์ตัวอย่างนั้น นั่นเป็นเพราะด้วยไฟล์ที่รวมกัน jquery จะได้รับการโหลดพร้อม ๆ กันดังนั้น jquery จึงรับประกันว่าจะถูกโหลดตามเวลาที่คุณพยายามใช้ $ plugins ใด ๆ ในโมดูลใด ๆ ในกรณีนี้เมื่อคุณต้องการใช้ $ plugins คุณสามารถรวมไว้ในรายการอ้างอิงของคุณราวกับว่าพวกเขาเป็น AMD แม้ว่าพวกเขาจะไม่ นี่เป็นข้อยกเว้นสำหรับกฎอย่างแน่นอนและโดยทั่วไปคุณจะต้องมีชิมสำหรับโมดูลที่ไม่ใช่ของ AMD
Ben Roberts

โปรดทราบว่าการกำหนดค่า shim นั้นเข้ากันได้กับโครงการตัวอย่างนั้นและสามารถใช้เพื่อเพิ่มไลบรารีที่ไม่ใช่ของ AMD
Ben Roberts

11
แค่คิดว่าฉันจะพูดถึงว่านี่เป็นวิธีที่จะไปจริงๆหวังว่าฉันจะให้ +50 upvotes เพื่อให้ได้ # 1 คำตอบ
koblas

วิธีการในคำตอบนี้ดูดี แต่ไม่ได้ผลสำหรับฉัน ฉันใช้gist.github.com/2517531แทนซึ่งใช้งานได้ดี
Rob W

171

ปรับปรุง : ขณะที่รุ่น 1.3.0 เน้นเอาออกเอเอ็มดี (RequireJS) การสนับสนุน

คุณสามารถใช้amdjs / Backbone 0.9.1และamdjs / Underscore 1.3.1 fork พร้อมกับรองรับ AMD จาก James Burke (ผู้ดูแลของ RequireJS)

ข้อมูลเพิ่มเติมเกี่ยวกับการสนับสนุนเอเอ็มดีสำหรับการเน้นและกระดูกสันหลัง

// main.js using RequireJS 1.0.7
require.config({
    paths: {
        'jquery': 'libs/jquery/1.7.1/jquery',
        'underscore': 'libs/underscore/1.3.1-amdjs/underscore', // AMD support
        'backbone': 'libs/backbone/0.9.1-amdjs/backbone', // AMD support
        'templates': '../templates'
    }
});

require([
    'domReady', // optional, using RequireJS domReady plugin
    'app'
], function(domReady, app){
    domReady(function () {
        app.initialize();
    });
});

โมดูลมีการลงทะเบียนอย่างถูกต้องและไม่จำเป็นต้องใช้ปลั๊กอินสั่งซื้อ:

// app.js
define([
    'jquery', 
    'underscore',
    'backbone'
], function($, _, Backbone){
    return {
        initialize: function(){
            // you can use $, _ or Backbone here
        }
    };
});

ขีดเส้นใต้เป็นตัวเลือกจริง ๆ แล้วเนื่องจาก Backbone ได้รับการอ้างอิงด้วยตัวเอง:

// app.js
define(['jquery', 'backbone'], function($, Backbone){
    return {
        initialize: function(){
            // you can use $ and Backbone here with
            // dependencies loaded i.e. Underscore
        }
    };
});

ด้วยน้ำตาลเอเอ็มดีคุณสามารถเขียนได้เช่นนี้:

define(function(require) {
    var Backbone = require('backbone'),
        $ = require('jquery');

    return {
        initialize: function(){
            // you can use $ and Backbone here with
            // dependencies loaded i.e. Underscore
        }
    };
});

เกี่ยวกับข้อผิดพลาดของเครื่องมือเพิ่มประสิทธิภาพ: ดับเบิลตรวจสอบการกำหนดค่าการสร้างของคุณ ฉันถือว่าการกำหนดค่าพา ธ ของคุณปิดอยู่ หากคุณมีการตั้งค่าไดเรกทอรีคล้ายกับ RequireJS Docsคุณสามารถใช้:

// app.build.js
({
    appDir: "../",
    baseUrl: "js",
    dir: "../../ui-build",
    paths: {
        'jquery': 'libs/jquery/1.7.1/jquery',
        'underscore': 'libs/underscore/1.3.1-amdjs/underscore',
        'backbone': 'libs/backbone/0.9.1-amdjs/backbone',
        'templates': '../templates'
    }, 
    modules: [
        {
            name: "main"
        }
    ]
})

4
นั่นคือสิ่งที่ฉันกำลังมองหา ขอบคุณ! คำตอบที่ยอดเยี่ยมเช่นกัน ตอนนี้มันทำงานได้ตามที่คุณอธิบาย
Aaronius

2
+1 + คำตอบที่ถูกต้องทำงานและอัปเดตตัวอย่าง งานที่ยอดเยี่ยม Riebel คุณช่วยฉันและฉันแน่ใจว่าคนอื่น ๆ มากมาย
Ken

22
โบนัสซุปเปอร์สำหรับการรักษานี้อัปเดตนานหลังจากโพสต์ต้นฉบับ
Aaronius

คำตอบที่ดี @Riebel! มันมีประโยชน์กับฉันจริงๆ Btw ฉันจะแนะนำให้ดูvoloด้วย มันเป็นห้องสมุดที่สร้างขึ้นโดย jrburke (ผู้สร้าง requirejs) เพื่อดึงการอ้างอิงจาก github ตัวอย่างเช่นการดึงขีดล่างของ amd รุ่น amd ทำได้แค่พิมพ์: volo add underscore
txominpelu

5

สำหรับการอ้างอิงเป็นของรุ่น 1.1.1 (~ กุมภาพันธ์ '13) Backbone ยังลงทะเบียนตัวเองในฐานะที่เป็นโมดูลเอเอ็มดี มันจะทำงานร่วมกับ requirejs โดยไม่จำเป็นต้องใช้ shim config ของมัน (ตัวแยก amdjs ของ James Burkeยังไม่ได้รับการอัพเดตตั้งแต่ 1.1.0)


4

ข่าวดีตอนนี้ขีดเส้นใต้ 1.6.0 ตอนนี้รองรับ requirejs กำหนด !!!

เวอร์ชันด้านล่างนี้ต้องใช้ shims หรือต้องการ underscore.js ดังนั้นจึงคาดหวังว่าตัวแปรทั่วโลก "_" ไม่มีการถูกทุบ (ซึ่งจะยุติธรรมคือการเดิมพันที่ยุติธรรม)

เพียงแค่โหลดโดย

  requirejs.config({
    paths: {
        "underscore": "PATH/underscore-1.6.0.min",
    }
  });

4

ฉันจะเขียนโดยตรงคุณสามารถอ่านคำอธิบายบน requirejs.org คุณสามารถใช้โค้ดด้านล่างเป็นตัวอย่างสำหรับการใช้ชีวิตประจำวันของคุณ (ps ฉันใช้ yeoman) (เนื่องจากมีการอัปเดตหลายอย่างฉันกำลังโพสต์สิ่งนี้ตั้งแต่เดือนกุมภาพันธ์ 2014)

ตรวจสอบให้แน่ใจว่าคุณรวมสคริปต์ไว้ใน index.html ของคุณ

<!-- build:js({app,.tmp}) scripts/main.js -->
<script data-main="scripts/main" src="bower_components/requirejs/require.js"></script>
<!-- endbuild -->

จากนั้นใน main.js

require.config({
    shim: {
        'backbone': {
            deps: ['../bower_components/underscore/underscore.js', 'jquery'],
            exports: 'Backbone'
        }
    },

    paths: {
        jquery: '../bower_components/jquery/jquery',
        backbone: '../bower_components/backbone/backbone'
    }
});

require(['views/app'], function(AppView){
    new AppView();
});

app.js

/**
 * App View
 */
define(['backbone', 'router'], function(Backbone, MainRouter) {
    var AppView = Backbone.View.extend({
        el: 'body',

        initialize: function() {
            App.Router = new MainRouter();
            Backbone.history.start();
        }
    });

    return AppView;
});

ฉันหวังว่าฉันจะเป็นประโยชน์!


1
มีประโยชน์มากกว่าที่คุณรู้ นี่คือสิ่งที่ฉันได้พยายามที่จะสร้างในโครงการของฉัน bower_components และทั้งหมด ขอบคุณ @STEEL
Dwight Spencer

0
require.config({
  waitSeconds: 500,
  paths: {
    jquery: "libs/jquery/jquery",
    jqueryCookie: "libs/jquery/jquery.cookie",
    .....
  },

  shim: {
    jqxcore: {
      export: "$",
      deps: ["jquery"]
    },
    jqxbuttons: {
      export: "$",
      deps: ["jquery", "jqxcore"]
    }
    ............
  }
});

require([
 <i> // Load our app module and pass it to our definition function</i>
  "app"
], function(App) {
  // The "app" dependency is passed in as "App"
  // Again, the other dependencies passed in are not "AMD" therefore don't pass a parameter to this function
  App.initialize();
});
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.