<img height="1" width="1" style="display:none" src="https://www.facebook.com/tr?id=1063935717132479&amp;ev=PageView&amp;noscript=1 https://www.facebook.com/tr?id=1063935717132479&amp;ev=PageView&amp;noscript=1 "> Bitovi Blog - UX and UI design, JavaScript and Frontend development

DoneJS Release

Today we are releasing DoneJS. Learn about DoneJS's best features and what we're doing to help the community learn the technology.

Justin Meyer

Justin Meyer

Twitter Reddit

Today, we feel a mix of satisfaction, pride, and a bit of exhaustion as we announce the release of DoneJS.


DoneJS is an open source JavaScript framework that contains everything you need to build high-performance, real-time, web, mobile and desktop applications. It’s not a new framework, but a cleaned up and enhanced version of JavaScriptMVC.

The best way to get a feel for DoneJS’s capabilities is to take 45 minutes and go through its quick start guide. There you’ll build a simple chat application that:

  • is real-time
  • is server side rendered
  • progressively loads bundles from a CDN
  • runs as a mobile application, a desktop application, and a web application

Here's the completed mobile, desktop, and web chat applications messaging each other:

In this article, I'll highlight:

1. The features that make DoneJS a next generation framework.

DoneJS includes all "modern" front-end application and development features like:

In addition, its tight integration of module-loader and MVVM framework means that its whole is greater than the sum of its parts. For example, we will show how you can:

  • progressively import modules in templates, and
  • embed Model data in the server-side rendered HTML.

2. How to get started learning DoneJS.

There's a lot to learn to build world-class JavaScript applications. We want to provide the best learning experience possible. Now that DoneJS is released, we are going to focus on documentation and evangelism. We are providing weekly trainings, "office hours", and free one-day trainings.

3. The longevity legacy of DoneJS.

Longevity is an important and underrated consideration when evaluating JavaScript frameworks. DoneJS, which is highly compatible with JavaScriptMVC 3.3, despite being rewritten in many new technologies, proves our commitment to being a steady hand. For 8 years, the DoneJS and JavaScriptMC frameworks have walked the line between innovation and backwards compatibility.

Next Generation Features

DoneJS packs a wide variety of features essential to modern JavaScript applications. We believe it solves many of the most important, but challenging problems in better ways than alternative solutions.

For this article, it’s difficult to pick DoneJS’s best features from its huge list of features. For example, DoneJS can turn on worker thread rendering and diffing with one change. How cool is that! But, for this release article, we’ll focus on the features that have the biggest impact on your applications:

  • Server-side rendering
  • Faster loading sites
  • Real time behavior
  • Mobile and desktop app builds

Before diving into features, there are a few other things to know about DoneJS:

  • DoneJS is agnostic to any server-side language or framework. While NodeJS is a requirement in order to use DoneJS' CLI tools, you can choose any language to implement your backend, including Python, Java, Ruby, or .NET.
  • You can mix and match many of DoneJS’s underlying libraries. Use StealJS with React. Use CanJS with RequireJS. Test with Jasmine or Mocha. If there’s some integration you’d like to add, let us know!

Ok … ok … lets see the tech!

Server-side rendering

DoneJS applications are written as Single Page Applications (SPA). SPAs use client-side JavaScript to produce all HTML. The clean separation of frontend and backend is great for maintenance. But single page applications (like GMail) are notorious for spinners.

User experience with and without a spinner

No one wants to see a spinner!

Making a rich application without spinners can be tricky. Most alternative approaches are either slow, difficult to use, or difficult to maintain. DoneJS’s server side rendering solves all of those problems.


DoneJS’s server-side rendering is super fast. Rendering happens asynchronously within NodeJS’s event loop using a lightweight virtual DOM. Let’s break that down:

By asynchronously within NodeJS’s event loop, we mean that any IO, such as requesting data, is non-blocking. This allows partial rendering of the resulting page while it waits for data.

The page rendering is done with a lightweight virtual dom which is much faster than rendering with an actual DOM.

The following diagram illustrates what happens when two pages are requested at about the same time. Notice that when data is requested by one page, other pages can be processed:

enter image description here

Easy to use

Server-side rendering shouldn’t be an afterthought, something only turned on in production, where you suddenly discover problems. While developing, if you make changes, you should immediately be able to see how they affect server-side rendering.

DoneJS’s server side rendering uses the same hot module replacement that takes place on the client. When you change a file, the server-side rendering code is updated so the next refresh shows html that is rendered with the latest code. No need to restart the server!

DoneJS’s server side rendering is available as express middleware, making setup as simple as:

app.use('/', ssr({
  config: __dirname + '/public/package.json!npm',
  liveReload: true

Easy to maintain

Server-side rendering should require as few changes to your application code as possible. Alternate solutions:

  • Use a non-DOM like virtual DOM which makes using DOM or jQuery based widgets impossible.
  • Require a synchronous render call which means that all data needs to be present prior to rendering.

DoneJS avoids these limitations by using a virtual DOM that looks very similar to a normal DOM. This means that modules that modify the DOM with jQuery can work with server side rendering. And, it means that modules, like custom elements, can fetch their own data. They simply need to indicate what they are waiting for with the waitFor method. This looks like:

  tag: "user-name",
  template: can.stache( "{{user.name}}" ),
  viewModel: {
    init: function () {
      var promise = User.getOne({ id: this.attr("id") });
      this.attr( "%root" ).waitFor( promise );
      promise.then( (user) => { 
        this.attr( "user", user ); 

DoneJS goes even one step further. If .waitFor is swapped with .pageData, the promise’s resolved data will be embedded in the HTML response. When JavaScript in the client eventually tries to make the same request, the embedded data is used instead.

The following video shows how embedded data works:

Faster loading sites

DoneJS has a great performance story. Check out the homepage's performance section for the complete picture:

Faster Loading Sites

DoneJS speeds up perceived load times and actual load times with a combination of technologies:

We already covered how DoneJS improves server-side rendering. Here we will talk about how it’s able to load your site’s JavaScript and CSS faster, and highlight how DoneJS makes this uniquely simple.

DoneJS is able to load your site faster because it downloads less code, faster. It only downloads the JS and CSS it needs for a given page and it downloads them from a content delivery network (CDN), which makes downloads faster.

What’s unique about DoneJS is how easily you get progressive loading and optimized bundles. To progressively load something, you simply wrap a conditional section in your template with <can-import>.

For example, you might want to:

  • load and show the <home-page> element when the url is /home
  • load and show the <chat-page> element when the url is /chat

To do this, you simply write this behavior in the template:

{{#eq page 'home'}}
  <can-import from="components/home">
    {{#isResolved}}<home-page/> {{else}} Loading {{/}}
{{#eq page 'chat'}}
  <can-import from="components/chat">
    {{#isResolved}}<chat-page/> {{else}} Loading {{/}

That’s it! DoneJS’s build system detects those <can-import>s and builds an optimized bundle for those pages.

DoneJS’s build algorithm is also unique. It figures out the best way to build your application automatically. The following video explains:

DoneJS can be easily configured to deploy and load from a CDN service. Once configured, just write:

donejs deploy

to push out your static content.

Real Time

DoneJS makes it easy to add real time behavior to any backend system.

DoneJS is server-agnostic. It doesn’t force you to adopt a certain specific service or database technology. If your server can produce a REST-ish interface, and can send the browser messages when records are created, updated, and deleted, DoneJS can automatically update the UI when those changes happen.

It accomplishes this with set logic. For example, the following url returns all new todos that belong to user 5:


With jQuery, you might have made this request like:

$.get("/services/todos", {type: 'new', ownerId: 5})

in DoneJS you’d do it like:

Todo.getList({type: 'new', ownerId: 5})

The params passed to $.get and Todo.getList are {type: ‘new’, ownerId: 5}. These params represent a set.

When the client pushes a created todo to the browser like:

{id: 100, type: ‘new’, ownerId: 5, name: "do dishes"}

DoneJS knows to add the created todo where it belongs in the set {type: 'new', ownerId: 5}. DoneJS adds the created todo to todos received by .getList, which updates the UI automatically. The following video explains it:

Treating the parameters you pass to an ajax request as representing a set is a very simple idea. By using sets, we’ve not only been able to make real-time behavior easy to set up against any backend, we’ve used it to add other performance optimizations like:

  • fall through caching
  • inline caching
  • combining requests

Real-time and other optimizations are part of can-connect which can be used totally independently of every other part of DoneJS and CanJS.

Mobile and Desktop builds

If a server-side rendered, real time, high-performing web application isn't enough, DoneJS applications can be quickly ported to native mobile and desktop applications using Apache Cordova and NW.js. To build to cordova’s mobile Android or iOS platform, simply run:

donejs add cordova

and then

donejs build cordova

To build a desktop application using NW.js, run:

donejs add nw

and then

donejs build nw

When you do this in our getting started guide, you see something like:

Looks like there's going to be even more Hipchat, Slack, Campfire and Gitter competitors soon.

Hopefully, you’ve just seen how DoneJS solves the critical problems of building real-time applications, that run everywhere and load super quickly. We believe we’re the only framework that solves all these problems, and certainly the only that does them as elegantly.

But, that’s not all DoneJS done do! There’s a ton of other features to check out:


Great technology that keeps getting better doesn’t mean anything if you don’t know how to use it. Currently DoneJS's site has two guides:

  • Quick start - Build and deploy a real-time, server-side rendered, progressively loaded application that runs on the desktop, iOS, and Android.
  • In depth - Build, test, document, continuously integrate, and continuously deploy a real-time, server-side rendered, progressively loaded application that runs on the desktop, iOS, and Android.

Historically, documentation and guides is a place where we’ve had room to improve.

This is why helping the community learn DoneJS is one of our primary goals. After this release, we’re taking a 3 month break from nonessential feature development to focus on writing documentation, guides, and more example applications.

But our commitment to education extends beyond that.

First, we have weekly JavaScript, jQuery, and DoneJS trainings. Our goal is to create a video series that anyone can pick up and learn to build anything the right way. We started in May so there’s already 23 hours of content to get you started.

Second, we will provide $5* one day trainings to any group of 10 people or more, anywhere in the US. We’ve already created 9 different meetups across the United States. Sign up for a training in your local city.

If your city isn’t listed, but you, your user group, or company are interested, let us know by email - contact@bitovi.com. If you are outside the US, let us know too. We will likely require more attendees, or a specific date, but we want to help you learn too.


World class applications take months or years to build. The continuing maintenance, if the application is successful, will often last over 5 years. However, the JavaScript landscape changes almost constantly. New frameworks emerge with exciting new technologies and often replace old frameworks and technologies in completely incompatible ways. We recently wrote an article on this problem.

We believe that with this release, DoneJS demonstrates it is the best example of striking the balance between persistent innovation and backwards compatibility. DoneJS is effectively the 7th major version of JavaScriptMVC. It has a technical legacy over 8 years old.

JavaScriptMVC is over 8 years old.

8 years ago, JavaScriptMVC included many of the features no frontend developer would be without today:

  • Routing Templates
  • Models
  • Module loader and builds
  • Testing

Since that time, we’ve consistently improved the framework, adding many ideas from other frameworks and libraries:

  • Observables
  • Live binding and two way binding
  • Custom Elements
  • DOM diffing

...but adding technologies is actually easy. We are most proud of digging our users out of holes while maintaining large amounts of backwards compatibility. When JavaScriptMVC was created, there was no NodeJS. There wasn’t even AMD. When JavaScriptMVC 3.3 was released two years ago, it was based on Rhino (a Java based JavaScript engine) and used a module format (steal) that no one supported.


We needed to get everyone on to NodeJS and onto CommonJS, AMD or ES6 modules. We rewrote StealJS on NodeJS to support the new formats, while maintaining the legacy steal format. With the release of DoneJS, JavaScriptMVC users will be able to upgrade their app incrementally to standard module formats.

We also rewrote DocumentJS and our test launching tool in NodeJS.

Similarly, when our original string-based mustache template engine’s live binding was slow as molasses, we rewrote a new, highly backwards compatible, DOM fragment based template engine that's over twice as fast - stache.

The consistent evolution of our tools can be a bit bumpy. Nearly every major release guided (but not forced) our users to change technologies. For example:

  • Using QUnit instead of our custom assertion library.
  • Changing EJS templates to mustache based templates.
  • Using custom elements and MVVM instead of MVC.

Now, with DoneJS, we’re hoping people will switch to:

Change isn’t easy. But lots of little changes spread out over time is better than rewriting an entire application in a new framework every 3 years.

bumpy road, but there's a road

This is why we are committed to always evolving our technology to improve with new tools and techniques while being highly backwards compatible between major releases.

Unlike other framework’s sponsor companies, we aren’t motivated by search results, or connecting you to friends. We care about one thing, helping people and teams make amazing applications.

If you are looking for a framework that grows with you and your team, DoneJS is the framework for you.

Concluding thoughts

I’m very excited for the next chapter of JavaScriptMVC. A huge thank you to everyone who’s contributed, promoted, tweeted, or used JavaScriptMVC in the last 8 years. Getting from JavaScriptMVC to DoneJS has been a tremendous effort by a lot of very skilled software engineers.

We have some cool new features on the roadmap. Please let us know if you’re interested in helping.

And if you haven’t yet checked out donejs, start now with the getting started guide. Your journey begins by installing donejs.

npm install donejs -g


  • - We only charge to make sure people are committed to being there when signing up. We are going to bring more than $5 of swag per person to every event.