Tải xương sống và gạch dưới bằng RequireJS


172

Tôi đang cố tải Backbone và Underscore (cũng như jQuery) bằng RequireJS. Với các phiên bản mới nhất của Backbone và Underscore, nó có vẻ khó khăn. Đối với một, Underscore tự động đăng ký chính nó như một mô-đun, nhưng Backbone giả định Underscore có sẵn trên toàn cầu. Tôi cũng nên lưu ý rằng Backbone dường như không đăng ký chính nó như là một mô-đun khiến nó không phù hợp với các lib khác. Đây là main.js tốt nhất tôi có thể làm với nó hoạt động:

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

Tôi nên đề cập rằng, trong khi nó hoạt động, trình tối ưu hóa cuộn cảm với nó. Tôi nhận được như sau:

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

Có cách nào tốt hơn để xử lý này? Cảm ơn!


Bạn đã làm nó bằng cách sử dụng bất kỳ hướng dẫn?
kaha

1
Tôi đã xem qua các hướng dẫn khác nhau như backbonetutorials.com/ Organizing-backbone-USEmodules nhưng dường như chúng đã lỗi thời với các phiên bản mới nhất của gạch dưới và xương sống.
Aaronius

Tôi cũng thấy các yêu cầu khó sử dụng với các thư viện khác và ngược lại. Đó là lý do tại sao tôi tạo ra một thư viện dễ sử dụng hơn nhiều và được thử nghiệm với góc cạnh. Có một ứng dụng demo ở phía dưới: gngeorgiev.github.io/Modulerr.js Bạn cũng có thể kết hợp tất cả các tập lệnh thành một mà không cần phụ thuộc vào Modulerr.js
Georgi-it

btw Định nghĩa mô-đun không đồng bộ đồng bộ là loại oxymoron :)
Strajk

Hà! Điểm tốt. Đã chỉnh sửa.
Aaronius

Câu trả lời:


294

RequireJS 2.X hiện đang xử lý một cách hữu cơ các mô-đun không phải AMD như Backbone & Underscore tốt hơn nhiều, sử dụng shimcấu hình mới .

Các shimcấu hình là đơn giản để sử dụng: (1) một khẳng định sự phụ thuộc ( deps), nếu có, (có thể là từ các pathscấu hình, hoặc có thể là con đường hợp lệ bản thân). (2) (tùy chọn) chỉ định tên biến toàn cục từ tệp bạn đang làm mờ, sẽ được xuất sang các chức năng mô-đun của bạn yêu cầu nó. (Nếu bạn không chỉ định xuất khẩu, thì bạn sẽ chỉ cần sử dụng toàn cầu, vì sẽ không có gì được chuyển vào các hàm yêu cầu / xác định của bạn.)

Dưới đây là một ví dụ đơn giản về cách sử dụng shimđể tải Backbone. Nó cũng thêm một bản xuất cho dấu gạch dưới, mặc dù nó không có bất kỳ phụ thuộc nào.

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

});

Lưu ý: mã đơn giản hóa này giả định rằng jquery, xương sống và dấu gạch dưới nằm trong các tệp có tên "jquery.js", "backbone.js" và "underscore.js" trong cùng thư mục với mã "chính" này (trở thành cơ sở cho yêu cầu này ). Nếu đây không phải là trường hợp, bạn sẽ cần phải sử dụng một cấu hình đường dẫn .

Cá nhân tôi nghĩ rằng với shimchức năng tích hợp sẵn, những lợi thế của việc không sử dụng phiên bản rút gọn của Backbone & Underscore vượt trội hơn lợi ích của việc sử dụng ngã ba AMD được đề xuất trong câu trả lời phổ biến khác, nhưng cả hai cách đều hoạt động.


Có nên sử dụng mã này với Sample RequireJS 2.0.1 + jQuery 1.7.2 project allowjs.org/docs/doad.html#samplejquery ?
Henry

Nếu tôi hiểu bạn một cách chính xác, Henry, bạn đang hỏi liệu shim có cần thiết cho các plugin không. Không, NẾU bạn sử dụng tệp request-jquery.js kết hợp từ dự án mẫu đó. Đó là bởi vì với tệp kết hợp, jquery được tải đồng bộ với yêu cầu, vì vậy jquery được đảm bảo được tải theo thời gian bạn cố gắng sử dụng bất kỳ plugin $ nào trong bất kỳ mô-đun nào. Trong trường hợp này, khi bạn muốn sử dụng các plugin $, bạn chỉ có thể đưa chúng vào danh sách phụ thuộc của mình như thể chúng là AMD, ngay cả khi chúng không phải. Đây chắc chắn là một ngoại lệ đối với quy tắc và nói chung, bạn sẽ cần shim cho bất kỳ mô-đun không phải AMD nào.
Ben Roberts

Lưu ý rằng shof cofiguration tương thích với dự án mẫu đó và có thể được sử dụng để thêm các thư viện không phải AMD khác.
Ben Roberts

11
Chỉ cần nghĩ rằng tôi sẽ đề cập rằng đây thực sự là con đường để đi, ước gì tôi có thể đưa ra hơn 50 lượt upvote để đưa nó trở thành câu trả lời số 1.
koblas

Phương pháp trong câu trả lời này có vẻ đầy hứa hẹn, nhưng không hiệu quả với tôi. Tôi đã sử dụng gist.github.com/2517531 thay vào đó, nó hoạt động tốt.
Rob W

171

Cập nhật : Kể từ phiên bản 1.3.0 Underscore đã loại bỏ hỗ trợ AMD (RequireJS) .

Bạn có thể sử dụng amdjs / Backbone 0.9.1 và ngã ba amdjs / Underscore 1.3.1 với sự hỗ trợ của AMD từ James Burke (người duy trì RequireJS).

Thông tin thêm về hỗ trợ AMD cho Underscore và 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();
    });
});

Các mô-đun được đăng ký đúng cách và không cần plugin thứ tự:

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

Underscore thực sự là tùy chọn, vì Backbone hiện có phụ thuộc vào chính nó:

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

Với một số đường AMD, bạn cũng có thể viết nó như thế này:

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

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

Liên quan đến lỗi tối ưu hóa: nhân đôi cấu hình bản dựng của bạn. Tôi giả sử cấu hình đường dẫn của bạn là tắt. Nếu bạn có thiết lập thư mục tương tự như RequireJS Docs, bạn có thể sử dụng:

// 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
Đó chính xác là những gì tôi đang tìm kiếm. Cảm ơn bạn! Câu trả lời rất chi tiết là tốt. Bây giờ nó đang chạy đúng như bạn mô tả.
Aaronius

2
+1 chính xác, làm việc và cập nhật câu trả lời + ví dụ. công việc tuyệt vời Riebel, bạn đã giúp tôi, và tôi chắc chắn những người khác, rất nhiều.
Ken

22
Siêu tiền thưởng cho việc giữ cập nhật này lâu sau bài viết gốc.
Aaronius

Câu trả lời tuyệt vời @Riebel! Nó thực sự hữu ích với tôi. Btw, tôi cũng khuyên bạn nên xem volo . Đó là một thư viện được tạo bởi jrburke (người tạo ra các yêu cầu) để lấy các phụ thuộc từ github. Ví dụ: lấy phiên bản amd của gạch dưới được thực hiện chỉ bằng cách gõ: volo add gạch dưới
txominpelu


4

Tin tốt, Underscore 1.6.0 hiện hỗ trợ xác định các yêu cầu !!!

các phiên bản bên dưới này yêu cầu shims hoặc yêu cầu underscore.js sau đó hy vọng mù quáng rằng biến toàn cầu "_" không bị phá hủy (điều công bằng là đặt cược công bằng)

chỉ cần tải nó vào

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

4

Tôi sẽ viết trực tiếp, bạn có thể đọc phần giải thích trên allowjs.org, bạn có thể sử dụng đoạn mã dưới đây như một đoạn trích để sử dụng hàng ngày; (ps tôi sử dụng yeoman) (vì nhiều thứ được cập nhật, tôi sẽ đăng bài này vào tháng 2 năm 2014.)

Đảm bảo bạn đã bao gồm tập lệnh trong index.html của bạn

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

Sau đó, trong 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;
});

Tôi hy vọng tôi có ích.!


1
Nhiều hơn nữa hữu ích hơn bạn sẽ biết. Đây chính xác là những gì tôi đã cố gắng xây dựng trên một dự án của tôi, bower_components và tất cả. Cảm ơn @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();
});
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.