jQuery does however normalize things across browsers and serves as a great way of doing DOM manipulation. Using it to it's strengths, you can select some excellent tools to use along-side it as a toolkit for your larger-scale app development.
In this post we'll be looking at ways you can put together a toolkit for large-scale jQuery application development by identifying the options you have available at the moment for dependency management, MVC with jQuery, templating, testing, minification and more.
1. Dependency Management
When writing large-scale jQuery applications, there may be script dependencies which you would prefer to load within a specific order or dynamically depending on their need (for a very basic example, you may wish to load functions.js before loading app.js if it relies on it) - a script loader can assist with this process. Although the traditional technique of just using hierarchially-organized script tags is equally as valid, script loaders nowadays come with a few extra features which you may find helpful, eg. loading different scripts depending on the features a browser supports or as mentioned, dynamically depending on some condition or need.
The two most dominant script loaders on the market at the moment are RequireJS (by James Burke) and LabJS (by Kyle Simpson). For quite some time there was a view that one of these had to be better than the other, but in truth, they both have their own strengths. In my experience, one of Require's best features is it's support of structured 'modules' for your code whilst LabJS is best for when you don't need that extra feature and would prefer something more lightweight.
If you would like to read up more on whether to use Require or LabJS for your project, check out this post. For the purpose of saving you time, I've also included a few other options for dependancy management if these two don't quite meet your requirements.
- RequireJS - I recommend using this if you plan on keeping your code more modular. Modules attempt to limit their impact on the global namespace and be more explicit about mentioning their immediate dependencies. RequireJS also comes with an optimization tool that allows you to combine and group your scripts into a smaller set of minified scripts that load quickly - http://requirejs.org/docs/jquery.html
- LabJS - this works best where scripts need to efficiently loaded in a particular order and you're looking for a more lightweight solution than RequireJS or aren't as interested in a modular approach to dependancy management -http://www.labjs.com (and checkout YepNope JS, an excellent conditional loader that works on top of LabJS by Alex Sexton - http://www.yepnopejs.com).
- JSL Script Loader - yet another decent contenter which supports lazy lading, ordered loading, duplicate source prevention and caching. Perhaps not as extensively tested as LabJS or Require - http://www.andresvidal.com/jsl
- Bootstrap- a less feature-rich option than the others, but gets the job done. Best option if you're looking for a very minimal solution without any of the frills https://bitbucket.org/scott_koon/bootstrap
2. MVC& Organization For Large-Scale jQuery Applications
Design patterns and Architectural patterns allow you to create re-usable, structured and more organized pieces of code based on existing tried and tested patterns in software engineering. Using a design pattern across your application is something I consider necessary especially when trying to ensure the coding style and structure is consistent when teams are involved in writing the app and not just a single person.
Quite often in modern web application development, the MVC (model-view-controller) pattern is employed for this purpose, however there exist several other popular patterns which you may find equally as useful if you feel MVC is not for you.
The argument is that a clean MVC-strutured server-side codebase should suffice whilst others believe that as the complexity and scale of jQuery applications increases, especially at an enterprise level, we need a pattern like MVC in place. I agree with this latter viewpoint, although depending on the use case other patterns may be equally as useful here.
This section is directed at assisting those who have already decided they would benefit from using MVC with jQuery.
How does the MVC Pattern work?
Traditionally with MVC, you separate objects into three main categories (or concerns) when coding up your application. My interpretation of these categories is as follows:
Model - the models in your application represent knowledge and data. For example: get methods and set methods fall under this umbrella. The models are isolated and know nothing about the View nor the Controller.
View - views, from a web app perspective, can be considered the UI. They are generally dumb and don't necessarily need to perform validation logic ie. they always forward the input via a callback system. Views are isolated and know nothing about the Model nor the Controller.
Controller - the controller sits right between the Model and the View. It performs any necessary business logic / data manipulation needed to get the data from the model to the view. The controllers do most of the validation that come back from the view and are aware of both the View and the Model.
That said, if you are used to building web applications using traditional conventions (ie. heavier on the server-side, lighter on the client-side), you may find JMVC’s approach to development something which requires a small change in mindset.
Speaking with Justin Meyer from the JMVC project, perhaps the biggest confusion that he sees newcomers to it have is that they misunderstand exactly what the project really has to offer. In this segment of the post I would like to help clarify this.
JMVC can really be considered two things - both integrated development tools and a repeatable MVC architecture. The benefit of JMVC is that it provides a clear path to adding functionality and does a lot of the things you should be doing on your project quite easily.
- Model - A way to package and organize Ajax requests and service data
- Controller - A jQuery widget generator
- View - Client side templates
Next, in terms of the integrated development tools that the project offers, you get the following (and more) included. While these are hardly what you would consider ground-breaking, the clean integration of such features means that you don’t have to roll your own toolkit to handle them.
- Dependency management, production builds (with Less and CoffeeScript)
- Automated unit and functional testing
For all other cases such as working with a larger-scale application, JMVC offers more than enough advantages to warrant evaluating it for your projects.
For the purpose of being extensive, I'm including a number of other options for adding MVC to your projects if you would like an alternative to JMVC.
Mature MVC solution which includes testing, dependency management, build tools, client side templates. Perfect for large applications where an all-in-one solution for organizing and building code is required. Most recently used by Grooveshark in their app re-write.
Demos and download:
Excellent for a DIY MVC Solution where you select the additional components you feel work best for your project. Backbone provides the ‘backbone’ you need to organize your code using the MVC pattern (but bare in mind that here the C in MVC stands for Collections and not Controllers). It's great because it basically a provides a small framework ?(~2Kb) that provides the core pieces of KVO bindings.
Demos and download:
As it runs in the browser, SproutCore extends MVC to include a server interface, a display that 'paints' your interface and responders for controlling application state. Yeduha Katz who is heavily involved in the project is also working on adding modularity to SC and this option should also be available soon. Recommended for applications wishing to have a desktop-like ‘richness’. Considered overkill for smaller-sized apps. Used by Apple amongst others.
Demos and download:
Demos and download:
An MVC framework by Paul Campbell who is well known for his involvement with Ruby. Eyeballs works with many libraries but provides a layer of features for organising your code - it aims to be both agnostic and modular. About on par with Backbone. A trivial note but it's initialization function (o_O()) may be a offputting to some. Above all, Eyeballs has quite a familiar feeling if you're a Ruby developer and I would recommend checking it out if you primarily use Ruby for building the server-side code to your web applications.
Demos and download:
Sammy.js is a lightweight jQuery plugin which allows you to easily define 'route' based applications. Where the C in MVC stands for Controller, some would consider Sammy.js the best controller framework out there but it doesn't exactly provide the Model and View aspects itself. Sammy is still worth checking out for single page JS apps requiring a level of organization.
Demos and download:
A decent looking MVC solution but needs some polish. Based on Sammy and JS-Model but comes with clean support for generators and is easily extensible.
Additional pattern resources for large-scale jQuery applications:
- John Resig's Simple Inheritence
- Using Inheritence Patterns To Organize Large jQuery Apps with Alex Sexton
- The Object Literal pattern recommended by Rebecca Murphy
- jQuery-tmpl http://github.com/jquery/jquery-tmpl (tutorial video here)
- Mustache.js https://github.com/janl/mustache.js (tutorial video here)
- Dust.js (one of Alex's recommendations) - http://akdubya.github.com/dustjs/
- Handlebars by Yehuda Katz (an extension to Mustache) - https://github.com/wycats/handlebars.js (I'm warming up to this option)
- jQote http://aefxx.com/jquery-plugins/jqote/
- PURE http://beebole.com/pure
- Nano https://github.com/trix/nano
4. Communication Between Modules
Although this may be something you attempt to solve using a homebrewed solution, using existing pub/sub or custom events approachs are ideal for implementing simple communication between the modules in your application. Below you can find links to some different implementations of pub/sub which vary in terms of what they offer. At the moment, Ben Alman's version is my implementation of preference as it focuses on size and utilizes jQuery custom events.
- Ben Alman's pub/sub on GitHub (this updated version contains two variations)
- @phiggins jQuery.pubsub
- An Introduction To jQuery Custom Events
- jsSignals - Custom Events/Messaging for jQuery
5. Build Process & Script Concatenation
Now let's take a look at your options for concatenation.
- Using Google Closure Compiler for compile JS applictions with Ant http://groups.google.com/group/closure-compiler-discuss/browse_thread/thread/92278e7a84736f3c
- Programatically concatenating files using only Ant http://stackoverflow.com/questions/1373564/how-to-programmaticly-concatenate-with-ant
- Concatonate files with MVC and .NET http://www.codeplex.com/MvcScriptManager
6. Script Minification
Minification is a critical part of the build process for any large jQuery application. When delivering scripts in a live production environment (especially one which you may get a lot of traffic to), every extra byte counts, which is why you should ideally minify your code rather than just including the unminified/uncompressed version that requires your users to spend longer waiting for it to download.
The minification process can sometimes require a little tool tweaking to get the most out of it, but trust me when I say that this time can be well worth the investment. It might be interesting to note that over at jQuery, we are constantly testing new minification tools and a tool is never something set in stone - just because you opt for Google's Closure compiler in 2010 doesn't mean you might not shift to UglifyJS in 2011 for example. Your build process can be flexible enough to accomodate these changes.
- Google Closure Compiler http://code.google.com/closure/compiler/
- YUI Compressor http://developer.yahoo.com/yui/compressor/ (and automating this with Packer here)
- Minifier http://aspnet.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=34488
- UglifyJS * (Recommended as it shows promising minification gains on the others) https://github.com/mishoo/cl-uglify-js
- Packer for .NET http://svn.offwhite.net/trac/SmallSharpTools.Packer/wiki
- Dojo Toolkit's ShrinkSafe http://www.dojotoolkit.org/
Production-ready jQuery applications need to be heavily tested to ensure that your code both works *and* performs as expected - this is especially critical when writing large-scale apps as you don't want your users first experience to be of your application falling over.
Before we get deeper into this section, I should say that regardless of how complete your test coverage is, nothing really beats having a human that didn't write your code go through and test your code/application out. That said, let's take a look at further testing options.
Unit testing is something I suggest as a must but in this section I'm also going to include links to resources on other aspects of testing jQuery apps which may come in helpful depending on what you're doing.
A solid build process with unit-testing should be used for testing and releasing any serious jQuery application. Manual functional testing is great from a user-interface perspective, but Unit testing will allow you to stress-test your code to find out if all the inner-workings of it perform as intended. Below is a good tutorial on how to get started with QUnit - a popular jQuery Unit testing tool which is quite straight-forward to use. You may alternatively like to check out JSUnit or FireUnit but QUnit is by far the most widely used of the three and my personal unit testing tool of choice.
FuncUnit, as recommended by Alex, allows you to easily manipulate elements and fake aspects such as user interaction quite well.FuncUnit itself is an add-on to QUnit and the tests you create with it can be run in the browser or with Selenium. It also allows you to automate basic QUnit tests in EnvJS (a commend line browser). We recommend checking it out
Mock Your Ajax Requests with MockJax & jQuery for Rapid Development
The MockJax plugin is a really fantastic development and testing tool for intercepting and simulating ajax requests made with jQuery with a minimal impact on changes to production code. I recommend this for testing web applications that frequently use Ajax connections. TamperData is also useful for testing of this type. Read the complete tutorial on using MockJax below.
Getting Started With Test-Driven Development For jQuery
The concept of test-driven development is quite simple. Anytime you want to add a new feature to your application, you need to write a test for it before writing any code for that feature. To write the test, you need to fully understand the specifications and requirements for what that feature does. At the start, your test will of course fail, but the goal is to ultimately code up a solution to that feature which is considered finished if the test passes. Here is an excellent tutorial on how to get started with test-driven development for jQuery with Elijah Manor.
Automating jQuery testing with Browser Launching, Test Execution And Result Reporting
jQuery Driven Automated User Interface Testing
I hope you've found this guide to building large-scale jQuery applications useful. Whilst a single all-encompassing solution may very be something desirable to the community at large, the aim of this post was to provide you with all of the options that are (to my knowledge) available for both rolling your own large-scale toolkit for application development.
Providing you and your team with the flexibility to decide is the most useful thing that could be done with this information and in that regard, I hope I've managed to trim down some of the time you may have otherwise spent researching this topic.
Further Reading & Resources
- On jQuery and large applications with Rebecca Murphy
- On 'Rolling Your Own' Large jQuery Apps with Alex Sexton
- jQuery UI Developer's Guide (for those wishing to use $.widget etc)
- Tech Behind The New GrooveShark (Good Article On Large Scale jQuery App Dev)
- Cody Lindley's excellent list of client-side development links for app development