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 technique to combine multiple GWT apps that can be built and released by separate teams while providing a seamless, snappy user experience.
Turducken - Divide and Conquer large GWT apps with multiple teams
1. Turducken
Divide and conquer large GWT apps with
multiple teams
Rob Keane
Google / Ad Exchange Front End
rkeane@google.com
2. 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
9. Bob’s GWT App
Bob has a sticker site
bobs-sticker-emporium.com
BOB’S STICKERS
Stickers
BUY!
BUY!
BUY!
10. 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
11. Things are getting complex
➔ Still one giant GWT module
➔ Compilation takes several minutes
➔ A few megabytes of JS
➔ 5 teams!
➔ Continuous integration
➔ Release coordination
12. What should Bob do?
How do you split up a large GWT project?
13. One GWT module
× One release
× One build
× Very large if code isn’t split properly
× Difficult to test
14. Many GWT modules
× Full page reloads
× Code can’t be split between modules
21. Container (GWT Module)
Inter-app Event Bus (JSNI)
Virtual
historian
Virtual
historian
Virtual
historian
Tab A
Tab B
Tab C
(GWT)
(GWT)
(GWT)
22. 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
25. Load multiple GWT modules?
➔ When a module is loaded, a <script> tag is added to
the <head>
➔ Everything lives in the same container
26. Memory usage
➔ Browsers are good at hiding elements
➔ Memory only increases marginally when
loading new modules
27.
28. 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>
29. 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;
}
30. But I really want @external CSS...
When Module “TAB_1” is loaded →
When Module “TAB_2” is loaded
→
31. 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;
}
36. Container History
Produces a “safe” URL that contains
information about the module
For example:
#MODULE_A/MyPlace
instead of
#MyPlace
37. Container (GWT Module)
Inter-app Event Bus (JSNI)
Virtual
historian
Virtual
historian
Virtual
historian
Tab A
Tab B
Tab C
(GWT)
(GWT)
(GWT)
38. 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
40. Message trace for history
Virtual Historian
Event bus
Container
Browser
Change to virtual history
Module load event
Real URL is changed
41. 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
42. The future
➔ Shadow DOM eliminates a lot of the issues
➔ Eliminate JSNI with GWT 3.0
45. It’s all about the event bus
An inter-app event bus opens up some
interesting doors
46. Inter-app communication
Load another module via an event
➔ Settings Module
◆ Change settings from other modules
◆ Global “Accept ToS” message
➔ Chat module
47. 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
48. Invisible Modules
There can be “background” modules that
aren’t visible but handle events
➔ Monitoring session
➔ Caching data for multiple modules
49. Non-GWT “modules”
➔ Follow the same CSS approach
➔ Write an virtual history implementation
➔ Add hashPrefix to $location in Angular
50. Where’s the code?
➔ A few small parts
➔ A design pattern, not a library
➔ Tends to be application specific
...but we are considering it
51. 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