I’ve recently been tinkering with Durandal, which is an SPA framework that uses jQuery, Knockout, Sammy, and RequireJS. This is my first experience building an SPA that uses URL hash fragments to manage views/state, and honestly, I’m not very familiar with any of these libraries, aside from jQuery. My point is, I don’t really know if the WPT results I’m seeing are the result of a bug (in WPT)…or the result of how web browsers handle hash fragments. What I do know…is that the results are not what I expected.
(This is difficult to explain, so bear with me.)
Instead of creating an SPA in the traditional sense (i.e., where 100% of the web page’s content is dynamically inserted into the DOM), I want to design an app that functions more like a Flash widget. That is, I want to embed the app-controlled DOM element(s) into a standalone web page of static content (aka, the host page). Furthermore, I need the app to meet the following criteria:
Negligible impact on host page’s load time
Not a single point of failure for the host page
In order to meet these criteria, I’m designing the app (including all the 3rd-party libraries mentioned above) to be lazy-loadable. This is something I’ve done many times before; the only major difference this time is that the app appends a hash fragment to the host page’s URL (compliments of Sammy.js).
So basically, the page load sequence I was expecting would look something like this:
host-page.html is downloaded
style.css and script.js are downloaded/parsed
script.js defines a callback that dynamically loads app.js, and attaches it to window.load
host-page.html static content is rendered
Document Complete (i.e., window.load event fires)
app.js is dynamically inserted into the head section
[*]app.js begins downloading dependencies, populating its designated element on the host page, rendering content, etc.
In other words, I expected the WPT waterfall view to show 3 HTTP requests, then the Document Complete line, then app.js, followed by a long list of 3rd-party libraries and AMD modules.
What I’m actually seeing is…um…not that?
IE6 - IE9 show most of the app files being downloaded before the blue line. In other words, it looks like I’d expect if app.js were hard-coded right before the host page’s /body tag.
IE10 looks right.
Chrome looks right.
Firefox looks right.
Safari times out and doesn’t show the blue line at all.
Android 2.1 is perhaps the most confusing. It looks like it downloads half the app files on the initial page view, and the other half on the repeat view?
Based on where IE6 - IE9 are drawing the blue line, it appears as though maybe they’re considering the URL change (i.e., when the #/ is appended) to be the point where the Document Completed?
Anyway, this whole thing is virtually impossible to explain without an example, so…I spent like 100 years creating a full demo, and I put it up on Github. You can find the repo here.
The repo is set up with Github Pages, so the test pages are live (links below). So far, I’ve tried 4 variations (e.g., changing the require.js config, initiating the app in different ways, etc.), all of which had similar results, except for the last one. For the last one, Page D, I modified Durandal so that it doesn’t automatically change the URL. This was the only real breakthrough I made; Page D lazy-loads as you’d expect. So there’s something about dynamically appending the hash fragment that causes WPT to act weird.
Or maybe it’s not WPT. Maybe this is such an esoteric use case that the browsers all respond to it differently?
Anyway, here are the test pages I’ve been playing around with:
Page D currently has a problem where the app is preventing link clicks from actually navigating to their respective URLs. So to get from Page D to Page C, you might need to click the Page C link and then hard-refresh the page.
The WPT results (linked to from each test page) are just a snapshot–the test page has changed since the tests were originally run–so be sure to click “Rerun this test” to get updated results.
[*]I’ll most likely continue to make (arbitrary) changes to this repo. In other words, the live pages are not stable.
Bottom Line: Can someone please explain why WPT shows weird test results for web pages that embed asynchronously lazy-loaded single-page applications that dynamically append hash fragments to their URLs?