- From: Getify <getify@gmail.com>
- Date: Tue, 12 Oct 2010 10:57:51 -0500
- To: "public html" <public-html@w3.org>
>> I fully expect LABjs to UA sniff past browsers. My point is that, ideally, for future browsers LABjs should be able to capability sniff so that a LABjs update isn't needed every time an additional browser implements the spec. And more to the point, a situation where a JS library used by many sites needs to be updated in order for an additional browser to implement the spec is a way to make it less likely that browsers implement the spec. Yes, I agree with this as being the best option. I just want to guard against further complicating the (already complicated) issue by implementing a set of new attributes/features because the train has already left the station on the `async` feature (FF 3.6). It's a difficult situation to balance, but I'm kind of leaning toward it being the better of two evils to rely on the more simple approach (piggybacking on `async`) and dealing with the necessity of browser inferences for awhile longer. Yes, sites will need to keep their LABjs up to date, but that's far less impactful to overall page behavior than say asking them to keep jQuery up to date (with whom lots more potentially breaking changes go into each release). Since LABjs is so small and highly focused, I think the risk to sites keeping it up to date is minimized compared to jQuery. Also, as far as I can see, all that LABjs needs to do is "sniff" for browsers that currently have `async` but who don't yet have the ordered behavior if its value is `false`. AFAIK, this is only FF3.6 (and FF4 betas/nightlies), right? Maybe I'm wrong on that, but I think inferences/sniffing should be able to just identify these specific browsers and correct for that. I would hope that if we standardize the proposed `async=false` ordered behavior on injected scripts quickly, then any new browsers implementing `async` for the first time would do so fully and not partially. I know this is obviously quite optimistic, but it seems like the reasonable behavior to at least push the browsers for. "Don't implement `async` until you do it fully and correctly." But even if some browser doesn't (which is quite possible), the only challenge then is for LABjs to update to sniff for that new browser and correct. Certainly not ideal, but I think it's possible and manageable (at least I hope so). I'm just thinking that's a better short-term fix (with short-term pain for longer-term bliss) than a more complicated feature set that noone has implemented yet. But I can definitely see how the argument may go either way on it. >> So if IE and WebKit stayed on the old script/cache code path even if they >> made script-inserted external scripts without the async attribute execute >> in insertion order, what carrot would you be giving IE and WebKit to >> motivate them to change (other than that it would be the Right Thing to >> implement the spec)? I understand that IE/Webkit might need a carrot to agree to implement behavior they haven't implemented before. But I don't think that constructing a use-case (or engineering for it) where their old way loses out is the right way to entice them. I'm new to this standards body and to the process in general, but I feel like both Webkit and Microsoft (with IE9) are showing they clearly want to be in line with standards, so the high board approach of convincing based on merits of the standard is how I'd default to approaching the discussion. I *definitely* think it will take some community pressure and advocacy to make it happen. And to be clear, obviously I'm not asking that the "as-soon-as-possible" script execution be removed... in some use cases, that's much better than the ordered execution. We're only discussing that the additional ordered behavior should be straightforwardly possible, and I'm further asserting that it's the more common use case than the non-ordered. FWIW, there *is* a negative side-effect of IE/Webkit/Chrome forcing this use case to be solved with the hackish "script/cache" behavior. The side-effect is that the trick is completely ineffective (and in fact, quite detrimental) if the script being loaded has improper cache headers, because it results in a double-load (since the first preload didn't cache) *and* it also fails the assumption of immediate execution from cache as the second load must make the full asynchronous (non-ordered) round-trip again. So, in other words, the trick completely fails and breaks if proper cache headers aren't sent. While we'd like to think that proper cache headers are a given, they certainly are not completely ubiquitous on the broader web. This is actually why LABjs only uses this trick as a last resort for preloading remote scripts (which can't be XHR'd like local scripts) -- because the assumption is there's more risk with the trick, but that if you're loading remotely, you're more likely to be loading from a CDN where (hopefully) caching headers are more likely to be correctly configured. So, if anything, *this* could be the carrot (although indirect) to use with IE/Webkit/Chrome -- you are forcing a sub-optimal trick for this use case which not only complicates LABjs (and thus slows down its usage), but which also has non-trivial risk if used against scripts that aren't served with proper headers. >> We could just as easily say that feature-test for `async` (and >> specifically >> its default value, either true or false) is the feature-test for >> ordered vs. >> non-ordered behavior. > > I hadn't considered this. I guess I was specifically thinking that the default value being added to the feature-test might help distinguish it. I think currently in all `async` implementations, the default is `false`. But if we say that in order-preserving implementations, the default value is true for injected scripts (which fits your preference for defaults anyway), then the feature test can be not only for the presence of the `async` but also for its default value to be 'true', which would differentiate it from current `async` implementations. >> Why would that be the performance-savvy default? It seems to me IE/WebKit >> behavior is more performance-savvy when there are at least two >> non-interacting scripts being downloaded in parallel (e.g. a site >> functionality script and an advertising script). Here's my perspective on why I claim that ordered execution of parallel scripts is the performance-savvy way. I realize it's sort of counter-intuitive and I should have explained myself better before. "facts" (observations): 1. There are far more sites on the web which currently use scripts with dependencies on each other (right or wrong) than on sites who load multiple scripts which have no dependencies. 2. In the majority of these sites, they are using manual script tags in their HTML markup, which as I've explained in another email comment to this thread (to Ian) has some significant performance disadvantages. 3. When those sites become aware of the potential savings that dynamic parallel loading will provide, they naturally are willing to make the change, as long as that change doesn't require significant refactoring of their own scripts, and especially of remote scripts they don't control. 4. As they make the switch to dynamic script loading (not using a smart loader like LABjs), they quickly realize that the beneficial behavior in FF/Opera of keeping the order makes their job a lot easier than the non-ordering behavior of IE/Webkit/Chrome. 5. As such, they then implement a script loader to try and help smooth out those difficult quirks. LABjs is small (so is RequireJS et al), but it's still less than optimal given that it has extra cruft in it to handle all these hacky tricks like "preloading". 6. Their conclusion (and mine)? For sites who need ordering (which are more common that those who care nothing about ordering), the ordered behavior (whether default or opt-in) is much more friendly to simple performance optimizations than is the non-ordered behavior (which significantly complicates things). For the browsers which provide no easy opt-in and instead force these ugly hacks for ordering, we are trading back some of the performance benefits (in the form of script loader complexity and also use-case risk side effects) we otherwise would have had if the standard ordered behavior from FF/Opera were *possible* everywhere (which would let LABjs be a lot simpler!) >> Now you are talking about a different thing: Script-inserted inline >> script maintaining insertion order relative to script-inserted external >> scripts. When I assert the previous behavior of FF/Opera as being desirable, I *only* mean the ordered part of injected *external* scripts. I have no care or feeling about the actual motivating behavior problem where the ordering had effects on injected inline scripts. I *only* am asserting behavior regarding injected external scripts. >> I'm trying to find a solution that satisfies the constraints placed by >> existing jQuery and the constraints placed by existing LABjs. AFAICT, the >> jQuery constraint is about how script-inserted inline scripts execute >> relative to script-inserted external scripts but the LABjs constraint is >> about how script-inserted external scripts execute relative to each >> other. Thus, it seems to me that it's possible to satisfy both >> constraints at the same time. (By making script-inserted inline scripts >> not maintain order relative to script-inserted external scripts and >> making script-inserted external scripts with async=false maintain order >> among themselves.) Yes I agree that the two behaviors are *not* mutually exclusive and both use cases can reasonably be supported. I think the original change you did (based on spec, no doubt) had the unintended side effect, which is why we're now discussing ways to separate the issue so that both can be served. >> Maybe they aren't enjoying better performance in the case where a library >> like LABjs emulates in-order execution. However, they might be enjoying >> better performance in other (potentially more common) cases. I don't have >> measurement data, but on the face if things, it seems reasonable to >> assume IE and WebKit at least aren't putting themselves at a performance >> disadvantage when the execution order doesn't matter. I explained above, but again... yes, there *is* a use-case for dynamic loading (with performance optimization in mind) where you don't care about order. And IE/Webkit/Safari serve that use-case well, and probably on purpose. But this other use-case, where scripts are loaded that have dependencies, just seems pretty obvious to me as the more common use case. If you survey just the sites that use jQuery on the web, it's heavily common that those sites are loading jQuery separately from whatever page-code (or plugins) uses jQuery. Obviously, those sites aren't necessarily all wide-spread doing dynamic loading for performance (yet), but once they do, there will be millions of sites caught in this use-case we're discussing, and for *them*, IE/Webkit/Chrome will clearly be serving the non-majority use-case with only a barely workable hacky fallback for the more common use case. This has to be (in my mind) the reasoning/"carrot" for how to convince IE/Webkit/Chrome to make a change to support ordered behavior, however we decide that should be opted into (or out of). > I disagree. I think the old Gecko behavior had three characteristics that > deviated from the current spec draft, so the old Gecko behavior shouldn't > be considered as one either-or thing. I think two of those characteristics > were clearly undesirable and the third is potentially desirable. As I said above, I completely agree with the assertion that injected external scripts should not have *any* other behavioral side-effects or dependencies on anything else (including injected inline scripts, parser-inserted scripts, etc)... EXCEPT each other (if necessary). I don't know the underlying code in the browser, but I know conceptually I consider injected external scripts to be a completely separate topic, and when I as an author inject them (using LABjs or otherwise), I want for them to be completely unpinned from anything else in the page (except each other). > There's no chance that such a feature would be supported cross-origin > without CORS, because it would cause cross-origin information leaks that > aren't already present and unremovable for compatibility. I actually didn't intend to suggest that external templating loading needed to support remote (CORS) type behavior. The cross-domain security issues are well documented, and none of what I've suggested for the templating use-case should imply that I was intending that behavior to work cross-domain. I just meant that loading a template from an external (local-domain) file helps performance by letting templates be independently cacheable. The cross-domain issue is an entirely different beast that I didn't mean to invoke. >> I'm entirely unconvinced that maintaining execution order between >> script-inserted external scripts and parser-inserted scripts (so that the >> script-inserted script goes first and the parser-inserted script blocks) >> needs to be available at all. >> I'm also doubting the necessity of having the option to make >> script-inserted inline scripts maintain order relative to script-inserted >> external scripts, even though I suggested it as part of my .ordered >> proposal, since if we had an explicit opt-in, providing this option would >> be easy. However, if we aren't doing .ordered, I'm not convinced we need >> to provide this option, since if a Web app wants to eval some text in the >> global scope after loading a set of external scripts, it can do so off >> the onload handler of the last one of those external scripts. The only >> case where value would be added is the case where the order is external, >> inline, external (all script-inserted that is). Seems a bit too special >> to me to support parallel download of the two externals here. Addressed above. I am not arguing for injected external scripts to have any effect on, or dependency on, injected inline scripts OR parser-injected scripts of any kind. --Kyle
Received on Tuesday, 12 October 2010 15:58:27 UTC