Завантаження хребта та підкреслення за допомогою RequireJS


172

Я намагаюся завантажити Backbone та Underscore (а також jQuery) за допомогою RequireJS. З останніми версіями Backbone та Underscore це здається дещо складним. Для одного, Underscore автоматично реєструється як модуль, але Backbone припускає, що Underscore доступний у всьому світі. Слід також зазначити, що Backbone, здається, не реєструється як модуль, що робить його таким чином, що не відповідає іншим. Це найкращий 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

Чи є кращий спосіб впоратися з цим? Дякую!


Ви робили це за допомогою будь-якого підручника?
каха

1
Я переглянув різні підручники, такі як backbonetutorials.com/organizing-backbone-using-модули, але вони, здається, застаріли зараз із останніми версіями підкреслення та магістралі.
Аароній

Я також виявив, що Requjs важко використовувати з іншими бібліотеками і навпаки. Ось чому я створив бібліотеку, яка набагато простіше у використанні та перевірена кутом. Внизу є демо-додаток: gngeorgiev.github.io/Modulerr.js Ви також можете комбінувати всі сценарії в один без залежності від Modulerr.js
Georgi-it

Визначення синхронного асинхронного модуля btw є
своєрідним

Га! Гарна думка. Відредаговано.
Аароній

Відповіді:


294

RequireJS 2.X тепер органічно звертається до не-AMD модулів, таких як Backbone & Underscore, набагато краще, використовуючи нову shimконфігурацію.

shimКонфігурація проста у використанні: (1) один стверджує залежності ( deps), якщо такі є, (які можуть бути від pathsконфігурації, або можуть бути дійсними тракти самі). (2) (необов'язково) вкажіть ім'я глобальної змінної з файлу, який ви переливаєтеся, який слід експортувати до функцій вашого модуля, які цього потребують. (Якщо ви не вкажете експорт, вам знадобиться просто використовувати глобальний, оскільки нічого не буде передано вашим функціям вимагати / визначити.)

Ось простий приклад використання shimдля завантаження хребта. Він також додає експорт для підкреслення, хоча він не має ніяких залежностей.

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, магістраль та підкреслення містяться у файлах з назвою "jquery.js", "backbone.js" та "underscore.js" у тому самому каталозі, що і цей "головний" код (який стає базовимURL для вимагання ). Якщо це не так, вам потрібно буде використовувати конфігурацію контурів .

Я особисто думаю, що завдяки вбудованій shimфункціональності переваги від використання роздвоєної версії Backbone & Underscore переважують переваги використання вилки AMD, рекомендованої в іншій популярній відповіді, але будь-який спосіб працює.


Чи слід використовувати цей код у Sample RequireJS 2.0.1 + jQuery 1.7.2 project Requjs.org/docs/download.html#samplejquery ?
Генрі

Якщо я вас правильно зрозумів, Генрі, ти запитуєш, чи потрібна шим для плагінів $. Це не так, якщо ви використовуєте комбінований файл requ-jquery.js з цього зразкового проекту. Це тому, що при комбінованому файлі jquery завантажується синхронно з попитом, тому jquery гарантовано завантажується тим часом, коли ви намагаєтесь використовувати будь-які плагіни $ у будь-якому модулі. У цьому випадку, коли ви хочете використовувати $ плагіни, ви можете просто включити їх у свій список залежностей, як якщо б вони були AMD, навіть якщо вони не є. Це, безумовно, виняток із правила, і, як правило, вам знадобляться будь-які модулі, що не належать до AMD.
Бен Робертс

Зауважте, що конфігурація shim сумісна з цим зразковим проектом і може використовуватися для додавання інших бібліотек, що не належать до AMD.
Бен Робертс

11
Щойно я подумав, що хотів би зазначити, що це дійсно шлях, хотілося б, щоб я міг дати +50 підсумків, щоб отримати відповідь №1.
коблас

Метод у цій відповіді виглядав багатообіцяючим, але не працював для мене. Я використовував натомість gist.github.com/2517531 , який спрацював чудово.
Роб Ш

171

Оновлення : Станом на версію 1.3.0 підкреслено видалено підтримку AMD (RequireJS) .

Ви можете використовувати amdjs / Backbone 0.9.1 та виделку amdjs / Underscore 1.3.1 з підтримкою AMD від Джеймса Берка (підтримувача RequireJS).

Більше інформації про підтримку AMD для підкреслення та хребта .

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

З деяким цукром AMD ви також можете написати це так:

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, ви можете використовувати:

// 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
Саме це я і шукав. Дякую! Відмінна детальна відповідь також. Зараз він працює так, як ви описали.
Аароній

2
+1 точна, робоча та оновлена ​​відповідь + приклади. Відмінна робота Рібел, ви мені допомагаєте, і я впевнений, що багато інших.
Кен

22
Супер-бонус за збереження цього оновлення довго після оригіналу публікації.
Аароній

Чудова відповідь @ Riebel! Мені це було дуже корисно. До речі, я б також рекомендував поглянути на volo . Це бібліотека, створена jrburke (творець Requjs) для отримання залежностей від github. Наприклад, отримання версії amd підкреслення робиться лише набравши текст: volo add
подчеркивание


4

Хороша новина, Underscore 1.6.0 тепер підтримує вимагати визначення !!!

Версії нижче цього вимагають збитків або вимагають underscore.js, а потім сліпо сподіваючись, що глобальна змінна "_" не була розбита (що справедливо - це справедлива ставка)

просто завантажте його

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

4

Я запишу прямо, ви можете прочитати пояснення на Requjs.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
Дуайт Спенсер

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();
});
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.