Skip to main content

From GWT to AngularDart: a case study with source code

Lots of interesting articles about Dart have been cropping up on lately. We've decided to cross post them here so that followers of this blog won't miss out on them. We'll start by Istvan Soos's GWT-to-Dart case study, published on Friday. — Filip Hracek

Earlier this year I was asked if there’s a good way to compare developing web UIs in Google Web Toolkit (GWT) vs. Dart, specifically AngularDart. Having worked with both GWT and Dart, I had a good idea of the differences, but as I thought more, I started to wonder how hard it would be to migrate a GWT application to AngularDart. This article describes what I’ve found while doing just that.

The GWT Mail Sample was an ideal place to start: it’s much more than a trivial example, with diverse features and complex UI interactions, yet it’s still manageable in size.

If you’re in a hurry, take a look at the working demo and the source code, or scroll to the bottom for the conclusions.

Screenshot of the demo.

The method of migration

I’ve done the migration without any automated compiler. While it may be possible to write a tool to automatically convert the GWT templates to Angular, or the backing Java code to Dart, I wouldn’t suggest doing it that way. Chances are that the template, the styling, or the Java code uses patterns that are better served with new approaches. I’ll list a couple of these new approaches in the next section.

My process was very simple. I put the GWT and the AngularDart code in the same git repository and did the following cycle:

  1. Select a small or medium-sized chunk of the GWT codebase. Usually this was a single widget, or a smaller part of a complex widget.
  2. Carefully explore the features and edge cases that are in the code. Most of a proprietary codebase will be some kind of edge case that somebody stuffed in it. If there are more than 5 edge cases, it is a good indication that the task is too large and needs to be split into multiple chunks.
  3. Implement the selected part in AngularDart. This sounds simple, because it is simple. :-)
  4. Delete the selected part from the GWT codebase. The GWT application will no longer build, but you can easily track the parts that you haven’t migrated yet.

You can check my progress and individual steps either by observing the commit history, or by looking at the file that I was writing along as I was doing the changes. One interesting observation: writing down the changes took much more time than implementing the code in AngularDart.

Old solutions vs. new ones

The bulk of the migration is straightforward: simple templates and styles can be mapped to their Angular counterparts easily. I won’t waste your time with minute details; instead I’ll just talk about the parts that differ.

The first and most obvious difference is the design: the Angular version uses material widgets from the angular2_components package. The package has a lot of useful components, if you are starting with AngularDart, you should try to go with that. While both stacks have a great selection of ready-to-use components, and most of them have 1:1 mappings with regard to features and settings, sometimes you need to use your judgement on which to use or select.

Watch the new version alongside the old one. AngularDart Components make it easy to have nice animations and consistent component views.

I missed a few things that aren’t available yet in AngularDart Components, like a table and tree component. However, as you can see in the log, it was really easy to implement them with Angular’s *ngFor templates. For example, the list of mail items is handled by the following template, which is much simpler than GWT’s table initialization in

<div *ngFor="let item of items"
  <div class="col sender">{{item.sender}}</div>
  <div class="col email">{{}}</div>
  <div class="col subject">{{item.subject}}</div>

I was told that team is working on open sourcing more components; fingers crossed that a more complex table will be included soon.

Less intriguing, but an important difference is the lack of static variables and the handling of singleton instances. In the GWT version, the list of email messages is stored in a static field in In the Dart version, the same (and much more) functionality is handled by MailService, which is injected and better for unit testing.

I’ve started with a mock implementation for easier development (also to match the GWT version), while later on it is easy to plug in a real API behind the web client. For example, configuring the injection is as simple as the following code. Switching to a real implementation would be just changing the useValue: part of it.

Change to real implementation when ready.

On a more subjective note, I find the separation of code, HTML template, and CSS styles much better in AngularDart than in GWT. The GWT codebase allowed sprinkling the Java code with both styling details and template construction, and those parts were the hardest to migrate to a cleaner version.

End result by the numbers

While the AngularDart version has more features, and I’ve implemented custom components like the tree, overall I needed to write less code than what was needed for the GWT original. Depending on how you count, code size is down by 30%.

I was developing the application using Dartium, so I didn’t need to compile the Dart code to JavaScript; everything was done with a low-latency type-save-refresh cycle. However, the end result needed to be compiled to JS, and it may provide value to compare the numbers. On my Macbook Pro, the GWT applications’ compile times were:

  • 26 seconds for 1 permutations,
  • 11 seconds if the Java source code was already compiled, and
  • 40 seconds for all 5 permutations.

The Dart version took about 15–20 seconds to compile to cross-browser ES5. That is not blazing-fast, but it is faster than the GWT compiler.

Compile times (in seconds)

Last, a few notes about the output JavaScript’s size. The GWT compiler produces different JS version for each permutation (target browser), while the Dart compiler emits only a single compiled version. GWT’s output was roughly 207 KB / permutation (1M total for all 5, 84 KB/permutation when compressed), while the AngularDart version resulted in 689 KB (178 KB compressed).

Considering that the application logic is more complex (for example: diverse widgets, ripples, more detailed mail item handling), the larger JS size is not a surprise, although I hoped it would be smaller. Fortunately for us, a huge part of it is “fixed cost”, and additional components increase the size only a little (proportional to their complexity).


Both technologies originate from Google and both are capable of supporting larger team sizes, but they represent two very different eras. I have found the GWT code harder to read and reason about; the AngularDart version is more compact and easier for me. But don’t trust my point of view blindly. I strongly suggest that you try out the application and check the source codefor yourself.

I have also found the material components refreshing, and most of the time they were out of my way. Compared to that, styling and customizing GWT components is harder, requiring time that would be better spent on the application itself.

If you are looking to migrate your GWT app to a newer technology, AngularDart is a viable option. After all, Google is doing the same thing: they are migrating their critical apps from GWT to Dart (see their AdSenseand AdWords interviews).

— István Soós, March 10, 2017, canonical link

Popular posts from this blog

A stronger Dart for everyone

We are constantly asking ourselves:
How do we make developers even more productive when writing Dart apps? We believe that a critical part of the answer to this question is to make strongmode – a sound static type system for Dart – the standard for all Dart developers.

Teams that use Dart to build apps like Soundtrap, AdWords, AdSense, and Greentea say they really enjoy using strong mode features, such as early error detection. In fact, teams that have switched completely to strong mode cite not only early error detection but also better code readability and maintainability as major benefits. We hear this both from small teams and – even more so – from large teams with hundreds of developers writing and maintaining millions of lines of Dart code. As Björn Sperber from Soundtrap says,
Strong mode and the smooth integration with IntelliJ is a joy to use and a huge improvement. If you’ve tried out Flutter, you’ve already used strong mode checks from the Dart analyzer.

Given the benefits …

AngularDart 3.0: Easy upgrade, better performance

AngularDart 3.0 is now available. It brings better performance and smaller generated code, while also making you more productive.

Version 3.0 is an evolution: although it has some breaking changes (detailed below), it is a smooth upgrade due to minimal public API adjustments. Most of the progress is under the hood—in code quality, stability, generated code size, performance, and developer experience.

Code quality:
2731 instances of making the framework code more type safe (using sound Dart).The AngularDart framework code size is down by 12%.Many additional style updates to the codebase:Changed to use idiomatic <T> for generic methods.Removed NgZoneImpl, all the code exists in NgZone now.Stability:
Many CSS encapsulation fixes due to update with csslib package.Fixed bugs with IE11.

For the Mail sample app, we see 30% faster time-to-interactive (currently 3812 ms on a simulated 3G connection, measured via Lighthouse).Our large app benchmark shows 2x faster render times of…

Dart 1.24: Faster edit-refresh cycle on the web & new function type syntax

Dart 1.24 is now available. It includes the Dart Development Compiler and supports a new generic function type syntax. Get it now!

Figure 1: DDC debugging in Chrome.

Some notable changes in this release:
pub serve now has support for the Dart Development Compiler. Unlike dart2js, this new compiler is modular, which allows pub to do incremental re-builds for pub serve.In practice what that means is you can edit your Dart files, refresh in Chrome (or other supported browsers), and see your edits almost immediately. This is because pub is only recompiling your package, not all packages that you depend on.There is one caveat with the new compiler, which is that your package and your dependencies must all be strong mode clean.You can also use the new compiler to run your tests in Chrome much more quickly than you can with dart2js.Read more in the changelog.You can now publish packages that depend on the Flutter SDK to pub. Moreover, has started tagging Flutter plugins with …