Home > CSS, cujo.js, dojo, HTML / DHTML, In-browser MVC > Firefox’s proposed Resource Packages spec blows!

Firefox’s proposed Resource Packages spec blows!

August 3rd, 2010

It’s no secret that one of the keys to a decent user experience is a responsive (fast) user interface. And the most critical component to a fast web app is minimizing the HTTP requests. So it’s no mystery that people are working on ways to solve this problem.

Firefox, of course, is one of the leaders in this area. Their proposal started out fine. Here’s a sample of what it would look like (if you didn’t read the article):

<link rel="resource-package" 
      type="application/zip" 
      href="/static/site-resources.zip"
      content="javascript/jquery.js;
               css/reset.css;
               css/grid.css;
               css/main.css;
               images/save.png;
               images/info.png" />

You specify that the file, /static/site-resources.zip”, contains the listed resources. JavaScript, CSS, and images. (I imagine SWFs and videos would also be options.)

But for some reason, this concise, nearly-valid implementation was trashed in favor of a terse, unfamiliar, and nearly unusable alternative. Here’s what the spec looks like now:

<html packages='[pkg1.zip img1.png script.js styles/style.css]
                [static/pkg2.zip]'>

In this bastardization, the packages are specified as an attribute on the document element (<html> tag). Package definitions in the packages attribute are delimited by square brackets, and the resources within them are delimited by spaces.

WTF? Not only is this ugly and non-standard, but it also has some serious drawbacks. Here’s why:

Reason #1: Any non-trivial web app has hundreds of resources

The spec says that naming the resources is optional. However, not naming them causes the browser to block all further downloads until the resource package is downloaded and unzipped. So to gain optimal performance (not block), we’ve got to list every single resource? Not only is that going to be one hell of a large <html> tag, but it also needs to be maintained every time a new resource is added to the app.

The real answer, of course, is to use a dependency-management and packaging solution. dojo.require and dojo.build do all of the work of resource packaging already. (require.js is a good start at dependency-management for the non-dojo world, but still lacks packaging. Admittedly, dojo only packages javascript and html templates, not css or images. cujo.js will also package css, but still not images.)

With dependency-management, resources are named where they are used, not in some other file. Having to remember to go back and list every resource in every HTML file is nothing short of a maintenance hassle.

But hmmmm. Maybe this is a not as big an issue as I originally thought. If I am using a dependency-management solution, my resource packages would consist of one javascript file, one css file, and a few dozen images. That’s still a lot of image files to maintain, but not as bad as maintaining hundreds of javascript and css files.

One of the reasons the browser needs to block is to allow for overrides. If package, pkg2.zip, has a resource with the same path/name as a resource in a package declared earlier, pkg1.zip, then the resource in pkg2.zip will override (replace) the resource in pkg1.zip. Therefore, the resources in the packages must be delineated — either explicitly or by inspecting the package — before the packages can be used.

Again, this override functionality is just duplicating dependency-management solutions. Object-oriented javascript allows us to override methods and properties. OOCSS allows us to override CSS rules in a different, but equally effective, manner. (cujo.js also allows for HTML template inheritance / overrides (OOHTML?).)

When done properly (small, concise OOJS, OOHTML, and OOCSS files) and combined with dependency-management, the download size should be exactly the same and amount of extra RAM needed by the browser should be small compared to the resource packaging solution.

dojo.require('pkg1'); // base functionality (large)
dojo.require('pkg2'); // overrides (small)

Reason #2: There’s no way to specify a resource package dynamically

This is a non-starter for me. I write client-heavy web apps. These apps are typically long-running and are served to the browser as a single page. In other words, the browser doesn’t load a new page every time the user takes an action. Google Docs and Google Mail are good examples.

Using dojo.require and dojo.build, I can package my apps into as many packages as I like. (They’re called “layers” in dojo.) This is especially important in a few scenarios:

  1. the app will load a package only when needed
  2. the user can switch “theme” packages dynamically
  3. the user can switch language packages dynamically

If Firefox goes forward with the packages attribute on the <html> tag, then I don’t see how this is possible. For example:

var html = document.documentElement,
    myNewPackage = 'pkg3.zip js/myModule.js images/myPng.png';
html.setAttribute('packages', html.getAttribute('packages') + ' [' + myNewPackage + ']');

Even if that did work (which I doubt it would), it would undoubtably be unbearably inefficient. Re-parsing, re-scanning, and re-analyzing every package.

The original proposal did not have this problem. It’s a lot simpler to just add a new <link> tag:

var head = document.documentElement.firstChild, // assumes no comments before head!
    link = document.createElement('link');
link.setAttribute('rel', 'resource-package');
link.setAttribute('type', 'application/zip');
link.setAttribute('href', 'pkg3.zip');
link.setAttribute('contents', 'js/myModule.js; images/myPng.png');
head.appendChild(link);
 
// in dojo:
var head = dojo.query('head')[0];
dojo.create('link', {rel: 'resource-package', type: 'application/zip', href: 'pkg3.zip', contents: 'js/myModule.js; images/myPng.png', head, 'last');

So. Can it be fixed?

Of course. But, frankly, I don’t really care. For us dojo developers, all it’s going to help out with is images. And since we’re using less and less images and more and more CSS3, images aren’t such a big deal going forward. (border-image, border-radius, and gradient, FTW!)

But I guess, for image-heavy apps, there’s still a need. So here’s how I’d fix it:

First of all, abandon that dumb-ass packages attribute. It’s ugly, non-standard, and unworkable for the large apps that really need packaging. Go back to the <link> tag. That was a much better idea.

Or better yet, use the <script> tag. (gasp) And while you’re at it, fix the defer attribute so I can decide whether the package contains any resources that may need to invoke blocking. (It could be a package of non-essential images, for instance.)

Hmmmm…. on second thought, the <link> may be semantically and syntactically better. Therefore, maybe just add the defer attribute (and functionality) to the link tag?

Should it be fixed?

The more I think about the proposed solutions, the more it seems they’re targeted toward trivial web apps/pages. Unfortunately, it’s typically the larger, more sophisticated apps that need the performance boost.

Therefore, I say, why bother?

Instead, let’s find a way to package images and make dependency management a standard feature in javascript!

What do you say? Am I missing something? Do you have a better solution? Please let me know in the comments!

Be Sociable, Share!

CSS, cujo.js, dojo, HTML / DHTML, In-browser MVC

  1. August 4th, 2010 at 02:24 | #1

    I’m not super well-versed on this resource packaging spec and how it’s evolved with Firefox at the helm, but I do know that one issue I have with it is that we are losing all ability to parallel independent resources (say an image and a css file) by forcing them to be in one file.

    As far as I’m concerned, the ability to do parallel loading where necessary is far more critical than some way to homogenize a bunch of disparate resources into a single downloadable file. We don’t want to do dozens of resources, but 1 massive resource file is too few, I think.

    Also, will all these elements be individually cached in the browser, or will the resource package be the cached item? This makes a big difference. Or will the resource package file be cached in ADDITION to the extra files? May be an issue for mobile browsers with limited caches.

    I love all things performance optimization, but this one smells too funny for me to be fully behind. Not sure I’m buying its usefulness.

    • August 4th, 2010 at 07:15 | #2

      Excellent points Kyle!

      I was thinking about LABjs specifically, but not long enough to figure out how it might interact with the packages. I think it comes down to this:

      We, the developers, need to be able to determine the packaging, the dependencies of those packages, and if they’re downloaded in parallel.

  2. Justin Long
    August 4th, 2010 at 09:20 | #3

    The link tag is the best idea, but it should not be in javascript.

    The three tiers (content/resources, functionality, styling) approach is still valid, but the lines are getting blurred.

    The packages are part of the content, as resources, but are not functionality concerns. The content of the page (in this case, you are referencing packages), contain what’s in there, not how it should behave.

    However, the best approach, in my opinion, is to create a branch of the defer attribute, to defer=”oncall”, and then be able to call .load() on the DOM element, to create nonblocking download. And then be able to do the same as you can with stylesheets, namely disabled=”true”, etc.

    tl;dr = Don’t mix content and functionality, and modify defer to handle js made solutions

  3. Mike R
    August 4th, 2010 at 10:38 | #4

    I think the link tag is a better solution, but I’m not sure how I feel about having such a massive content tag. I might prefer if each resource was a node inside a resources tag.

    Perhaps a better solution would be to use omit the resource specification, and use something similar to data urls that point to a package.

  1. August 4th, 2010 at 00:33 | #1
Comments are closed.