h5bp / lazyweb-requests

Get projects and ideas built by the community
https://github.com/h5bp/lazyweb-requests/issues
1.69k stars 84 forks source link

Definitive answer to: concatenate or separate with async script load? #5

Closed paulirish closed 5 years ago

paulirish commented 13 years ago

Mathias attempted to best answer this: http://mathiasbynens.be/notes/inline-vs-separate-file

In it he says:

Making an HTTP requests costs roughly 100 ms (the average TTFB I’ve seen, though it can be as low as 50 ms or 60 ms). Assuming a low powered DSL connection, [users ...] can download 10 kilobytes every 100 ms

Which seems to mostly answer it but i think we need some more data and confirmation on this figure.

also getify also has a post on this topic http://blog.getify.com/2009/11/labjs-why-not-just-concat/

christian has a test rig up here that explores this topic: http://www.der-schepp.de/http-connects/

getify commented 13 years ago

I'm currently conducting some tests to try and test this question. The tests in low-frequency runs have shown pretty definitively that parallel loading 2 files (2 equal chunks of a single 'concat' file) instead of the 1 big file does load quicker (~10-15%), even with http overhead/latency factored in, and even with other resources loading at the same time.

The test is very bandwidth intensive, so I haven't been able to take it broadscale yet, but I'm working with some places that may donate the hosting so we can take scale it up. I'll of course make the test and its results public ASAP.

paulirish commented 13 years ago

I was talking to some developers about this and noted this thing.. "the 10k rule of thumb"..

instantly that makes sense to people and they can make wise decisions about that.

so i hope we can create such a rule of thumb.. 10k.. 20k.. 5k.. or at least boil this down to something super specific with a few critical modifiers you should consider.

getify commented 13 years ago

if the number you're talking about is the number above which it makes sense to chunk into two pieces to download both chunks in parallel, then yes, I agree such a number is generally possible to get close to estimating, and is important to find. That is explicitly what I'm trying to find with my test series.

I think it's definitely not 5k or down near that end of the line. The tests I'm running at the moment are testing 100k (before gzip), either all together in one file or chunked into two 50k files.

SlexAxton commented 13 years ago

I was talking with Yehuda Katz about this subject as well, and he brought up a great point about how it's likely very different for mobile. Should we turn off our crazy loaders for mobile websites/apps, or are there different best practices?

diegotres-zz commented 13 years ago

I think use a concatenate file with the largest frameworks like jquery + jqueryui and the rest to load async way. What you about the use of packages? Like the requirejs do.

jAndreas commented 13 years ago

Best results for script loading on mobile devices I get with a multipart XHR loader. That is, streaming any number of files over one xhr request. This technique requires a little backend script aswell as some javascript magic, but it's stunningly fast. This combined with localStorage caching is called supplyJS.

ZeeAgency commented 13 years ago

LABjs is often use as an alternative for <script> but another useful use of LABjs I have is to conditionally load some libs only when needed, later in the code.

For instance, we're using JWPlayer JS API on some projects and, for people who may not know, it can play <video> when supported, or create and play with <object> including their Flash player. I'm not a huge fan of their API (my company bought it before I was hired) and even if I'm not looking at the quality of the code, it weights 80 freaking KB (23KB gzipped).

Mobile devices (and modern browsers) doesn't need this...

So... I wrote 2 abstraction classes (<600B each gzipped), one for HTML5, one for JWPlayer, forgetting its fallback feature, each of them sharing the same simple API so I can talk to them the same way (and more like the HTML5 way than the JWPlayer way...). Thanks to Modernizr (which I always use on every projects) I can easily detect if <video> (and mp4...) is supported or not and thanks to LABjs I can load only one of my abstraction class (and JWPlayer JS API if needed), all of this after DOM ready and parallellized. Plus, on my current project, videos are not always present/used on every pages, including the homepage. So (that's the ugly part) I'm checking $('video').length before doing anything useless, when I'm not triggering this load with a $('a.video-preview').click() or something.

Which makes me bounce to the "architecture" topic : imo, a good web app architecture should include a smart way (smarter then $('#are-you').there() ? ) to tell which part of the app is useful or not, urgently or not, we need to prioritize features. UI events (View Controllers) for instance could hardly be load dynamically or should be the first on the queue because when the user see his fast-loaded page and impatiently wants to interact with it, we can't garantee if his actions are listened (the use of the hashchange event is not always possible or desired).

About the original topic : concatenate or async. Of course : both. Except the weight problem, it's a feature question. As I said, some can wait, some can't. For the last ones, I use to concatenate and compile everyone in an all.js file, for the first ones I'm doing (by hand, not yet an ant addict) some compiled packages which I load on demand or deferred. I like the deferred approach because it's caching useful files for the next pages the user would probably request after the homepage. LABjs is also great for that.

Back to LABjs, I miss a feature and I'll probably make a fork of LABjs to fit this lack one day : loading something else than scripts, like images and templates. I really think LABjs needs extensions to become some kind of "universal" loader.

Images : the LABjs's syntax is great and cleaner than a new Image, image.load blablabla... definitely when we need a callback after more than one image load. Very useful with big images we don't want to show rendering live to the user (from top to bottom, you know?) but only when they're fully loaded so it appears decently. I had the need last week with a fade animation as a callback to a big background loading (fallback : Modernizr & html.no-js)

Templates : I'm using an implementation of Resig's micro-templates but instead of putting my templates in some <script type="text/html"> I'm using external files, imho it's cleaner, people can work on it without opening something like index.html and when all the work is done I'm storing every templates once compiled in one JS file (so eval() won't be used after that).

Is there some people with the same needs and already got solutions for this or would like one ?

Schepp commented 13 years ago

Hi guys,

I already wrote something about this yesterday but then I decided to sleep one night and check back on this today (it was already very late). Today I updated my test in order to check other factors and so that you peeps can play around with it. Coming to my results, I would now settle on the following findings:

A) 1 x JS + 1 x CSS is always the slowest configuration (except legacy IEs and probably IE8/9 in VPN/SSL mode) B) Splitting up into more than 2 x JS + 2 x CSS doesn't improve the results across all browsers. Some improve, some degrade. So that may be the sweet spot.

mathiasbynens commented 12 years ago

@Schepp What size were those files?

Schepp commented 12 years ago

I don't rememeber exactly but I guess I used my default presets. That is 100.000 bytes for JS and CSS each + 10 pictures with 10.000 Bytes each. Those numbers are located near the szenario of a small website.

But play around yourself: http://www.der-schepp.de/http-connects/

stale[bot] commented 5 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

stale[bot] commented 5 years ago

This issue has been automatically closed because it has not had recent activity. Thank you for your contributions.