Turducken Divide and conquer large GWT apps with multiple teams Rob Keane Google / Ad Exchange Front End rkeane@google.com
Turducken Complex GWT apps can involve multiple teams with different release cycles. Compile times can quickly become prohibitive when your codebase grows into millions of lines. “Turducken” is a design pattern to combine multiple GWT apps that can be built and released by separate teams while providing a seamless, snappy user experience
A note on the name... Turkey + Duck + Chicken
For this... ...not this
Large projects Multiple... teams? release cycles? testers? frameworks?
Terminology In the context of this talk... Module == GWT Module with entry point
One last note... This is a design pattern not a library
Turducken 1. Bob’s Sticker Emporium 2. Conquering Multiple Entry Points 3. Other uses
Bob’s GWT App Bob has a sticker site bobs-sticker-emporium.com BOB’S STICKERS Stickers BUY! BUY! BUY!
Success! Bob adds more options... bobs-sticker-emporium.com Your Cart (2) BOB’S STICKERS Stickers Create your own! BUY! Customize BUY! Customize Sell a sticker! BUY! Customize
Things are getting complex ➔ Still one giant GWT module ➔ Compilation takes several minutes ➔ A few megabytes of JS ➔ 5 teams! ➔ Continuous integration ➔ Release coordination
What should Bob do? How do you split up a large GWT project?
One GWT module × One release × One build × Very large if code isn’t split properly × Difficult to test
Many GWT modules × Full page reloads × Code can’t be split between modules
One GWT module? ಠ_ಠ Many GWT modules? ಠ_ಠ
Ultimately multiple GWT modules is the only real option
Multiple modules Split into multiple GWT entry points bobs-sticker-emporium.com Your Cart (2) BOB’S STICKERS Stickers Create your own! BUY! Customize BUY! Customize Sell a sticker! BUY! Customize
Bob Full page refresh between each module
Research showed that half of aggregate user latency was due to full page reloads
Turducken 1. Bob’s Sticker Emporium 2. Conquering Multiple Entry Points 3. Other uses
Container (GWT Module) Inter-app Event Bus (JSNI) Virtual historian Virtual historian Virtual historian Tab A Tab B Tab C (GWT) (GWT) (GWT)
The container ➔ ➔ ➔ ➔ A GWT module (mostly) The first thing to load on the page Loads the other modules on demand Communicates with modules through inter-app event bus
Loading all of the modules? Yes. This actually works
Bob’s container bobs-sticker-emporium.com Your Cart (2) BOB’S STICKERS Stickers Create your own! Sell a sticker! BUY!
Load multiple GWT modules? ➔ When a module is loaded, a <script> tag is added to the <head> ➔ Everything lives in the same container
Memory usage ➔ Browsers are good at hiding elements ➔ Memory only increases marginally when loading new modules
DOM Assumptions // Old RootPanel.get().add(myRootWidget); // New ContainerHelper.getModulePanel().add(myRootWidget); <body> <div id=”modules”> <div id=”TAB_1_ROOT”>...</div> <div id=”TAB_2_ROOT” style=”display:none”>...</div> <div id=”TAB_3_ROOT” style=”display:none”>...</div> </div> </body>
CSS ➔ Avoid @external as much as possible ➔ Avoid styling tags ... unless the style is truly global ➔ Should be in a “global” CSS file > global.css a { color: #999; }
But I really want @external CSS... When Module “TAB_1” is loaded → When Module “TAB_2” is loaded →
CSS example /* no, no, no */ @external .title; .title { color: pink; font-size: 72px; } /* that’s better */ @external .title; #TAB_1 .title { color: pink; font-size: 72px; }
There’s just one tiny, little issue...
“ All problems in computer science can be solved by another level of indirection Butler Lampson
Container (GWT Module) Inter-app Event Bus (JSNI) Virtual historian Virtual historian Virtual historian Tab A Tab B Tab C (GWT) (GWT) (GWT)
Virtual History Implementation An history implementation that doesn’t alter the “real” URL but instead sends an event
Container History Produces a “safe” URL that contains information about the module For example: #MODULE_A/MyPlace instead of #MyPlace
Container (GWT Module) Inter-app Event Bus (JSNI) Virtual historian Virtual historian Virtual historian Tab A Tab B Tab C (GWT) (GWT) (GWT)
Event bus implementation The event bus that broadcasts between modules needs to be JSNI since it must communicate between GWT modules A simple publish/subscribe interface will do
Code example // Container InterAppEventBus.subscribe(“HISTORY_CHANGE”, updateUrlHandler); // Virtual History in a submodule InterAppEventBus.publish(“HISTORY_CHANGE”, “myNewUrl”);
Message trace for history Virtual Historian Event bus Container Browser Change to virtual history Module load event Real URL is changed
Summary of Turducken ➔ Separate your app into multiple entry points ➔ A container module manages loading the submodules ➔ Carefully manage your CSS ➔ The submodules talk to a virtual historian ➔ A JavaScript/JSNI InterAppEventBus handles events between modules and the container ➔ Events are broadcast that the container handles to alter the real URL
The future ➔ Shadow DOM eliminates a lot of the issues ➔ Eliminate JSNI with GWT 3.0
But wait! There’s more.
Turducken 1. Bob’s Sticker Emporium 2. Conquering Multiple Entry Points 3. Other uses
It’s all about the event bus An inter-app event bus opens up some interesting doors
Inter-app communication Load another module via an event ➔ Settings Module ◆ Change settings from other modules ◆ Global “Accept ToS” message ➔ Chat module
Example ➔ One team maintains “Chat” functionality ➔ Another team maintains a “Profile” page ➔ Launch a chat with a person from their profile ➔ Chat module doesn’t always need to be loaded ➔ Limited coupling between modules
Invisible Modules There can be “background” modules that aren’t visible but handle events ➔ Monitoring session ➔ Caching data for multiple modules
Non-GWT “modules” ➔ Follow the same CSS approach ➔ Write an virtual history implementation ➔ Add hashPrefix to $location in Angular
Where’s the code? ➔ A few small parts ➔ A design pattern, not a library ➔ Tends to be application specific ...but we are considering it
Turducken Complex GWT apps can involve multiple teams with different release cycles. Compile times can quickly become prohibitive when your codebase grows into millions of lines. “Turducken” is a design pattern to combine multiple GWT apps that can be built and released by separate teams while providing a seamless, snappy user experience
no reloads many modules wow such performance different releases wow Questions?

Turducken - Divide and Conquer large GWT apps with multiple teams