2011-12-22 37 views
14

Tôi đang xây dựng ứng dụng JavaScript lớn đầu tiên (không phải là spaghetti) của mình. Trong khi việc giới thiệu RequireJS và các khung quản lý phụ thuộc khác cho JavaScript giúp dễ dàng chia nhỏ các tệp, Tôi không rõ ràng về cách đẩy cơ sở mã lớn vào sản xuất. Những gì tôi muốn là một cách để tổng hợp và rút gọn/uglify JavaScripts của tôi để sản xuất, sử dụng một cái gì đó như Ready.jsUglifyJS. Hoặc một số cách tiếp cận khác, nếu nó có ý nghĩa.Cách cấu trúc các ứng dụng JavaScript trong phát triển và sản xuất

Nhà phát triển có ứng dụng JavaScript lớn trong sản xuất xử lý cấu trúc của họ trong phát triển và trong sản xuất như thế nào?

Ví dụ: tôi có thể sử dụng RequireJS để phát triển và sau đó sử dụng Ready/Uglify để tổng hợp/rút gọn. Nhưng sau đó mã của tôi sẽ có vô nghĩa require()'s nằm rải rác trong suốt. Tôi chắc chắn có một cách tiếp cận tốt hơn.

Tôi cũng bị nhầm lẫn về việc bao gồm jQuery trong các tệp này. Tôi có nên đóng gói mỗi và mọi tệp jQuery riêng biệt (ví dụ như các khung nhìn Backbone sử dụng jQuery) trong riêng biệt của riêng mình $(document).ready(function(){...})? Điều đó có vẻ rất không rõ ràng.

+2

+1 vì đã tham gia làm javascript không phải là spaghetti cho lần đầu tiên. Để nhiều nhà phát triển sống trong sự từ chối quá lâu :) –

Trả lời

2

Bạn có thể sử dụng RequireJS optimizer. Các yêu cầu không phải là vô nghĩa, ngay cả trong ứng dụng nén, bởi vì bạn luôn luôn phải có được một tham chiếu đến các mô-đun. Các tài liệu tối ưu hóa cũng nói, rằng nó sẽ không bao gồm một mô-đun đã được nạp với một biến như

var mods = someCondition ? ['a', 'b'], ['c', 'd']; 
require(mods); 

Tôi nghĩ rằng RequireJS nên đợi cho đến khi DOM đã sẵn sàng tất cả các module đã được nạp, vì vậy bạn không cần phải quấn tất cả các tập tin.

Điều đó nói rằng, người quản lý gói yêu thích của tôi vẫn là StealJS. Nó có thể khởi động các cuộc gọi không cần thiết trong một xây dựng sản xuất và một mô-đun luôn được đóng gói trong một đóng cửa để đối tượng jQuery được truyền và đợi cho tới khi DOM sẵn sàng và tất cả các kịch bản đã được tải. Thật không may là nó chưa tương thích với các đặc tả của mô đun CommonJS.

cách
+0

Điều này thật tuyệt vời. StealJS trông rất đẹp, nhưng tôi thích nhiều hơn những gì mà RequireJS có thể làm. Tôi rất muốn biết thêm về toàn bộ quá trình xây dựng của bạn, nếu bạn không ngại chia sẻ. Ở đâu trong bước triển khai của bạn, bạn có chạy trình tối ưu hóa của mình không? Bạn có thử nghiệm cùng với nó không? Bạn có kiểm tra JS được tối ưu hóa không? Tôi có thể hỏi điều này trong một câu hỏi khác, nhưng tôi có một lịch sử xấu về những loại câu hỏi "thực hành tốt nhất" này. –

+0

Mặc dù nó hoạt động tốt, StealJS là một phần của khung JavaScriptMVC (http://javascriptmvc.com/), đó là những gì tôi sử dụng để tạo cấu trúc, xây dựng và thử nghiệm các ứng dụng của mình và chăm sóc tất cả những thứ này nhiều chính nó (và là giải pháp hoàn toàn chứa đựng JavaScript mà tôi biết). – Daff

1

Tôi đã tìm thấy YUI Builder hoạt động tốt cho tôi. Tôi không chắc chắn nó hữu ích như thế nào nếu bạn không sử dụng YUI 3, nhưng có một cơ hội tốt, bạn có thể thích nghi nó với nhu cầu của bạn. Mặt khác, bạn đã xem RequireJS Optimizer chưa?

Về việc xử lý document.ready; Tôi nghĩ rằng thực hành tốt để không cho phép mã trong các mô-đun làm bất cứ điều gì cho đến khi chúng được khởi tạo hoặc được gọi. Vì vậy, tôi sẽ có một đơn $(document).ready() trong thẻ <script> ở cuối trang, chính nó sẽ "gắn kết với nhau" các mô-đun cần thiết trên trang đó.

0

Anti-mì spaghetti

Để phát triển một cách hiệu quả và dễ dàng duy trì một ứng dụng JavaScript, như trái ngược với một số quảng cáo hoc kịch bản hay xoàng xĩnh tự động hóa phi trong suốt, bạn có thể sử dụng native Qooxdoo application. Không thể bao gồm Qooxdoo mà không cần viết quá nhiều, nhưng trong trường hợp ứng dụng gốc (không nhầm lẫn thuật ngữ với C hoặc Java, Qooxdoo là JavaScript thuần túy), nó được mô tả là:

Đối với các ứng dụng sử dụng HTML tùy chỉnh/GUI dựa trên CSS thay vì lớp tiện ích của qooxdoo.

Do đó, ứng dụng này không sử dụng bất kỳ lớp giao diện người dùng Qooxdoo nào, nhưng chỉ có cơ sở cấu trúc mã và công cụ xây dựng. Mã trong Qooxdoo được sắp xếp trong các lớp, một tệp cho mỗi tệp như trong Java. Tôi có thể trông giống như sau:

/** 
* @use(website.library.MosaicFlow) 
*/ 
qx.Class.define('website.controller.Gallery', { 

    extend : website.controller.Abstract, 

    members : { 

    _baseUrl : 'https://picasaweb.google.com/data/feed/api', 


    _render : function(photos) 
    { 
     q('.preloader').remove(); 

     q.template.get('gallery-template', {'photos': photos}).appendTo('#gallery-container'); 
     var gallery = window.jQuery('#gallery-container .gallery').mosaicflow({ 
     'minItemWidth' : 256, 
     'itemSelector' : '.photo', 
     'autoCalculation' : false 
     }); 
     gallery.trigger('resize'); 
    }, 

    _convert : function(item, index) 
    { 
     try 
     { 
     return { 
      'url'  : item.content.src, 
      'summary' : item.summary.$t, 
      'thumb' : item.media$group.media$thumbnail[0] 
     }; 
     } 
     catch(ex) 
     { 
     this.debug('failed to convert', index, item); 
     return null; 
     } 
    }, 

    _onLoadSuccess : function(event) 
    { 
     var request = event.getTarget(); 
     var response = request.getResponse(); 
     if(!qx.lang.Type.isObject(response) || !('feed' in response)) 
     { 
     request.debug('Malformed response received'); 
     } 
     else 
     { 
     this._render(response.feed.entry.map(this._convert, this).filter(function(item) 
     { 
      return !!item; 
     })); 
     } 
    }, 

    _onLoadFail : function() 
    { 
     this.debug('Picasa search failed'); 
    }, 

    main : function() 
    { 
     var query = /^\/gallery\/(\w+)$/.exec(window.location.pathname); 
     var request = new qx.io.request.Jsonp(qx.lang.String.format('%1/all', [this._baseUrl])); 
     request.setRequestData({ 
     'q'   : query[1], 
     'thumbsize' : 300, 
     'max-results' : 20, 
     'alt'   : 'json' 
     }); 
     request.setTimeout(16000); 
     request.setCache(false); 
     request.addListener('fail', this._onLoadFail, this); 
     request.addListener('success', this._onLoadSuccess, this); 
     request.send(); 
    } 

    } 

}); 

Mô hình đối tượng Qooxdoo tận dụng cả hai thế giới. Trong có phẩm chất của nền tảng trưởng thành như Java, đồng thời nó hiện đại và năng động, cung cấp các lớp học, thừa kế, giao diện, mixins, sự kiện, tài sản, dữ liệu ràng buộc và nhiều hơn nữa. Bởi vì mỗi lớp có một tên được định nghĩa và nằm trong một cây không gian tên, trình tạo Qooxdoo có thể tận dụng nó. Nó phân tích các lớp của bạn và xây dựng các cây cú pháp của chúng. Sau đó, nó giải quyết các phụ thuộc. I E. khi bạn tham khảo một lớp khác, như website.controller.Abstract. Điều này dẫn đến biểu đồ phụ thuộc, được sử dụng để tải các tập lệnh theo thứ tự thích hợp. Lưu ý rằng tất cả đều tự động và minh bạch đối với nhà phát triển và tệp được tải như nguyên trạng. Không có sự thúc đẩy như trong trường hợp của CommonJS, không có bản mẫu xấu xí nào để bọc mã cho bạn giống như AMD.

Như bạn có thể thấy trong ví dụ trên, bạn có thể xử lý các thư viện ngoài qooxdoo bên ngoài. Bạn chỉ có thể cần phải viết một wrapper giả cho một thư viện để bao gồm nó trong quá trình xây dựng.

và Phát triển sản xuất môi trường

Bạn phát triển xây dựng ứng dụng của bạn (xây dựng là cần thiết chỉ khi phụ thuộc mới được giới thiệu trong code) với cái gọi là mục tiêu nguồn. Các tệp ứng dụng của bạn được tải theo thứ tự phụ thuộc, từng cái một. Các tệp khung có thể được tải từng cái một hoặc tùy chọn tốt hơn, được xây dựng theo một số khối lớn. Trong môi trường sản xuất, mã ứng dụng của bạn được xây dựng với mục tiêu xây dựng. Bạn có một tùy chọn để tạo ra một tệp đầu ra duy nhất, hoặc có một phần xây dựng, nơi mã được chunked trong các tệp lớn (bạn có thể kiểm soát kích thước của chúng). Xây dựng một phần có thể trông như thế này (được tối ưu hóa/gzipped):

├── [127/64kB] website.f6ffa57fc541.js 
├── [100/33kB] website.f86294b58d1a.js 
└── [361/110kB] website.js 

Lưu ý rằng các bộ phận được tải theo yêu cầu trên các trang yêu cầu chúng.

http://example.com/ 
└── website.js 
http://example.com/article 
└── website.js 
http://example.com/form 
└── website.js 
    └── website.f86294b58d1a.js 
http://example.com/gallery 
└── website.js 
    └── website.f6ffa57fc541.js 
http://example.com/geo 
└── website.js 

Vì qooxdoo không nhắm mục tiêu trang web toàn diện xây dựng, nhưng chỉ được cung cấp một nền tảng của loại ứng dụng bản địa, bạn cần phải mã hóa các mục nhập vào các ứng dụng và một số vấn đề cơ bản, như bootstrapping, định tuyến URL, v.v. Tôi đã cố gắng giải quyết vấn đề này với qooxdoo-website-skeleton, những ví dụ trên thuộc về. Bạn được tự do sử dụng nó hoặc viết của riêng bạn.

Cuối cùng lưu ý rằng nó có thể không dễ dàng để bắt đầu như với thư viện JavaScript trung bình, nhưng độ phức tạp là tỷ lệ thuận với lợi ích cuối cùng.

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