With so many SPA-style frameworks emerging in the last couple years, you may wonder what makes Durandal unique or different. Why would you want to choose it for your next project?
With these three libraries as a foundation, Durandal constructs a thin integration layer and transforms them into a powerful SPA framework. In addition to strategically connecting these libraries, Durandal adds new functionality. Some things Durandal adds are: a client-side router, rich view composition, screen state management, pub/sub, simple conventions, modals/message boxes and more...
If you’ve worked with any of the three libraries listed above, then you already have skills you can leverage on a Durandal project. You already know part of the framework. This makes it relatively easy for existing web developers to get started. The time you've invested learning the three core libraries on prior traditional web projects translates directly to Durandal apps. Choosing Durandal is almost a "no brainer".
Suppose you've never worked with jQuery, RequireJS or Knockout. Is Durandal worth your time to learn? Why not pick a different SPA framework that is "all inclusive"? The simple answer is YES, it is well worth your time. Here's the longer answer: Almost every major SPA framework has a way to work with the DOM, create modules and declare data bindings. No matter what framework you pick, you are going to have to make the effort to learn these things both conceptually and in terms of the chosen library's API. The difference with Durandal is that we get those capabilities from other libraries which were originally designed for traditional web development. That means that when you learn those things in the context of Durandal, you are also learning things you can directly apply to traditional web development too. It's a huge return on investment.
But that’s only the beginning of the advantages...
The AMD spec is pluggable via the notion of loader plugins. These plugins can acquire and transform any resource in any way and supply it as a module dependency. Want to load some JSON data? You can do that declaratively. Want to load CoffeeScript? You can use a loader to compile it on the fly if you want. You can write loaders to do just about anything. Most of Durandal's view engine is in fact supplied by the text loader plugin. What's the really awesome thing about loaders? They can execute code both at runtime and at build time. This means you can have a loader optimize content as part of a build process, but not have to change your application code at all. It's extremely powerful.
Speaking of the build process...RequireJS supplies a build tool called r.js. It essentially takes a list of modules as inputs and spits out 1-n optimized files. For a small or medium-sized application, you might choose to build to one optimized file. For larger apps, you might choose to build a shell with each feature area optimized into its own file...and download features on the fly based on live user usage. That and many more deployment scenarios are what this tool was designed for. On top of that, there are many higher level build tools that work with RequireJS. You can use Grunt, Mimosa or even Durandal's Weyland to automate the process.
But you don't just need to compose objects, you need to compose views. Fortunately, Durandal has the most powerful, declarative view composition engine available in any framework today. Here's a short list of some things you can do declaratively:
This is just a few examples of what can be done. Keep in mind that in all these cases the composition can be configured with transition animations, optimized per composition site to cache views or be driven entirely by static or dynamically changing data.
Building rich clients usually involves asynchronous requests for data or other resources. Durandal was designed to handle this with elegance from the very beginning. To that point, Durandal uses promises throughout. Durandal's own API exposes all potentially asynchronous commands via promises. Internally, Durandal also understands when you use promises and it can therefor cause the binding system, router and other key features to respond appropriately. Out of the box, our promise implementation is provided by jQuery. However, existing site documentation explains how you can switch that out in favor of your favorite promise library, such as Q.
If you are targeting an ES5 browser, you can then enable the observable module. When this module is active, it teaches the binding system to data-bind directly to promises. The result is that you can set up a foreach binding over a promise for an array of data. In your own code, you don't have to handle the promise yourself at all.
Durandal's router is perhaps the most powerful router available today. It is configured with simple route-to-module mappings but can also be configured for convention-based routing. It automatically handles bad routes, supports hash and push state navigation and provides a lot of capabilities around data driven routes such as parameters, optional parameters, splats and query strings. Additionally, we support the notion of "child routers" allowing you to structure and encapsulate entire areas of your application, reducing the overall complexity of the navigation structure.
In real applications you need more than just routing though. You need something which is occasionally called "screen state management." What is that? Imagine you’ve got a customer filling out a form in your application. Before they save, they attempt to navigate to a new screen. The current screen is in a "dirty" state and the application may want to prevent the user from navigating away...or at least temporarily halt the process and ask the user what it should do with the data. In Durandal, the router supports something we call the "screen activation lifecycle" which allows any screen to synchronously or asynchronously control flow into and out of screens. But this functionality is implemented so that it's decoupled from the router itself, thus Durandal also uses it to handle the lifecycle of its modal dialogs. In fact, you can use it anywhere in your app, even controlling fragments of a screen and individual component activations. This is a complex bit of functionality to get right but it is critical in real applications. Most frameworks just ignore it entirely, but not Durandal.
SPA’s can be complex code-bases and such projects need to be tested. Durandal has this area covered well. Because we've built on RequireJS and all of your code is built as AMD modules, you can easily fake, mock, or stub any part of the system. This applies both to your code as well as all of Durandal's modules. The test strategy is consistent. In fact, if you want to see how to write unit tests for your application, all you have to do is fork the Durandal test suite, change some file paths and you are up and running with a test setup for yourself. If you are interested in testability, there are several articles in the documentation that expand upon this.
From the beginning of work on Durandal 2.0, SEO was considered. Interestingly, much of this work has to be handled on the server for a SPA. That said, Durandal supports all the necessary client-side hooks and configuration options to enable full Google crawling of your application. Interested in how to make it wll work? We've got some great documentation on that.
Modern applications need to be made available to diverse people groups. Today Durandal is being used by companies all over the world who are rolling out apps to multiple cultures. Since Durandal was designed to be pluggable, it actually only takes a few minutes to plug a localization solution into the binder. With just a few lines of code centralized in one part of your code-base, you can ensure that everything displayed on the screen is properly localized; no hassle, no fuss.
The Durandal project follows Sematic Versioning with great rigor. APIs do not break on minor or patch releases. Minor releases contain only additions and patches contain only bug fixes. Only major version changes signal potential breakage. Those aren’t going to happen very often. When you depend on Durandal, you know exactly what the version numbers mean and what you can expect when updating. The docs from previous versions are made available perpetually and conversion guides are provided for major version changes. We handle integration of the dependent libraries for you as well.
Durandal has an active community that is happy to help you learn the framework as you work through your application's unique challenges. Much discussion is taking place already in our Google Group as well as on Stack Overflow. However, if that is not enough for you, or if you or your business need a safety net, Durandal has a few options available to you. First, we have commercial support. This is a monthly subscription you can cancel any time and is priced based on the team size. We usually have clients purchase the commercial support for the few months they are working on the project and then discontinue after a successful rollout. It’s a great bargain compared to traditional consulting prices and turnaround time is very good. Additionally, Blue Spire provides customized training either delivered in person at your place of business or virtually through a series of web meetings. Pricing is usually negotiated on a case by case basis depending on the depth, time length and number of students. Finally, in the next couple of months you are going to start seeing official video training become available. Some of this will be free and some of it will be available for a reasonable price, providing you not only with a way to learn directly from us, but also to financially support the project.
While there are several SPA frameworks available today, only Durandal has all the benefits and characteristics listed above. But not only is it one of the most powerful and flexible options today, it also provides you with a great return on investment for your non-SPA web work. On top of all that, it’s enterprise ready and the kind of training and support you would expect is readily available. And this is just the beginning. Wait until you see what’s next...