#326 ✓ resolved

Asynchronous script loading

Reported by brianchirls | February 10th, 2011 @ 01:01 AM | in 1.0 Release (closed)

Most (all?) of the Popcorn sites I've seen load all the scripts in the header, causing quite a lot of delay before the page can be displayed. The official demo loads 16 scripts in the header. Thirteen of those are all on the same server, so they can only be downloaded one at a time. The browser can't display anything until every single one of those scripts loads. On my (pathetic DSL) connection, with an empty cache, the demo takes about 18 seconds before anything at all shows up at all.

If we can load all of those scripts at the end of the document, we can give the user something to look at much sooner, making the site feel faster. (For reference: Best Practices for Speeding Up Your Web Site and Usability Engineering) This can be particularly tricky, since all the plugin and parser scripts will crash on loading if the Popcorn object hasn't been defined first. So we need to make sure they load in order.

One way to fix this could be to have all dependent scripts check for the Popcorn object and, if it's missing, enqueue themselves into some global array, which popcorn.js will look for when it's done loading.

In the meantime, I'm happy to contribute some code I wrote for exactly this purpose. I wrote it for a number of HTML5 and WebGL demos I've been building, and it'll dynamically load scripts, media, fonts or other data in whatever order you tell it.


I modified the Semantic Video demo to use Loaderator, and the page displays in about 2.5 seconds instead of 18. You can see how it works here:


Comments and changes to this ticket

  • Rick

    Rick February 12th, 2011 @ 03:05 PM

    I just want to throw this into the mix: http://requirejs.org/

    RequireJS is CommonJS compliant, battle tested and widely regarded as best solution for async module loading systems.

  • annasob

    annasob March 24th, 2011 @ 04:40 PM

    • Milestone set to 0.5
    • Assigned user set to “brianchirls”
    • Milestone order changed from “28” to “0”

    Hey Brian,
    Is this still an issue. Right now we are using getScript to load all of the script which is done on a thread. I believe the html content is loaded and visible. Can you confirm. Also feel free to post a patch =>"I'm happy to contribute some code I wrote for exactly this purpose."

  • Rick

    Rick March 24th, 2011 @ 04:47 PM

    @annasob, with popcorn-complete.js being our "shipping" package, this is likely a non-starter. I think if we explore the truly async module route, I have to insist that we do so under CommonJS AMD http://wiki.commonjs.org/wiki/Modules/AsynchronousDefinition

  • brianchirls

    brianchirls March 24th, 2011 @ 04:55 PM

    Hey Anna,

    Yes, it is still an issue. I'm looking at the semantic video demo included in the repository here:


    ...and the popcornjs.org main page as well, which is a little better, but not much.

    Both examples load all of the plugin scripts before the entire page is loaded, and there is a visible delay. (On the popcorn main site, you can see that the delay happens after the top nav bar is displayed, which is right where all those plugin scripts are loaded.

    I'm not sure to what degree this is something that should be specifically addressed in the Popcorn.js (did we ever solve that name branding problem?), but it should certainly be handled better in the examples.

  • Rick

    Rick March 24th, 2011 @ 05:20 PM

    Those pages likely need to be updated to not call all of the scripts but instead use the minified package script.

    Also, I'm seeing DOMContentLoaded of popcornjs.org in less then 1s: http://gyazo.com/f86b45e5e8377ec48764ef691e11cd1d.png

  • Steven W

    Steven W April 19th, 2011 @ 11:22 AM

    • Milestone changed from 0.5 to 0.6
  • annasob

    annasob May 5th, 2011 @ 11:00 AM

    Hey Brian,
    I really love this idea however the consensus is to use RequireJS. This is simply due to the fact that it is well known, used and tested. Feel free to dump this ticket if you do not want to use RequireJS or if you believe you library is faster make a case for it.

  • brianchirls

    brianchirls May 5th, 2011 @ 11:14 AM


    Thanks for the update. Yes, RequireJS makes sense in this context. I'm more concerned with solving the problem than with using my particular code.

    I have not done a speed comparison of loaderator vs. RequireJS, though loaderator is definitely faster than loading all the scripts in the header, as I mentioned in my original post.

    loaderator was designed for complex, media-heavy applications, and the main advantage is that it handles different media types: images, audio, video, fonts, AJAX data, etc. So if you're building something with lots of those media, and you need to make sure they're loaded up before starting your scripts, I suggest you reconsider loaderator. (It's especially good for WebGL, since things can get ugly if you try to create textures from images that aren't loaded yet.)

    But if you're only pre-loading scripts, then stick with RequireJS.

  • Bobby Richter

    Bobby Richter May 5th, 2011 @ 11:36 AM

    In general, seeing this kind of attention in our demo/plugin code is a good thing, so thanks for the thoughts, Brian.

    Does it make sense to develop something in popcorn that uses require.js to load scripts as necessary? Maybe a simple wrapper?

    Popcorn.require(['googlemap', 'flickr', 'bobsawesomeplugin'], 'plugin/directory/');

    Keep in mind that we do want to keep things as generic as possible. Even this might begin to encroach a little on how people prepare their webpages.

  • David Humphrey

    David Humphrey May 5th, 2011 @ 11:40 AM

    NOTE: looking forward to seeing bobsawesomeplugin landing.

  • Rick

    Rick May 8th, 2011 @ 12:40 PM

    • Assigned user changed from “brianchirls” to “Bobby Richter”

    Just a note, Popcorn.require itself would have to be an "add-on" as it's dependency on Require.js (per Bobby's comment) disqualifies it for Popcorn.js core inclusion.

  • annasob

    annasob May 10th, 2011 @ 05:28 PM

    • Milestone changed from 0.6 to 0.7
  • Rick

    Rick June 18th, 2011 @ 11:39 AM

    • Milestone changed from 0.7 to 0.8
  • David Seifried

    David Seifried August 26th, 2011 @ 04:41 PM

    • Milestone changed from 0.8 to 0.9
  • cadecairos

    cadecairos September 15th, 2011 @ 02:17 PM

    What's the status of this ticket? The cut-off date for tickets is this coming Tuesday so if this makes any changes to core it needs to be in 0.9.

  • brianchirls

    brianchirls September 15th, 2011 @ 02:27 PM

    This has nothing to do with the core. It would only be done in the demos.

  • Brett Gaylor

    Brett Gaylor September 15th, 2011 @ 02:50 PM

    Is this actually a "best practice"? ie what we are talking about is documentation?

  • Rick

    Rick September 15th, 2011 @ 03:32 PM

    • Tag set to needs-docs

    +1 to both of those points.

  • David Seifried

    David Seifried September 22nd, 2011 @ 05:05 PM

    • Milestone changed from 0.9 to 1.0 Release
  • David Seifried

    David Seifried October 19th, 2011 @ 11:10 AM

    • State changed from “new” to “assigned”
  • Scott Downe

    Scott Downe October 26th, 2011 @ 01:34 PM

    I actually don't think this is as bad of an issue as it used to be.

    We do all our loading inside setup now, so only loads if it has a track of that type.

    Also, any fancy timed loaded code, imo, is up to the plugin developer to use a base practices guide to control loading. Using execs, setup, or earlier if they so wish.

    I vote to wont-fix this.

  • brianchirls

    brianchirls October 26th, 2011 @ 01:36 PM

    Sounds good. Maybe merge this into best practices.

    Just a reminder, this has nothing to do with the core, just that the examples we put out there should reflect best practices.

  • Scott Downe

    Scott Downe October 28th, 2011 @ 01:32 PM

    • Assigned user changed from “Bobby Richter” to “David Seifried”

    The best practices ticket #706 has a link to this one. I will pass this on to Dave then.

  • David Seifried
  • David Seifried

    David Seifried October 30th, 2011 @ 08:07 PM

    • State changed from “assigned” to “blocked”
  • David Seifried
  • brianchirls

    brianchirls November 1st, 2011 @ 05:10 PM

    Excellent. What do you guys think about getting the best practices stuff implemented in the packaged plugins and examples for 1.1?

  • David Seifried

    David Seifried November 2nd, 2011 @ 03:20 PM

    • Assigned user cleared.
    • State changed from “blocked” to “resolved”

    Hey Brian,

    Any core plugins that we are shipping should probably implement the best practices stuff, so I like the idea of doing this in 1.1

    As for now, marking this as resolved, the docs are up online now.

Please Sign in or create a free account to add a new ticket.

With your very own profile, you can contribute to projects, track your activity, watch tickets, receive and update tickets through your email and much more.

New-ticket Create new ticket

Create your profile

Help contribute to this project by taking a few moments to create your personal profile. Create your profile »

Popcorn.js is an HTML5 video framework that lets you bring elements of the web into your videos.

Popcorn.js is a project of Web Made Movies, Mozilla's Open Video Lab.

Shared Ticket Bins


Referenced by