2012-06-06 29 views
58

Chúng tôi đang xây dựng một ứng dụng web không trival bằng cách sử dụng Backbone, RequireJS và Handlebars, và tốt, tôi chỉ tò mò. Tại thời điểm này, mỗi mô hình của chúng tôi sorta trông như thế này:Làm thế nào để đạt được tải chậm với RequireJS?

define(['Backbone', 'js/thing/a', 'js/thing/b', 'js/lib/bob'], function(a, b, bob) { 
    return Backbone.Router.extend({ 
    // stuff here 
    }); 
}); 

nơi điều/A, điều/b cả hai đều có sự phụ thuộc của họ, ví dụ trên tay lái mẫu, vv Điều gì sẽ xảy ra bây giờ là ở chính của tôi .js, tất cả các bộ định tuyến 'cấp cao nhất' được tải và khởi tạo; mỗi bộ định tuyến cấp cao nhất có một tập hợp các phụ thuộc (các mô hình, các khung nhìn, vv) mà mỗi bộ có các phụ thuộc riêng của chúng (các khuôn mẫu, các trình trợ giúp, các utils, vv). Về cơ bản, một cấu trúc cây lớn.

Sự cố trong trường hợp này là toàn bộ cây này được giải quyết và được tải khi tải trang. Tôi không nhớ rằng mỗi sé, khi chúng tôi sẽ chạy nó thông qua trình tối ưu hóa cuối cùng và kết thúc với một tập tin lớn duy nhất (giảm RequireJS về cơ bản một khuôn khổ mô đun hóa). Tuy nhiên, tôi tò mò liệu bạn có thể tải các nội dung như lượt xem và mẫu 'theo yêu cầu' hay không.

Có là "CommonJS đơn giản gói" giải thích here, vì vậy tôi cố gắng rằng:

define(function(require) { 
    Backbone = require('Backbone'); 
    return Backbone.Router.extend({ 
    doStuff: function() { 
     var MyView = require('js/myView'); 
     new MyView().render(); 
    } 
    }); 
}); 

Tuy nhiên, nhìn vào thanh tra mạng của Chrome, có vẻ như RequireJS - bằng cách nào đó, ngay cả khi không kích hoạt các tuyến đường mà gây ra sự Trình xử lý doStuff - vẫn tải phụ thuộc myView. Câu hỏi:

  • Điều này thực sự có thể? Có ma thuật đen trong RequireJS tìm kiếm các cuộc gọi đến require() mà không thực sự kích hoạt tuyến đường doStuff?
  • Đây có phải là cách lý thuyết chính xác về việc 'theo yêu cầu', tải các mô-đun và tài nguyên RequireJS không?
  • Trình tối ưu hóa r.js vẫn hoạt động như được quảng cáo nếu bạn sử dụng ký pháp này?

Trả lời

48

Điều này thực sự có thể? Có ma thuật đen trong RequireJS tìm kiếm các cuộc gọi đến yêu cầu() mà không thực sự kích hoạt tuyến đường doStuff?

Khi bạn sử dụng cú pháp 'đường' it uses Function.prototype.toString and a regex để trích xuất tham chiếu đến require và sau đó liệt kê chúng là phụ thuộc trước khi chạy hàm. Về cơ bản nó trở thành phong cách bình thường của việc xác định với một mảng của deps như là đối số đầu tiên.

Vì điều này, nó không quan tâm đến yêu cầu cuộc gọi của bạn và đó là lý do tại sao các câu lệnh có điều kiện bị bỏ qua (nó cũng giải thích tại sao những cuộc gọi require phải sử dụng chuỗi ký tự và không phải biến).

Đây có phải là cách lý thuyết chính xác về việc 'theo yêu cầu', tải các mô-đun và tài nguyên RequireJS không?

Sử dụng cú pháp đường sẽ không cho phép tải có điều kiện như bạn đã thấy. Cách duy nhất tôi có thể nghĩ ra khỏi đỉnh đầu của tôi là sử dụng một cuộc gọi require với một mảng của DEPS và một callback:

define(function(require) { 
    var module1 = require('module1'); 

    // This will only load if the condition is true 
    if (true) { 
     require(['module2'], function(module2) { 

     }); 
    } 

    return {}; 
}); 

Chỉ có nhược điểm là một hàm lồng nhau nhưng nếu bạn sau khi thực hiện thì đây là một tuyến đường hợp lệ.

Trình tối ưu hóa r.js vẫn hoạt động như được quảng cáo nếu bạn sử dụng ký pháp này?

Nếu bạn đang sử dụng cú pháp 'đường' thì có, trình tối ưu hóa sẽ hoạt động tốt. Một ví dụ:

modules/test.js

define(function(require) { 
    var $ = require('jquery'); 
    var _ = require('underscore'); 

    return { 
     bla: true 
    } 
}); 

Khi biên soạn bởi r.js này trông giống như:

define('modules/test', ['require', 'jquery', 'underscore'], function(require) { 
    var $ = require('jquery'); 
    var _ = require('underscore'); 

    return { 
     bla: true 
    } 
}); 

Tóm lại bạn có thể tải những thứ có điều kiện, nhưng như bạn nói , nếu bạn có ý định tối ưu hóa dự án với r.js thì không có chi phí khổng lồ nào khi sử dụng cú pháp đường.

3

Bạn cũng có thể muốn xem require-lazy.

Nó có thành phần thời gian chạy và thành phần thời gian xây dựng. Thành phần runtime cho phép bạn uể oải đòi hỏi một mô-đun như (lưu ý các plugin lazy!):

define(["lazy!mymodule"], function(mymodule) { 
    ... 
}); 

Trong bối cảnh trước đó, mymodule là một promise, module thực sẽ được nạp với get() và sẽ được cung cấp trong then() gọi lại:

mymodule.get().then(function(m) { 
    // here m is the real mymodule 
}); 

Yêu cầu-lười tích hợp với r.js để tự động tạo "gói" của tệp Javascript. Nó cũng xử lý tự động bộ nhớ cache-busting cho các bó. Có một số ví dụ để có ý tưởng. Ngoài ra còn có tích hợp GruntBower.

Các vấn đề liên quan