Almost Getting To The Point

In Does Size Matter? we concluded that, while aggregating JavaScript code is generally a good thing, at a certain point we might need to back off and consider breaking up our code.  At the moment ADF Faces is at one end of the size vs. round trip spectrum.  The number of round trips is optimized by combining all JavaScript code into a single library (single round-trip).  At the other end of the spectrum, we could optimize total downloaded code size by breaking out each JavaScript “class” into its own library (many round trips).  Clearly some happy medium – a balance between size and round trips – is needed.

Perhaps the ideal solution would be a GWT-like approach.  We could consider analyzing JavaScript code usage to determine the bare minimum code requirements down to the method level.  While this would certainly lead to a highly optimized solution, it does have one drawback.  This is hard!  In a traditional JEE/JSP/JSF application, JavaScript code lives in a number of places, some of which are not exactly easy to identify.  JavaScript code may be bundled up into jar files or war files (not too hard to identify), or may live inside of JSPs or other templates (slightly harder to identify), or may be generated programmatically via Java code (very hard to identify).  That’s not to say that this approach is impossible or not worthwhile; this is clearly an idea that is worth pursuing.  However, given the scope of such a project, a solution along these lines was simply not in the cards for our current release.

So, if we aren’t able to perform code analysis to produce a minimal application-specific JavaScript library, what are our other options?  Let’s start by considering some requirements that we would like our solution to meet.

1.  Aggregation.  We want a solution that allows us to group JavaScript files into larger “chunks”.  At the moment, the ADF Faces JavaScript code is delivered in one big chunk.  We want to break this up into smaller chunks that can be delivered to the browser independently.

2.  Specificity.  Any given chunk should only be downloaded/loaded on pages that need the chunk.  So, for example, if the JavaScript code for the af:richTextEditor  component lives in its own chunk, this code should only be pulled in on pages which use the af:richTextEditor component.

3. Cacheability.  Chunks should be cacheable.  That is, the contents of the chunks should not vary from page to page.  If a chunk is required by both page A and page B, it should not be necessary to download the chunk a second time when navigating from page A to page B.

4. Tunability.  The number and content of the chunks should be configurable at the application level.  Different applications have different JavaScript usage patterns and should be able to optimize the chunks (ie. optimize the size vs. round-trip trade-off) accordingly.

5. Abstraction.  When defining the contents of a chunk, the application developer should not be required to reference the physical JavaScript file names or locations.  For example, when defining a chunk that includes the JavaScript code for the af:richTextEditor component, the application developer should not need to know that the af:richTextEditor implementation relies on code located in the “oracle/adfinternal/view/js/laf/dhtml/rich/AdfDhtmlRichTextEditorPeer.js” file.  File names and locations are implementation details that are easily changed/re-factored.  Instead of relying on file names, the application developer should reference the code via some logical identifier that is guaranteed not to change.  This protects both the component author (freedom to change/re-factor) and the application developer (freedom from breaking when pesky component authors make changes).

6. Defaults.  Some default set of chunks should be provided so that application developers are not forced to go to the trouble of defining their own chunk layout.

7. Ordering.  The solution should ensure that chunks are loaded in an order that honors code dependencies between chunks.  If chunk A depends on code in chunk B, chunk A should be loaded before chunk B.

8. Extensibility.  Custom components should be able to participate in the solution.  That is, it should be possible to chunk custom component code in the same manner as ADF Faces framework/component code.

Assuming we’ve hit the key requirements (and hopefully we did, as I am running out of serious-sounding words to describe each requirement), these requirements translate into a fairly straightforward solution.  Which of course is the topic of my next entry. 🙂

One Response to “Almost Getting To The Point”

  1. Hello, JavaScript Library Partitioning! « Andy Schwartz’s Weblog Says:

    […] Andy Schwartz’s Weblog Just another weblog « Almost Getting To The Point […]

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: