Memuat Backbone dan Garis Bawah menggunakan RequireJS


172

Saya mencoba memuat Backbone dan Garis Bawah (serta jQuery) dengan RequireJS. Dengan versi terbaru dari Backbone dan Underscore, sepertinya agak rumit. Untuk satu, Underscore secara otomatis mendaftar sendiri sebagai modul, tetapi Backbone mengasumsikan Underscore tersedia secara global. Saya juga harus mencatat bahwa Backbone tampaknya tidak mendaftarkan dirinya sebagai modul yang membuatnya agak tidak konsisten dengan lib lainnya. Ini main.js terbaik yang bisa saya dapatkan dengan bekerja:

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();
    })
});

Saya harus menyebutkan bahwa, saat berfungsi, pengoptimal tersedak. Saya menerima yang berikut:

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

Apakah ada cara yang lebih baik untuk menangani ini? Terima kasih!


Apakah Anda melakukannya menggunakan tutorial?
kaha

1
Saya melihat melalui berbagai tutorial seperti backbonetutorials.com/organizing-backbone-menggunakan-modules tetapi mereka tampaknya sudah ketinggalan zaman sekarang dengan versi terbaru garis bawah dan backbone.
Aaronius

Saya juga menemukan requirejs sulit digunakan dengan perpustakaan lain dan sebaliknya. Itu sebabnya saya membuat perpustakaan yang jauh lebih mudah digunakan dan diuji dengan sudut. Ada aplikasi demo di bagian bawah: gngeorgiev.github.io/Modulerr.js Anda juga dapat menggabungkan semua skrip menjadi satu tanpa ketergantungan pada Modulerr.js
Georgi-it

btw Synchronous Asynchronous Module Definition agak oxymoron :)
Strajk

Ha! Poin yang bagus. Diedit.
Aaronius

Jawaban:


294

Wajib 2.X sekarang secara organik menangani modul non-AMD seperti Backbone & Underscore jauh lebih baik, menggunakan shimkonfigurasi baru .

The shimkonfigurasi sederhana untuk digunakan: (1) satu menyatakan dependensi ( deps), jika ada, (yang mungkin dari pathskonfigurasi, atau mungkin jalur yang valid sendiri). (2) (secara opsional) tentukan nama variabel global dari file yang Anda pilih, yang harus diekspor ke fungsi modul Anda yang memerlukannya. (Jika Anda tidak menentukan ekspor, maka Anda hanya perlu menggunakan global, karena tidak ada yang akan diteruskan ke fungsi memerlukan / menetapkan Anda.)

Berikut adalah contoh sederhana penggunaan shimuntuk memuat Backbone. Itu juga menambahkan ekspor untuk garis bawah, meskipun tidak memiliki ketergantungan.

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

});

Catatan: kode yang disederhanakan ini mengasumsikan bahwa jquery, backbone, dan garis bawah berada dalam file yang bernama "jquery.js", "backbone.js" dan "underscore.js" di direktori yang sama dengan kode "utama" ini (yang menjadi basisURL untuk memerlukan ). Jika ini tidak terjadi, Anda harus menggunakan path konfigurasi .

Saya pribadi berpikir dengan shimfungsionalitas bawaan, keuntungan dari tidak menggunakan versi bercabang dari Backbone & Underscore melebihi manfaat menggunakan garpu AMD yang direkomendasikan dalam jawaban populer lainnya, tetapi cara apa pun berfungsi.


Haruskah kode ini digunakan dengan Sample RequireJS 2.0.1 + jQuery 1.7.2 project requireejs.org/docs/download.html#samplejquery ?
Henry

Jika saya mengerti Anda dengan benar, Henry, Anda bertanya apakah shim diperlukan untuk $ plugins. Bukan, JIKA Anda menggunakan file need-jquery.js gabungan dari proyek sampel itu. Itu karena dengan file gabungan, jquery akan dimuat secara bersamaan dengan kebutuhan, jadi jquery dijamin akan dimuat pada saat Anda mencoba menggunakan $ plugins dalam modul apa pun. Dalam hal ini, ketika Anda ingin menggunakan $ plugins, Anda bisa memasukkannya ke dalam daftar dependensi Anda seolah-olah itu adalah AMD, walaupun sebenarnya tidak. Ini jelas merupakan pengecualian dari aturan tersebut, dan umumnya Anda akan memerlukan shim untuk modul non-AMD.
Ben Roberts

Perhatikan bahwa konfigurasi shim kompatibel dengan proyek sampel tersebut dan dapat digunakan untuk menambah perpustakaan non-AMD lainnya.
Ben Roberts

11
Hanya berpikir saya akan menyebutkan bahwa ini benar-benar cara untuk pergi, berharap saya bisa memberi +50 upvotes untuk mendapatkannya menjadi jawaban # 1.
koblas

Metode dalam jawaban ini tampak menjanjikan, tetapi tidak berhasil untuk saya. Saya menggunakan gist.github.com/2517531 sebagai gantinya, yang berfungsi dengan baik.
Rob W

171

Pembaruan : Pada versi 1.3.0 Dukungan underscore AMD (RequireJS) dihapus .

Anda dapat menggunakan garpu amdjs / Backbone 0.9.1 dan amdjs / Underscore 1.3.1 dengan dukungan AMD dari James Burke (pengelola RequireJS).

Info lebih lanjut tentang dukungan AMD untuk Underscore dan Backbone .

// 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();
    });
});

Modul didaftarkan dengan benar dan tidak perlu untuk plugin pesanan:

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

Underscore sebenarnya opsional, karena Backbone sekarang mendapatkan dependensinya sendiri:

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

Dengan sedikit gula AMD Anda juga bisa menulis seperti ini:

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

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

Mengenai kesalahan pengoptimal: periksa kembali konfigurasi konfigurasi Anda. Saya menganggap konfigurasi jalur Anda tidak aktif. Jika Anda memiliki pengaturan direktori yang mirip dengan RequireJS Docs, Anda dapat menggunakan:

// 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
Itulah tepatnya yang saya cari. Terima kasih! Jawaban terinci yang bagus juga. Sekarang berjalan seperti yang telah Anda jelaskan.
Aaronius

2
+1 jawaban + contoh yang akurat, berfungsi, dan diperbarui. Riebel pekerjaan yang sangat baik, Anda telah membantu saya, dan saya yakin orang lain, banyak.
Ken

22
Super-bonus untuk menjaga ini diperbarui lama setelah posting asli.
Aaronius

Jawaban yang bagus @Riebel! Ini sangat berguna bagi saya. Btw, saya juga merekomendasikan untuk melihat volo . Ini adalah perpustakaan yang dibuat oleh jrburke (pencipta Requirejs) untuk mengambil dependensi dari github. Misalnya mengambil versi underscore amd dilakukan hanya mengetik: volo add underscore
txominpelu


4

Berita bagus, Underscore 1.6.0 sekarang mendukung persyaratan!

versi di bawah ini memerlukan shims, atau memerlukan underscore.js kemudian secara membabi buta berharap bahwa variabel global "_" belum dihancurkan (yang seharusnya adil adalah taruhan yang adil)

cukup masukkan dengan

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

4

Saya akan menuliskannya secara langsung, Anda dapat membaca penjelasan tentang requireejs.org, Anda dapat menggunakan kode di bawah ini sebagai potongan untuk penggunaan sehari-hari Anda; (ps saya menggunakan kamu) (karena banyak hal diperbarui, saya posting ini pada Februari 2014)

Pastikan Anda memasukkan skrip ke index.html Anda

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

Kemudian, di 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;
});

Semoga bermanfaat.!


1
Lebih bermanfaat daripada yang Anda tahu. Ini persis apa yang saya coba untuk membangun proyek saya, bower_components dan semuanya. Terima kasih @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();
});
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.