Re: [whatwg] Script preloading
On 8/27/13 2:55 PM, Ian Hickson i...@hixie.ch wrote: First, let's get down to use cases. Kyle did a great job of describing some key use cases: On Wed, 10 Jul 2013, Kyle Simpson wrote: [Use-case Q:] I am dynamically loading one of those social widgets that, upon load, automatically scans a page and renders social buttons. I need to be able to preload that script so it's ready to execute, but decide when I want it to run against the page. I don't want to wait for true on-demand loading, like when my user clicks a button, because of the loading delay that will be visible to the user, so I want to pre-load that script and have it waiting, ready at a moment's notice to say it's ok to execute, do it now! now! now!. [Use-case S:] One CMS plugin wants to load A.js and B.js, where B relies on A. Both need to load in parallel (for performance), but A must execute before B executes. I don't control A and B, so changing them is not an option. This CMS plugin [wants] to wait for some user-interaction, such as a button click, before executing the code. We don't want there to be any big network-loading delay visible to the user between their click of the button and the running of that plugin's code. Another CMS plugin on this same page wants to load A.js, C.js, and D.js. This plugin doesn't know or care that the other plugin also requests A.js. It doesn't know if there is a script element in the page requesting it or not, and it doesn't want to looking for it. It just wants to ask for A as a pre-requisite to C and D. But C and D have no dependency on each other, only a shared dependency on A. C and D should be free to run ASAP (in whichever order), assuming that A has already run [once] some user-interaction that initiates the load of A, C, and D. This user interaction may be before the other plugin requested A, or after it requested A. A.js can be requested relatively (via a base tag or just relative to document root) or absolutely, or it might be requested with the leading-// protocol-relative from, taking on whatever http or https protocol the page has, whereas other references to it may specify the prototcol. These plugins can't guarantee what ID's or classes they use are reliably unique without undue processing burden. [I've trimmed the text Kyle wrote here, but also implicit in his description, as I understood it, was that A.js should only run once even if both plugins tried to load it.] [Use-case T:] I have two different calendar widgets. I want to pop one of them up when a user clicks a button. The user may never click the button, in which case I don't want the calendar widget to have ever executed to render. [...] It'd be nice if both calendar widgets were built sensibly so that loading the code didn't automatically render. One of them IS, the other is unfortunately mis-behaving, and it will render itself as soon as its code is run. [...] Furthermore, these two widgets are not equal. Perhaps one is better for smaller browser window sizes, and the other is better for larger browser windows. [...] Regardless, the point is, there's run-time conditions which are going to determine if I want to execute calendar widget A or B, or maybe I never execute either. But I want them both preloaded and ready to go, just in case, so that if the user DOES need one, it's free and ready to execute with nearly no delay, instead of having to wait to request as I would with only on-demand techniques. [Use-case U:] I have a set of script A.js, B.js, and C.js. B relies on A, and C relies on B. So they need to execute strictly in that order. [Now], imagine they progressively render different parts of a widget. [...] I only want to execute A, B and C once all 3 are preloaded and ready to go. It's [...] about minimizing delays between them, for performance PERCEPTION. [For example, one of them might start playing a video, and another might introduce the canvas slides for that video. You want all of the relevant scripts to be run at once, so there's no point where the page has a video element but doesn't have the canvas.] On Thu, 11 Jul 2013, Kyle Simpson wrote: [Use-case V:] you have a string of scripts (A.js, B.js, and C.js) loading which constitute a dependency chain. A must run before B, which must run before C. However, if you detect an error in loading, you stop the rest of the executions (and preferably loading too!), since clearly dependencies will fail for further scripts, and the errors will just unnecessarily clutter the developer console log making it harder to debug. [Use-case W:] some developers have even requested to be able to stop the chain and prevent further executions if the script loads, but there's some compile-time syntax error or run-time error that happens during the execution. For them, it's not enough for B to simply finish loading successfully, but that it must fully execute without error. On Sun, 14
Re: [whatwg] Script preloading
On 31 August 2013 00:04, Ryosuke Niwa rn...@apple.com wrote: It'll be much harder to implement a new dependency API that replies on CSS selectors if we care about the performance at all. Where does the performance issue come from? It would only need to be resolved once on node creation or insertion into the document (the latter of the two). It's only used for execution, downloads can still be triggered without resolving the selectors (eg, by a pre-scanner).
Re: [whatwg] Script preloading
On 9/3/13 2:27 PM, Ryosuke Niwa wrote: From the fact selector matching is slow. Hold on. Back up. Selector matching can't be all that slow per se: browsers do it a _lot_. Do you mean doing the equivalent of document.querySelectorAll can be slow? -Boris
Re: [whatwg] Script preloading
Original proposal: http://lists.whatwg.org/pipermail/whatwg-whatwg.org/2013-August/040664.html http://lists.whatwg.org/pipermail/whatwg-whatwg.org/2013-August/040666.html In order to address use cases incDependencies and decDependencies satisfied, I'm going to add the following proposals: I make one more change that in order for a dependency specified in needs to be satisfied, src content attribute of the dependent script needs to match the value when the script finished running. e.g. myscript.src = null leaves any dependency on myscript unsatisfied. Also make needs IDL property take in any HTML element; e.g. adding an image element to needs makes the script wait until the corresponding image resource is loaded. On Aug 27, 2013, at 2:55 PM, Ian Hickson i...@hixie.ch wrote: First, let's get down to use cases. Kyle did a great job of describing some key use cases: On Wed, 10 Jul 2013, Kyle Simpson wrote: [Use-case Q:] I am dynamically loading one of those social widgets that, upon load, automatically scans a page and renders social buttons. I need to be able to preload that script so it's ready to execute, but decide when I want it to run against the page. I don't want to wait for true on-demand loading, like when my user clicks a button, because of the loading delay that will be visible to the user, so I want to pre-load that script and have it waiting, ready at a moment's notice to say it's ok to execute, do it now! now! now!. script id=social src=social-button.js prefetch/script button onmouseover=document.scripts.social.execute() ... /button [Use-case S:] One CMS plugin wants to load A.js and B.js, where B relies on A. Both need to load in parallel (for performance), but A must execute before B executes. I don't control A and B, so changing them is not an option. This CMS plugin [wants] to wait for some user-interaction, such as a button click, before executing the code. We don't want there to be any big network-loading delay visible to the user between their click of the button and the running of that plugin's code. // CMS plugin 1 var A = E('script', { src: 'A.js', prefetch: true }); var B = E('script', { src: 'B.js', needs: 'A.js', prefetch: true }); document.body.append(A, B); function sawUserInteraction() { B.execute(); }; Another CMS plugin on this same page wants to load A.js, C.js, and D.js. This plugin doesn't know or care that the other plugin also requests A.js. It doesn't know if there is a script element in the page requesting it or not, and it doesn't want to looking for it. It just wants to ask for A as a pre-requisite to C and D. But C and D have no dependency on each other, only a shared dependency on A. C and D should be free to run ASAP (in whichever order), assuming that A has already run [once] some user-interaction that initiates the load of A, C, and D. This user interaction may be before the other plugin requested A, or after it requested A. // CMS plugin 2 var A = E('script', { src: 'A.js', prefetch: true }); var C = E('script', { src: 'C.js', needs: 'A.js', prefetch: true }); var D = E('script', { src: 'D.js', needs: 'A.js', prefetch: true }); document.body.append(A, C, D); function sawUserInteraction() { C.execute(); D.execute(); }; A.js can be requested relatively (via a base tag or just relative to document root) or absolutely, or it might be requested with the leading-// protocol-relative from, taking on whatever http or https protocol the page has, whereas other references to it may specify the prototcol. These plugins can't guarantee what ID's or classes they use are reliably unique without undue processing burden. [I've trimmed the text Kyle wrote here, but also implicit in his description, as I understood it, was that A.js should only run once even if both plugins tried to load it.] [Use-case T:] I have two different calendar widgets. I want to pop one of them up when a user clicks a button. The user may never click the button, in which case I don't want the calendar widget to have ever executed to render. [...] script id=calA src=a.js prefetch/script script id=calB src=b.js prefetch/script script function showCalendar(which) { if (which == 'a') document.scripts.calA.execute(); else document.scripts.calB.execute(); } /script Neither Ian's nor my proposal fallbacks gracefully here :( [Use-case U:] I have a set of script A.js, B.js, and C.js. B relies on A, and C relies on B. So they need to execute strictly in that order. [Now], imagine they progressively render different parts of a widget. [...] I only want to execute A, B and C once all 3 are preloaded and ready to go. It's [...] about minimizing delays between them, for performance PERCEPTION. [For example, one of them might start playing a video, and another might introduce the canvas slides for that video. You want all of the relevant scripts to be run at once, so there's no
Re: [whatwg] Script preloading
On Sep 3, 2013, at 3:45 AM, Jake Archibald jaffathec...@gmail.com wrote: On 31 August 2013 00:04, Ryosuke Niwa rn...@apple.com wrote: It'll be much harder to implement a new dependency API that replies on CSS selectors if we care about the performance at all. Where does the performance issue come from? It would only need to be resolved once on node creation or insertion into the document (the latter of the two). It's only used for execution, downloads can still be triggered without resolving the selectors (eg, by a pre-scanner). From the fact selector matching is slow. I'm opposed to adding selector dependency unless there is a very important use case that can't be addressed by referring to a script by an element id or a script filename. - R. Niwa
Re: [whatwg] Script preloading
Per IRC discussion, I misunderstood the timing at which these at which dependencies are executed. Now I agree it's desirable to have two values for when needed as proposed by Ian in the original e-mail. For other people following this thread's sake, a.js will execute immediately as soon as it's loaded in this example: script src=a.js whenneeded/script script id=b src=b.js needs=a.js whendeeded/script // later document.scripts.b.execute(); whereas a.js doesn't get executed until b.js is loaded in this example: script src=a.js whenneeded=jit/script script id=b src=b.js needs=a.js whendeeded/script // later document.scripts.b.execute(); - R. Niwa On Sep 3, 2013, at 2:49 PM, Ryosuke Niwa rn...@apple.com wrote: Original proposal: http://lists.whatwg.org/pipermail/whatwg-whatwg.org/2013-August/040664.html http://lists.whatwg.org/pipermail/whatwg-whatwg.org/2013-August/040666.html In order to address use cases incDependencies and decDependencies satisfied, I'm going to add the following proposals: I make one more change that in order for a dependency specified in needs to be satisfied, src content attribute of the dependent script needs to match the value when the script finished running. e.g. myscript.src = null leaves any dependency on myscript unsatisfied. Also make needs IDL property take in any HTML element; e.g. adding an image element to needs makes the script wait until the corresponding image resource is loaded. On Aug 27, 2013, at 2:55 PM, Ian Hickson i...@hixie.ch wrote: First, let's get down to use cases. Kyle did a great job of describing some key use cases: On Wed, 10 Jul 2013, Kyle Simpson wrote: [Use-case Q:] I am dynamically loading one of those social widgets that, upon load, automatically scans a page and renders social buttons. I need to be able to preload that script so it's ready to execute, but decide when I want it to run against the page. I don't want to wait for true on-demand loading, like when my user clicks a button, because of the loading delay that will be visible to the user, so I want to pre-load that script and have it waiting, ready at a moment's notice to say it's ok to execute, do it now! now! now!. script id=social src=social-button.js prefetch/script button onmouseover=document.scripts.social.execute() ... /button [Use-case S:] One CMS plugin wants to load A.js and B.js, where B relies on A. Both need to load in parallel (for performance), but A must execute before B executes. I don't control A and B, so changing them is not an option. This CMS plugin [wants] to wait for some user-interaction, such as a button click, before executing the code. We don't want there to be any big network-loading delay visible to the user between their click of the button and the running of that plugin's code. // CMS plugin 1 var A = E('script', { src: 'A.js', prefetch: true }); var B = E('script', { src: 'B.js', needs: 'A.js', prefetch: true }); document.body.append(A, B); function sawUserInteraction() { B.execute(); }; Another CMS plugin on this same page wants to load A.js, C.js, and D.js. This plugin doesn't know or care that the other plugin also requests A.js. It doesn't know if there is a script element in the page requesting it or not, and it doesn't want to looking for it. It just wants to ask for A as a pre-requisite to C and D. But C and D have no dependency on each other, only a shared dependency on A. C and D should be free to run ASAP (in whichever order), assuming that A has already run [once] some user-interaction that initiates the load of A, C, and D. This user interaction may be before the other plugin requested A, or after it requested A. // CMS plugin 2 var A = E('script', { src: 'A.js', prefetch: true }); var C = E('script', { src: 'C.js', needs: 'A.js', prefetch: true }); var D = E('script', { src: 'D.js', needs: 'A.js', prefetch: true }); document.body.append(A, C, D); function sawUserInteraction() { C.execute(); D.execute(); }; A.js can be requested relatively (via a base tag or just relative to document root) or absolutely, or it might be requested with the leading-// protocol-relative from, taking on whatever http or https protocol the page has, whereas other references to it may specify the prototcol. These plugins can't guarantee what ID's or classes they use are reliably unique without undue processing burden. [I've trimmed the text Kyle wrote here, but also implicit in his description, as I understood it, was that A.js should only run once even if both plugins tried to load it.] [Use-case T:] I have two different calendar widgets. I want to pop one of them up when a user clicks a button. The user may never click the button, in which case I don't want the calendar widget to have ever executed to render. [...] script id=calA src=a.js prefetch/script script id=calB src=b.js prefetch/script script
Re: [whatwg] Script preloading
Hello folks. Sorry for the late response to several comments in this mega-thread, I've mostly been traveling/vacationing for the past 2 months. A teammate asked me to look at this in case I had comments. I don't know web dev issues very well, so I'm going to restrain myself from offering many opinions about the new proposals other than wow, all this dependency stuff looks complicated, but maybe it's worth it? I'll keep to some observations from a networking performance perspective, in case it's relevant to the discussion: * Any advantages the preloader currently gives is probably only going to be magnified with HTTP/2. Browsers today will in key situations hold back lower priority resource loads, even after the resource has been discovered by the parser/preloader, in order to reduce network contention and prioritize resources. But with HTTP/2, the browser almost never has to do this since it can express the request priority in the HTTP/2 protocol itself, and let the server order responses appropriately. * link rel=subresource is great for resource discovery. Given the above observation, note that it has some deficiencies. Most obviously, it does not indicate the resource type. Browsers today can heuristically assign a priority based on the resource type (script/image/stylesheet/etc). Arguably, browsers could just use the filename extension as a hint to the resource type, and that'd get us most of the way there. In any case, Chromium, when it encounters link rel=subresource is going to assign the resource load the lowest priority level, and only when the parser encounters the actual resource via a script tag or something, will another resource load be issued with the appropriate priority. Almost all modern browsers will hold back low priority resource loads before first paint in order to get critical scripts and stylesheets in head ASAP without contention. Anything marked with link rel=subresource will be considered low priority and in all likelihood not requested early. Note that HTTP/2 currently does not support re-prioritization (and that feature is being debated), so that means that when the resource load for link rel=subresource gets issued over an HTTP/2 connection, it will have the lowest priority, which is probably undesirable. FWIW, I think link rel=subresource was a good initial start, but suffers from key weaknesses and should be thrown out and replaced. * Given current browser heuristics for resource prioritization based on resource type, all script resources will have the same priority. Within HTTP/1.X, that means you'll get some amount of parallelization based on the connection per host limit and what origins the script resources are hosted, and then get FIFO. New additions like lazyload attributes (and perhaps leveraging the defer attribute) may affect this. With HTTP/2, there is a very high (effectively infinite) parallelization limit. With prioritization, there's no contention across priority levels. But since script resources today generally all have the same priority, they will all contend and most naive servers are going to round robin the response bytes, which is the worst thing you could do with script resources, since current JS VMs do not incrementally process script resources, but process them as a whole. So round-robining all the response bytes will just push out start time of JS processing for all scripts, which is rather terrible. * Obviously, given what I've said above, some level of hinting of prioritization/dependency amongst scripts/resources within the web platform would be useful to the networking layer since the networking layer can much more effectively prioritize resources and thus mitigate network contention. If finer grained priority/dependency information isn't provided in the web platform, my browser's networking stack is likely going to have to, even with HTTP/2, do HTTP/1.X style contention mitigation by restricting parallelization within a priority level. Which is a shame since web developers probably think that with HTTP/2, they can have as many fine grained resources as they want. Cheers. On Wed, Jul 10, 2013 at 3:39 AM, Ian Hickson i...@hixie.ch wrote: A topic that regularly comes up is script loading. I sent an e-mail responding to related feedback last year, though it didn't get any replies to the script loading parts of it: http://lists.w3.org/Archives/Public/public-whatwg-archive/2012Dec/0221.html It seems that people want something that: - Lets them download scripts but not execute them until needed. - Lets them have multiple interdependent scripts and have the browser manage their ordering. - Do all this without having to modify existing scripts. I must admit to not really understanding these requirements (script execution can be made more or less free if they are designed to just expose some functions, for example, and it's trivial to set up a script dependency mechanism for scripts to run each other in order, and there's
Re: [whatwg] Script preloading
On Tue, Aug 27, 2013 at 11:55 PM, Ian Hickson i...@hixie.ch wrote: On Thu, 11 Jul 2013, Yoav Weiss wrote: I've recently contemplated the slightly related issue of adding the media attribute to script, for declarative loading of scripts that are only relevant to some viewports [1] While it may complicate certain things (e.g. execution when media conditions change, dependencies), I believe it's worth while to give it some thought, as it'd enable preloaders to fetch these scripts as soon as possible, in case they are needed. How common are media-specific scripts? They are fairly common, especially for loading of mobile UI components (e.g. jquery mobile). They can also be used to download dynamic page components (e.g. maps) only on larger devices. But, unless adding `media` to script elements is relatively simple, I think that this use-case can be resolved by using the media attribute on rel subresource, in combination with ES6 modules or a custom script loader. As far as I understand it, all link elements can have a media attribute [1], so this is simply an implementation issue. [1] http://www.whatwg.org/specs/web-apps/current-work/multipage/semantics.html#the-link-element
Re: [whatwg] Script preloading
On Aug 30, 2013, at 9:08 AM, Yoav Weiss y...@yoav.ws wrote: On Tue, Aug 27, 2013 at 11:55 PM, Ian Hickson i...@hixie.ch wrote: On Thu, 11 Jul 2013, Yoav Weiss wrote: I've recently contemplated the slightly related issue of adding the media attribute to script, for declarative loading of scripts that are only relevant to some viewports [1] While it may complicate certain things (e.g. execution when media conditions change, dependencies), I believe it's worth while to give it some thought, as it'd enable preloaders to fetch these scripts as soon as possible, in case they are needed. How common are media-specific scripts? They are fairly common, especially for loading of mobile UI components (e.g. jquery mobile). They can also be used to download dynamic page components (e.g. maps) only on larger devices. But, unless adding `media` to script elements is relatively simple, I think that this use-case can be resolved by using the media attribute on rel subresource, in combination with ES6 modules or a custom script loader. As far as I understand it, all link elements can have a media attribute [1], so this is simply an implementation issue. I don't think it'll be hard to add the media attribute on the script element at least in WebKit. It'll be much harder to implement a new dependency API that replies on CSS selectors if we care about the performance at all. - R. Niwa
Re: [whatwg] Script preloading
On 8/30/13, Ryosuke Niwa rn...@apple.com wrote: On Aug 30, 2013, at 9:08 AM, Yoav Weiss y...@yoav.ws wrote: On Tue, Aug 27, 2013 at 11:55 PM, Ian Hickson i...@hixie.ch wrote: On Thu, 11 Jul 2013, Yoav Weiss wrote: [...] They are fairly common, especially for loading of mobile UI components (e.g. jquery mobile). They can also be used to download dynamic page components (e.g. maps) only on larger devices. But, unless adding `media` to script elements is relatively simple, I think that this use-case can be resolved by using the media attribute on rel subresource, in combination with ES6 modules or a custom script loader. As far as I understand it, all link elements can have a media attribute [1], so this is simply an implementation issue. I don't think it'll be hard to add the media attribute on the script element at least in WebKit. It'll be much harder to implement a new dependency API that replies on CSS selectors if we care about the performance at all. What is this in response to? What dependency API that relies on CSS selectors? (I'm assuming you mean relies and not replies, but still not sure what you mean). -- Garrett Twitter: @xkit personx.tumblr.com
Re: [whatwg] Script preloading
On Aug 30, 2013, at 4:36 PM, Garrett Smith dhtmlkitc...@gmail.com wrote: On 8/30/13, Ryosuke Niwa rn...@apple.com wrote: I don't think it'll be hard to add the media attribute on the script element at least in WebKit. It'll be much harder to implement a new dependency API that replies on CSS selectors if we care about the performance at all. What is this in response to? What dependency API that relies on CSS selectors? (I'm assuming you mean relies and not replies, but still not sure what you mean). Sorry, I meant to say relies. I was referring to the Jake's version of the dependency resolution mechanism as seen below: On Aug 29, 2013, at 9:42 AM, Jake Archibald jaffathec...@gmail.com wrote: I'm not sure it's possible to get into loops with this. I imagined dependency resolution to happen once, on element creation or adding to document (whichever happens latest). So with: script src=a.js needs=script[src=b.js]/script script src=b.js needs=script[src=a.js]/script …the first script would have zero dependencies, because the selector matches zero elements. The second would depend on the first, so the execution order is a.js, b.js. The thing I like about the selector thing is you can very easily get (almost) async=false behaviour: Going back to Ian's proposal. On Aug 27, 2013, at 2:55 PM, Ian Hickson i...@hixie.ch wrote: Here's a proposal that attempts to address all the use cases: High-level overview: script elements get a new whenneeded= attribute, which delays the execution of the script until the script element's execute() method is called. (This essentially provides the same as the preload suggestions.) script elements also get a new needs= attribute, which takes a list of URLs. A script won't run (even if you call execute()) until all the script src= elements referenced by its needs= attribute are themselves ready to run. For example: script src=b.js needs=a.js/script script src=a.js async/script ...will execute a.js when it's ready, and only then execute b.js. needs basically implies async if its needs aren't met when it first tries to run. script whenneeded=jit is a special mode where instead of running once the script's dependencies are met, it additionally waits until all the scripts that depend on _it_ are ready to run. (Just in time exection.) (The default is whenneeded=asap, as soon as possible exection.) You can manually increase or decrease a dependency count on script elements by calling incDependencies() and decDependencies(). Details (tersely): scripts have a whenneeded mode, initially none, can also be asap, jit. I don't quite understand why we need two values for whenneded. Why can't we simply have prefetch (since we already use that term in the link element) and needs (I'd prefer calling it requires) content attributes? When a script element has the prefetch attribute, it doesn't execute until execute() is called upon the element unless (i.e. the script is executed immediately when the script has been loaded) if at least one of its dependencies is not a prefetch (i.e. doesn't have the prefetch content attribute). Could you clarify which use case this alternative proposal doesn't address? script gets a method, execute(): 0. mark as needed 0. call execute() on each script we depend on 0. if we didn't depend on any, check if we need to run script gets a pair of methods, incDependencies() and decDependencies(), that increase and decrease the dependency count by one, respectively decDependencies() throws if called when the count is zero. If decDependencies() is called and it reduces the number to zero, I strongly oppose to adding incDependencies/decDependencies. We try not to add those pairwise functions as much as possible our C++ code because it's really hard to always pair function calls. - R. Niwa
Re: [whatwg] Script preloading
I don't like the name jit, because it already has a different meaning when talking about scripting. If this was for CSS or WebVTT or something else other than scripts, it wouldn't be as bad... On Fri, Aug 30, 2013 at 7:22 PM, Ryosuke Niwa rn...@apple.com wrote: I don't quite understand why we need two values for whenneded. Why can't we simply have prefetch (since we already use that term in the link element) and needs (I'd prefer calling it requires) content attributes? When a script element has the prefetch attribute, it doesn't execute until execute() is called upon the element unless (i.e. the script is executed immediately when the script has been loaded) if at least one of its dependencies is not a prefetch (i.e. doesn't have the prefetch content attribute). I'm not sure what you mean (skipping the parenthetical this says unless if, so I'm not sure how to parse that), but prefetch sounds like something different than jit. prefetch sounds like a hint about networking behavior, eg. download this script, even if it isn't needed yet. On the other hand, jit changes when the script is executed, not when it's downloaded: it means don't execute the script's contents until the scripts that depend on this one are also ready to be downloaded. Could you clarify which use case this alternative proposal doesn't address? The use case was download several scripts, then execute them all at once. I'm not sure about that use case, but a prefetch hint doesn't seem right for that. You'd end up downloading the scripts even if they're never used. With jit, the browser can still avoid downloading the scripts entirely if they're not used. -- Glenn Maynard
Re: [whatwg] Script preloading
On Aug 30, 2013, at 5:54 PM, Glenn Maynard gl...@zewt.org wrote: I don't like the name jit, because it already has a different meaning when talking about scripting. If this was for CSS or WebVTT or something else other than scripts, it wouldn't be as bad... On Fri, Aug 30, 2013 at 7:22 PM, Ryosuke Niwa rn...@apple.com wrote: I don't quite understand why we need two values for whenneded. Why can't we simply have prefetch (since we already use that term in the link element) and needs (I'd prefer calling it requires) content attributes? When a script element has the prefetch attribute, it doesn't execute until execute() is called upon the element unless (i.e. the script is executed immediately when the script has been loaded) if at least one of its dependencies is not a prefetch (i.e. doesn't have the prefetch content attribute). I'm not sure what you mean (skipping the parenthetical this says unless if, so I'm not sure how to parse that), but prefetch sounds like something different than jit. Yes. Prefetch is like noexecute if there are no dependencies that require immediate execution. But it behaves like jit if there are dependencies. Example 1. script src=A.js prefetch/script script src=B.js requires=C.js prefetch/script script src=C.js prefetch/script Neither A.js, B.js, nor C.js are executed until execute() is called on each element. Example 2. script src=A.js prefetch/script script src=B.js requires=C.js/script script src=C.js prefetch/script Both C.js and B.js are executed respectively once they're loaded since C.js requires B.js. Example 2. script src=A.js prefetch/script script src=B.js requires=C.js/script script src=C.js requires=A.js prefetch/script A.js, C.js, B.js are executed respectively because B.js requires C.js that in turn requires A.js The use case was download several scripts, then execute them all at once. I'm not sure about that use case, but a prefetch hint doesn't seem right for that. You'd end up downloading the scripts even if they're never used. There was a use case for fetching a script without ever executing them until execute() is called. I'll argue, however, that UAs should have the option NOT to fetch such a script immediately based on the network condition, bandwidth, etc... That's why I like the name prefetch because it implies a weak requirement. Another problem I'm interested in hearing Web developer's opinion is how we can manage the priority of resource requests. e.g. scripts only used for some obscure feature on a page can be requested later; Web browser should be able to prioritize requests for the page's main assets such as the tile image, web fonts, etc... - R. Niwa
Re: [whatwg] Script preloading
On Aug 29, 2013 1:21 AM, Jonas Sicking jo...@sicking.cc wrote: Hi Ryosuke, Based on the feedback here, it doesn't sound like you are a huge fan of the original proposal in this thread. At this point, has any implementation come out in support of the proposal in this thread as a preferred solution over noexecute/execute()? The strongest support I've seen in this thread, though I very well could have missed some, is it's better than status quo. Is that the case? / Jonas On Wed, Aug 28, 2013 at 7:43 PM, Ryosuke Niwa rn...@apple.com wrote: On Jul 13, 2013, at 5:55 AM, Andy Davies dajdav...@gmail.com wrote: On 12 July 2013 01:25, Bruno Racineux br...@hexanet.net wrote: On browser preloading: There seems to an inherent conflict between 'indiscriminate' Pre-parsers/ PreloadScanner and responsive design for mobile. Responsive designs mostly implies that everything needed for a full screen desktop is provided in markup to all devices. The pre-loader is a tradeoff, it's aiming to increase network utilisation by speculatively downloading resources it can discover. Some of the resources downloaded may be not be used but with good design and mobile first approaches hopefully this number can be minimised. Even if some unused resources get downloaded how much it matter? It matters a lot when you only have GSM wireless connection, and barely loading anything at all. By starting the downloads earlier, connections will be opened sooner, and the TCP congestion window to grow sooner. Of course this has to be balanced against visitors who might be paying to download those unused bytes, and whether the unused resources are blocking something on the critical path from being downloaded (believe some preloaders can re-prioritise resources if they need them before the preloader has downloaded them) Exactly. I'd to make sure whatever API we come up gives enough flexibility for the UAs to decide whether a given resource needs to be loaded immediatley. On Jul 12, 2013, at 11:56 AM, Kyle Simpson get...@gmail.com wrote: My scope (as it always has been) put simply: I want (for all the reasons here and before) to have a silver bullet in script loading, which lets me load any number of scripts in parallel, and to the extent that is reasonable, be fully in control of what order they run in, if at all, responding to conditions AS THE SCRIPTS EXECUTE, not merely as they might have existed at the time of initial request. I want such a facility because I want to continue to have LABjs be a best-in-class fully-capable script loader that sets the standard for best-practice on-demand script loading. Because of the different network conditions and constraints various devices have, I'm wary of any solution that gives the full control over when each script is loaded. While I'm sure large corporations with lots of resources will get this right, I don't want to provide a preloading API that's hard to use for ordinary Web developers. On Jul 15, 2013, at 7:55 AM, Kornel Lesiński kor...@geekhood.net wrote: There's a very high overlap between module dependencies and script dependencies proposal. I think at very least it would be useful to define script dependencies in terms of ES6 modules, or even abandon markup solution to avoid duplicating features. ES6 modules however do not solve the performance problem. In fact they would benefit from UA having a list of all dependencies up front (otherwise file's dependencies can only be discovered after that file is loaded, which costs as many RTTs as the height of the dependency tree). So I think that eventually ES6 modules + link[rel=subresource] could be the answer. The link would expose URLs to (pre)load for performance, but modules would handle actual loading/execution for flexibility and reliability. Yes, we should definitely consider how this preloading API works with ES6 modules. On Jul 22, 2013, at 3:22 PM, Jonas Sicking jo...@sicking.cc wrote: Having the load event anytime we are done with a network request also seems beneficial. Rather than having most APIs use load whereas this would use preload. Generally speaking load means loaded and processed. The 'noexecute' flag would change what the and processed piece includes. I don't think it'll be confusing if the script had noexecute. We can even call it noautoexecute if we wanted. But I'm fine either way here. The same question and risk of confusion seems to exist with the whenneeded attribute. In general whenneeded seems very similar to noexecute, but with a little bit more stuff done automatically, for better or worse. I like the simplicity of noexecute and excute(). However, I'm a little worried that it doesn't provide any information as to how important a given script is. So Web browsers have no choice but to request all scripts immediately. I'd like to eventually provide APIs that allow
Re: [whatwg] Script preloading
When Kyle and I originally started pushing for a way to preload JavaScript many moons ago, the intent was very simple: to allow the downloading of JavaScript and execution of JavaScript to be separate. The idea being that you should be able to preload scripts that you'll need later without incurring the cost of parsing and execution at that point in time. There are many examples of people doing this, the most famous being the Gmail mobile approach of loading JavaScript in comments and then pulling that code out and eval()ing it. I still feel very strongly that this pattern is a necessary evolution of how we should be able to load scripts into web pages. I just want a flag that says don't execute this now and a method to say okay, execute this now. Allowing that flag to be set both in HTML and JavaScript is ideal. The question of dependency management is, in my mind, a separate issue and one that doesn't belong in this layer of the web platform. HTML isn't the right spot for a dependency tree to be defined for scripts (or anything else). To me, that is a problem to be solved within the ECMAScript world much the way CSS has @import available from within CSS code. I think the use cases other than the initial one (preload/execute later) are best relegated to script loaders and are very tied to a current way of thinking about loading JavaScript. I'd rather provide a simple, low-level piece of functionality that make the job of script loaders easier by providing a reliable API and then let the dependency management use cases be addressed outside of HTML. Other random thoughts: * whenneeded is a very strange name for that attribute. It doesn't really tell me anything, as opposed to preload, noexecute, or future. How do I know when it will be needed? * I like execute() as the way to run the script in question. -N On Thu, Aug 29, 2013 at 5:58 AM, Brian Kardell bkard...@gmail.com wrote: On Aug 29, 2013 1:21 AM, Jonas Sicking jo...@sicking.cc wrote: Hi Ryosuke, Based on the feedback here, it doesn't sound like you are a huge fan of the original proposal in this thread. At this point, has any implementation come out in support of the proposal in this thread as a preferred solution over noexecute/execute()? The strongest support I've seen in this thread, though I very well could have missed some, is it's better than status quo. Is that the case? / Jonas On Wed, Aug 28, 2013 at 7:43 PM, Ryosuke Niwa rn...@apple.com wrote: On Jul 13, 2013, at 5:55 AM, Andy Davies dajdav...@gmail.com wrote: On 12 July 2013 01:25, Bruno Racineux br...@hexanet.net wrote: On browser preloading: There seems to an inherent conflict between 'indiscriminate' Pre-parsers/ PreloadScanner and responsive design for mobile. Responsive designs mostly implies that everything needed for a full screen desktop is provided in markup to all devices. The pre-loader is a tradeoff, it's aiming to increase network utilisation by speculatively downloading resources it can discover. Some of the resources downloaded may be not be used but with good design and mobile first approaches hopefully this number can be minimised. Even if some unused resources get downloaded how much it matter? It matters a lot when you only have GSM wireless connection, and barely loading anything at all. By starting the downloads earlier, connections will be opened sooner, and the TCP congestion window to grow sooner. Of course this has to be balanced against visitors who might be paying to download those unused bytes, and whether the unused resources are blocking something on the critical path from being downloaded (believe some preloaders can re-prioritise resources if they need them before the preloader has downloaded them) Exactly. I'd to make sure whatever API we come up gives enough flexibility for the UAs to decide whether a given resource needs to be loaded immediatley. On Jul 12, 2013, at 11:56 AM, Kyle Simpson get...@gmail.com wrote: My scope (as it always has been) put simply: I want (for all the reasons here and before) to have a silver bullet in script loading, which lets me load any number of scripts in parallel, and to the extent that is reasonable, be fully in control of what order they run in, if at all, responding to conditions AS THE SCRIPTS EXECUTE, not merely as they might have existed at the time of initial request. I want such a facility because I want to continue to have LABjs be a best-in-class fully-capable script loader that sets the standard for best-practice on-demand script loading. Because of the different network conditions and constraints various devices have, I'm wary of any solution that gives the full control over when each script is loaded. While I'm sure large corporations with lots of resources will get this right, I don't want to provide a preloading API
Re: [whatwg] Script preloading
On 27 August 2013 22:55, Ian Hickson i...@hixie.ch wrote: On Tue, 9 Jul 2013, Bruno Racineux wrote: Why not simply load all such scripts early in the head with 'defer', which preserves the dependency order as determined by your app. Using 'defer' in head scripts is actually a very good way to preserve script order with non-blocking scripts. And by loading the scripts very early in the head, the possibility of a incurred significant delay of DOMContentLoaded, for an eventual large script not yet downloaded, is minimal to none. This doesn't seem like it handles all the use cases (e.g. T and U). Worth noting that defer is busted in IE9 and below, to the point where it's unusable https://github.com/h5bp/lazyweb-requests/issues/42 I would also strongly favor restoring the previous spec portion of 'defer' which allow to have defer on inline script blocks (i.e. if the src attribute is not present). I don't know why this html4 functionality was removed from html5? Well, primarily because basically nobody implemented it, but also, because it's not clear what the point is. Why would you need it? I like my scripts to be inert, as in have no impact on the page (like jquery). I use a small inline script to start the work needed for that page, meaning I know the starting point for all JS interacting with the page is somewhere in an inline script. This is much easier to maintain than scripts that trigger themselves ondomready depending on what they see in the DOM. I'd have liked defer (to work in IE and) to work on scripts without src. In your proposal, does this work?… script src=whatever.js whenneeded/script ... script needs=whatever.js activateTheAlmightyWebsockets(); /script On Mon, 15 Jul 2013, Kornel Lesiński wrote: ES6 modules however do not solve the performance problem. In fact they would benefit from UA having a list of all dependencies up front (otherwise file's dependencies can only be discovered after that file is loaded, which costs as many RTTs as the height of the dependency tree). So I think that eventually ES6 modules + link[rel=subresource] could be the answer. The link would expose URLs to (pre)load for performance, but modules would handle actual loading/execution for flexibility and reliability. The ES6 module doesn't address some of the use cases above, as far as I can tell (e.g. Q, U) and require a lot of work to handle some of the others. But it seems important that anything we add to HTML be designed to work with ES6 modules on the long run. There seems to be a lack of data on how modules would work in the browser. Eg, when/if they block further rendering. Or is that in the doc I'm just not getting my head around it? It'd be great if modules can solve these but also give the UA all the requirements up front (or maybe that's the job of HTTP2). On Wed, 10 Jul 2013, Jake Archibald wrote: If dependencies took a CSS selector it could be: script dependencies=.cms-core src=cmd-plugin.js/script Now the number of scripts with class cms-core can change between versions of the CMS but the plugin still waits for them all. No ID generation needed. Using a selector is an interesting idea. It makes it harder to detect and prevent loops, but not fatally so. I'm not sure it's possible to get into loops with this. I imagined dependency resolution to happen once, on element creation or adding to document (whichever happens latest). So with: script src=a.js needs=script[src=b.js]/script script src=b.js needs=script[src=a.js]/script …the first script would have zero dependencies, because the selector matches zero elements. The second would depend on the first, so the execution order is a.js, b.js. The thing I like about the selector thing is you can very easily get (almost) async=false behaviour: script src=a.js needs=script/script script src=b.js needs=script/script script src=c.js needs=script/script script elements get a new whenneeded= attribute, which delays the execution of the script until the script element's execute() method is called. (This essentially provides the same as the preload suggestions.) execute() should return a promise that resolves when the script successfully downloads and executes. Also, should there be an event on the script element when the script has downloaded, but not executed (like IE used to have)? (there's probably a better name than whenneeded, but I can't think of one right now) script elements also get a new needs= attribute, which takes a list of URLs. A script won't run (even if you call execute()) until all the script src= elements referenced by its needs= attribute are themselves ready to run. For example: script src=b.js needs=a.js/script script src=a.js async/script It seems weird to refer to needs by url, but still require script elements for those needs, I'd rather use IDs (or selectors yey!). Also, I'm not sure we need to deal
Re: [whatwg] Script preloading
On Aug 29, 2013, at 8:37 AM, Nicholas Zakas standa...@nczconsulting.com wrote: When Kyle and I originally started pushing for a way to preload JavaScript many moons ago, the intent was very simple: to allow the downloading of JavaScript and execution of JavaScript to be separate. The idea being that you should be able to preload scripts that you'll need later without incurring the cost of parsing and execution at that point in time. There are many examples of people doing this, the most famous being the Gmail mobile approach of loading JavaScript in comments and then pulling that code out and eval()ing it. I still feel very strongly that this pattern is a necessary evolution of how we should be able to load scripts into web pages. I just want a flag that says don't execute this now and a method to say okay, execute this now. Allowing that flag to be set both in HTML and JavaScript is ideal. The question of dependency management is, in my mind, a separate issue and one that doesn't belong in this layer of the web platform. HTML isn't the right spot for a dependency tree to be defined for scripts (or anything else). To me, that is a problem to be solved within the ECMAScript world much the way CSS has @import available from within CSS code. But why do you want an ability to say don't execute this now if there were no dependencies? Loading an extra script file that's not needed immediately can add few hundred of milliseconds to the total page load time over a slow network connection. To put it another way, I don't see why anyone wants to load a script and not execute it other than for the purpose of avoiding the network request at a later time. However, if that were the main purpose of providing such a functionality, then we also need to address the issue of this load request needing to have a lower priority than other load requests that are vital for the page. In fact, we might want to avoid sending the request of a script file altogether if the user isn't going to interact the parts of the page that needs such a script. - R. Niwa
Re: [whatwg] Script preloading
On Tue, Aug 27, 2013 at 4:55 PM, Ian Hickson i...@hixie.ch wrote: IMHO, if you have to write a script to solve use cases like these, you haven't really solved the use cases. It seems that the opportunity we have here is to provide a feature or set of features that addresses these use cases directly, so that anyone can use them without much work. This is especially true for a module loader, which will be used to deal with interactions between scripts written by different parties. If the platform doesn't provide a standard, universal way to do this, then people will keep rolling their own incompatible solutions. That's bearable for self-contained code used by a module, but it doesn't make sense for the piece that handles the cross-vendor interactions. Anyway, the idea of only providing basic building blocks and making people roll their own solutions isn't the web's design philosophy at all, so I don't think it's a valid objection. script whenneeded=jit is a special mode where instead of running once the script's dependencies are met, it additionally waits until all the scripts that depend on _it_ are ready to run. (Just in time exection.) (The default is whenneeded=asap, as soon as possible exection.) This mode seems to be specifically for this use case: [Use-case U:] I have a set of script A.js, B.js, and C.js. B relies on A, and C relies on B. So they need to execute strictly in that order. [Now], imagine they progressively render different parts of a widget. [...] I only want to execute A, B and C once all 3 are preloaded and ready to go. It's [...] about minimizing delays between them, for performance PERCEPTION. This one seems uncommon, and less like a dependency use case than the others. How often is this wanted? Is it too inconvenient to just mark them all @whenneeded, and say something like: document.querySelector(#C).execute(function() { A.render(); B.render(); C.render(); }); That does require the modules render in a function, and not when the script is first executed. I don't know how much of a burden that is for this case. Alternatively, if an event is fired when a script's dependencies have been met, then you could mark all three scripts @whenneeded, and call (#C).execute() once C's dependencies have been met. Maybe the jit feature isn't a big deal, but it seems like a bit of an oddball for a narrow use case. You can manually increase or decrease a dependency count on script elements by calling incDependencies() and decDependencies(). Will a @defer dependency effectively defer all scripts that depend on it? incDependencies() and decDependencies() may be hard to debug, since if somebody messes up the counter, it's hard to tell whose fault it is. A named interface could help with this: script.addDependency(thing); /* script.dependencies is now [thing] */ script.removeDependency(thing); On Thu, Aug 29, 2013 at 10:37 AM, Nicholas Zakas standa...@nczconsulting.com wrote: The question of dependency management is, in my mind, a separate issue and one that doesn't belong in this layer of the web platform. HTML isn't the right spot for a dependency tree to be defined for scripts (or anything else). To me, that is a problem to be solved within the ECMAScript world much the way CSS has @import available from within CSS code. This would serialize script loading, because you wouldn't know a script's dependencies until you've actually fetched the script. That would make page loads very slow. I think the use cases other than the initial one (preload/execute later) are best relegated to script loaders I disagree. See above. (Please remember to trim quotes.) -- Glenn Maynard
Re: [whatwg] Script preloading
On 8/29/13, Nicholas Zakas standa...@nczconsulting.com wrote: When Kyle and I originally started pushing for a way to preload JavaScript many moons ago, the intent was very simple: to allow the downloading of JavaScript and execution of JavaScript to be separate. The idea being that you should be able to preload scripts that you'll need later without incurring the cost of parsing and execution at that point in time. There are many examples of people doing this, the most famous being the Gmail mobile approach of loading JavaScript in comments and then pulling that code out and eval()ing it. Ian mentioned the idea of exporting a module, and that idea requires only a function expression to return an object. This requires the parsing of one function -- the outermost function -- which can be evaluated later. Some examples of this include the Russian Doll Pattern (Cornford) Module Pattern (Crockford), IIFE (?), and function rewriting (me). For more on this, see Kangax' article: http://kangax.github.io/nfe/ (Kangax seems to have gotten bored at conquering javascript these days). I still feel very strongly that this pattern is a necessary evolution of how we should be able to load scripts into web pages. I just want a flag that says don't execute this now and a method to say okay, execute this now. Allowing that flag to be set both in HTML and JavaScript is ideal. The question of dependency management is, in my mind, a separate issue and one that doesn't belong in this layer of the web platform. HTML isn't the right spot for a dependency tree to be defined for scripts (or anything else). To me, that is a problem to be solved within the ECMAScript world much the way CSS has @import available from within CSS code. Dependency issues include problems from having to block for scripts, document.write, fouc. Problems arising with dependency stem give rise to the need of deferring and executing scripts. The problem is that the program needs to run a script during a certain condition. And if that condition is not met, then the script resource isn't needed at all. This could useful for a situation where there are a few different components on a page, say each component requires 100k of script and 10k of CSS. But the user will probably only use one of those three components and might very well use none at all. I have worked on pages like that, with sidebars, pickers, and panels, and I wanted something like this. As Ryosuke pointed out, the idea is to declare the script in the page and then use script to determine when it should load. My previous post on building a dependency tree delves into the idea that CSS and JS can be declared to depend on stuff being loaded. That feature makes it obvious as to why they're in the source code, to the human reader. Regards, -- Garrett Twitter: @xkit personx.tumblr.com
Re: [whatwg] Script preloading
On Jul 13, 2013, at 5:55 AM, Andy Davies dajdav...@gmail.com wrote: On 12 July 2013 01:25, Bruno Racineux br...@hexanet.net wrote: On browser preloading: There seems to an inherent conflict between 'indiscriminate' Pre-parsers/ PreloadScanner and responsive design for mobile. Responsive designs mostly implies that everything needed for a full screen desktop is provided in markup to all devices. The pre-loader is a tradeoff, it's aiming to increase network utilisation by speculatively downloading resources it can discover. Some of the resources downloaded may be not be used but with good design and mobile first approaches hopefully this number can be minimised. Even if some unused resources get downloaded how much it matter? It matters a lot when you only have GSM wireless connection, and barely loading anything at all. By starting the downloads earlier, connections will be opened sooner, and the TCP congestion window to grow sooner. Of course this has to be balanced against visitors who might be paying to download those unused bytes, and whether the unused resources are blocking something on the critical path from being downloaded (believe some preloaders can re-prioritise resources if they need them before the preloader has downloaded them) Exactly. I'd to make sure whatever API we come up gives enough flexibility for the UAs to decide whether a given resource needs to be loaded immediatley. On Jul 12, 2013, at 11:56 AM, Kyle Simpson get...@gmail.com wrote: My scope (as it always has been) put simply: I want (for all the reasons here and before) to have a silver bullet in script loading, which lets me load any number of scripts in parallel, and to the extent that is reasonable, be fully in control of what order they run in, if at all, responding to conditions AS THE SCRIPTS EXECUTE, not merely as they might have existed at the time of initial request. I want such a facility because I want to continue to have LABjs be a best-in-class fully-capable script loader that sets the standard for best-practice on-demand script loading. Because of the different network conditions and constraints various devices have, I'm wary of any solution that gives the full control over when each script is loaded. While I'm sure large corporations with lots of resources will get this right, I don't want to provide a preloading API that's hard to use for ordinary Web developers. On Jul 15, 2013, at 7:55 AM, Kornel Lesiński kor...@geekhood.net wrote: There's a very high overlap between module dependencies and script dependencies proposal. I think at very least it would be useful to define script dependencies in terms of ES6 modules, or even abandon markup solution to avoid duplicating features. ES6 modules however do not solve the performance problem. In fact they would benefit from UA having a list of all dependencies up front (otherwise file's dependencies can only be discovered after that file is loaded, which costs as many RTTs as the height of the dependency tree). So I think that eventually ES6 modules + link[rel=subresource] could be the answer. The link would expose URLs to (pre)load for performance, but modules would handle actual loading/execution for flexibility and reliability. Yes, we should definitely consider how this preloading API works with ES6 modules. On Jul 22, 2013, at 3:22 PM, Jonas Sicking jo...@sicking.cc wrote: Having the load event anytime we are done with a network request also seems beneficial. Rather than having most APIs use load whereas this would use preload. Generally speaking load means loaded and processed. The 'noexecute' flag would change what the and processed piece includes. I don't think it'll be confusing if the script had noexecute. We can even call it noautoexecute if we wanted. But I'm fine either way here. The same question and risk of confusion seems to exist with the whenneeded attribute. In general whenneeded seems very similar to noexecute, but with a little bit more stuff done automatically, for better or worse. I like the simplicity of noexecute and excute(). However, I'm a little worried that it doesn't provide any information as to how important a given script is. So Web browsers have no choice but to request all scripts immediately. I'd like to eventually provide APIs that allow authors to codify which scripts are vital so that Web browsers can properly prioritize each script request. Implementation wise, noexecute/execute() will be extremely easy to implement in WebKit. I.e. something like: script src=script1.js id=s1 script src=script2.js dependencies=s1 would run correctly in downlevel browsers, but would force the scripts to be blocking. script src=script1.js id=s1 async script src=script2.js async dependencies=s1 would give you performant non-blocking behavior in downlevel browsers, but at the expense of the scripts not always running
Re: [whatwg] Script preloading
Hi Ryosuke, Based on the feedback here, it doesn't sound like you are a huge fan of the original proposal in this thread. At this point, has any implementation come out in support of the proposal in this thread as a preferred solution over noexecute/execute()? The strongest support I've seen in this thread, though I very well could have missed some, is it's better than status quo. Is that the case? / Jonas On Wed, Aug 28, 2013 at 7:43 PM, Ryosuke Niwa rn...@apple.com wrote: On Jul 13, 2013, at 5:55 AM, Andy Davies dajdav...@gmail.com wrote: On 12 July 2013 01:25, Bruno Racineux br...@hexanet.net wrote: On browser preloading: There seems to an inherent conflict between 'indiscriminate' Pre-parsers/ PreloadScanner and responsive design for mobile. Responsive designs mostly implies that everything needed for a full screen desktop is provided in markup to all devices. The pre-loader is a tradeoff, it's aiming to increase network utilisation by speculatively downloading resources it can discover. Some of the resources downloaded may be not be used but with good design and mobile first approaches hopefully this number can be minimised. Even if some unused resources get downloaded how much it matter? It matters a lot when you only have GSM wireless connection, and barely loading anything at all. By starting the downloads earlier, connections will be opened sooner, and the TCP congestion window to grow sooner. Of course this has to be balanced against visitors who might be paying to download those unused bytes, and whether the unused resources are blocking something on the critical path from being downloaded (believe some preloaders can re-prioritise resources if they need them before the preloader has downloaded them) Exactly. I'd to make sure whatever API we come up gives enough flexibility for the UAs to decide whether a given resource needs to be loaded immediatley. On Jul 12, 2013, at 11:56 AM, Kyle Simpson get...@gmail.com wrote: My scope (as it always has been) put simply: I want (for all the reasons here and before) to have a silver bullet in script loading, which lets me load any number of scripts in parallel, and to the extent that is reasonable, be fully in control of what order they run in, if at all, responding to conditions AS THE SCRIPTS EXECUTE, not merely as they might have existed at the time of initial request. I want such a facility because I want to continue to have LABjs be a best-in-class fully-capable script loader that sets the standard for best-practice on-demand script loading. Because of the different network conditions and constraints various devices have, I'm wary of any solution that gives the full control over when each script is loaded. While I'm sure large corporations with lots of resources will get this right, I don't want to provide a preloading API that's hard to use for ordinary Web developers. On Jul 15, 2013, at 7:55 AM, Kornel Lesiński kor...@geekhood.net wrote: There's a very high overlap between module dependencies and script dependencies proposal. I think at very least it would be useful to define script dependencies in terms of ES6 modules, or even abandon markup solution to avoid duplicating features. ES6 modules however do not solve the performance problem. In fact they would benefit from UA having a list of all dependencies up front (otherwise file's dependencies can only be discovered after that file is loaded, which costs as many RTTs as the height of the dependency tree). So I think that eventually ES6 modules + link[rel=subresource] could be the answer. The link would expose URLs to (pre)load for performance, but modules would handle actual loading/execution for flexibility and reliability. Yes, we should definitely consider how this preloading API works with ES6 modules. On Jul 22, 2013, at 3:22 PM, Jonas Sicking jo...@sicking.cc wrote: Having the load event anytime we are done with a network request also seems beneficial. Rather than having most APIs use load whereas this would use preload. Generally speaking load means loaded and processed. The 'noexecute' flag would change what the and processed piece includes. I don't think it'll be confusing if the script had noexecute. We can even call it noautoexecute if we wanted. But I'm fine either way here. The same question and risk of confusion seems to exist with the whenneeded attribute. In general whenneeded seems very similar to noexecute, but with a little bit more stuff done automatically, for better or worse. I like the simplicity of noexecute and excute(). However, I'm a little worried that it doesn't provide any information as to how important a given script is. So Web browsers have no choice but to request all scripts immediately. I'd like to eventually provide APIs that allow authors to codify which scripts are vital so that Web browsers can properly prioritize each
[whatwg] Script preloading
First, let's get down to use cases. Kyle did a great job of describing some key use cases: On Wed, 10 Jul 2013, Kyle Simpson wrote: [Use-case Q:] I am dynamically loading one of those social widgets that, upon load, automatically scans a page and renders social buttons. I need to be able to preload that script so it's ready to execute, but decide when I want it to run against the page. I don't want to wait for true on-demand loading, like when my user clicks a button, because of the loading delay that will be visible to the user, so I want to pre-load that script and have it waiting, ready at a moment's notice to say it's ok to execute, do it now! now! now!. [Use-case S:] One CMS plugin wants to load A.js and B.js, where B relies on A. Both need to load in parallel (for performance), but A must execute before B executes. I don't control A and B, so changing them is not an option. This CMS plugin [wants] to wait for some user-interaction, such as a button click, before executing the code. We don't want there to be any big network-loading delay visible to the user between their click of the button and the running of that plugin's code. Another CMS plugin on this same page wants to load A.js, C.js, and D.js. This plugin doesn't know or care that the other plugin also requests A.js. It doesn't know if there is a script element in the page requesting it or not, and it doesn't want to looking for it. It just wants to ask for A as a pre-requisite to C and D. But C and D have no dependency on each other, only a shared dependency on A. C and D should be free to run ASAP (in whichever order), assuming that A has already run [once] some user-interaction that initiates the load of A, C, and D. This user interaction may be before the other plugin requested A, or after it requested A. A.js can be requested relatively (via a base tag or just relative to document root) or absolutely, or it might be requested with the leading-// protocol-relative from, taking on whatever http or https protocol the page has, whereas other references to it may specify the prototcol. These plugins can't guarantee what ID's or classes they use are reliably unique without undue processing burden. [I've trimmed the text Kyle wrote here, but also implicit in his description, as I understood it, was that A.js should only run once even if both plugins tried to load it.] [Use-case T:] I have two different calendar widgets. I want to pop one of them up when a user clicks a button. The user may never click the button, in which case I don't want the calendar widget to have ever executed to render. [...] It'd be nice if both calendar widgets were built sensibly so that loading the code didn't automatically render. One of them IS, the other is unfortunately mis-behaving, and it will render itself as soon as its code is run. [...] Furthermore, these two widgets are not equal. Perhaps one is better for smaller browser window sizes, and the other is better for larger browser windows. [...] Regardless, the point is, there's run-time conditions which are going to determine if I want to execute calendar widget A or B, or maybe I never execute either. But I want them both preloaded and ready to go, just in case, so that if the user DOES need one, it's free and ready to execute with nearly no delay, instead of having to wait to request as I would with only on-demand techniques. [Use-case U:] I have a set of script A.js, B.js, and C.js. B relies on A, and C relies on B. So they need to execute strictly in that order. [Now], imagine they progressively render different parts of a widget. [...] I only want to execute A, B and C once all 3 are preloaded and ready to go. It's [...] about minimizing delays between them, for performance PERCEPTION. [For example, one of them might start playing a video, and another might introduce the canvas slides for that video. You want all of the relevant scripts to be run at once, so there's no point where the page has a video element but doesn't have the canvas.] On Thu, 11 Jul 2013, Kyle Simpson wrote: [Use-case V:] you have a string of scripts (A.js, B.js, and C.js) loading which constitute a dependency chain. A must run before B, which must run before C. However, if you detect an error in loading, you stop the rest of the executions (and preferably loading too!), since clearly dependencies will fail for further scripts, and the errors will just unnecessarily clutter the developer console log making it harder to debug. [Use-case W:] some developers have even requested to be able to stop the chain and prevent further executions if the script loads, but there's some compile-time syntax error or run-time error that happens during the execution. For them, it's not enough for B to simply finish loading successfully, but that it must fully execute without error. On Sun, 14 Jul 2013,
Re: [whatwg] Script preloading
On 18 July 2013 23:28, Kyle Simpson get...@gmail.com wrote: About a week ago, I presented a set of code comparing the script dependencies=.. approach to the script preload approach, as far as creating generalized script loaders. There were a number of concerns presented in those code snippets, and the surrounding discussions. I asked for input on the code and the issues raised. Later in the thread, I also identified issues with needing to more robustly handle error recovery and it was suggested that Navigation Controller was a good candidate for partnering with script loading for this task. I asked for some code input in that respect as well. AFAICT, the thread basically went dormant at roughly the same time. As said on Twitter (https://twitter.com/jaffathecake/status/355436953929388034) I've been on leave for a week. As you might imagine I'm riddled with emails as a result. Working through them. You will get a reply.
Re: [whatwg] Script preloading
On Tue, Jul 9, 2013 at 12:39 PM, Ian Hickson i...@hixie.ch wrote: The proposals I've seen so far for extending the spec's script preloading mechanisms fall into two categories: - provide some more control over the mechanisms already there, e.g. firing events at various times, adding attributes to make the script loading algorithm work differently, or adding methods to trigger particular parts of the algorithm under author control. - provide a layer above the current algorithm that provides strong semantics, but that doesn't have much impact on the loading algorithm itself. I'm very hesitant to do the first of these, because the algorithm is _so_ complicated that adding anything else to it is just going to result in bugs in browsers. There comes a point where an algorithm just becomes so hard to accurately test that it's a lost cause. The second seems more feasible, though. FWIW, I don't really know what functionality you put in the first category, and what you put in the second. However, as an implementor, I definitely think that the current proposal is more complicated to implement than the proposal that I pushed for before. I.e. adding a noexecute attribute on the script element which causes the script element not to execute when it normally would. Instead it fires the load event when the script has been loaded and does nothing more. Once the page wants the script to execute, it would call a new .execute() function on the script which would cause the loaded script to execute. If the function is called before the load event has fired, an InvalidStateError exception would be thrown. I could absolutely believe that this is harder to specify than your proposal. I haven't looked at the spec in enough detail to know. But it's definitely easier to implement in at least Gecko. I'd be interested to hear what other implementors think. And implementations have a higher priority than spec writing in the hierarchy of constituents. I also think it's a simpler model for authors to understand. Now, even higher priority in the hierarchy of constituents are authors. So if your proposal above is written with the goal of creating something authors prefer over the noexecute proposal, then that definitely seems like the right goal. I haven't read enough of the feedback here to get a clear picture of if the proposal in this thread is considered better than noexecute. I could definitely see that the dependencies feature could be attractive if it indeed would let authors avoid manually scheduling scripts for execution. But as always when building high-level features, there's a risk that if they don't solve the use-cases exactly, that they won't get used. / Jonas
Re: [whatwg] Script preloading
FWIW, I'd be much more in favor of Jonas' proposal, at this point, than the dependencies=.. proposal. The `noexecute/execute()` is conceptually pretty similar to the preload proposal I've been pushing. As far as I can tell from how Jonas describes it, it looks like it would fit most of the use-cases I've put forth as caring about. There's a few details to iron out, however: 1. Will it cause confusion for authors that the behavior of the `onload` event on script elements is modified from its current long-standing loaded and executed to just loaded when in the presence of the `noexecute` attribute/property? Seems like it could cause a fair bit of confusion. That's why the preload proposal proposed another event (`onpreload`), to reduce the conflation/confusion. But it might be tenable for authors. I'm sure as a script loader author I can work around it just fine if I need to. 2. What will the interaction be, if any different, with the `onerror` events? Script preloading not-withstanding, there's little cross-browser compatibility on the topic of just what exactly constitutes a script error event. Some browsers fire it for all of the common network error conditions (404, 5xx), others only some of them. In particular, if we're just building off existing mechanisms and not inventing whole new ones, it would be nice, from an author perspective, if EITHER the `onload` or the `onerror` event ALWAYS fired, and never both, and never neither, and if it was consistent when each happened. I asked a couple of years ago on this list for that exact thing to be clarified in the spec, and was told at that time that implementors were left with the discretion, which accounted for the disparity. I of course would renew my request to reverse that and land on some common spec. 3. The main reason people seem to favor the `dependencies=..` proposal or its variants is the idea of markup-only preloading, where the loading of a subsequent script tag or tags can implicitly be the signal to execute another previously loaded-and-waiting script. Not clear if/how Jonas' proposal could suit that view. Perhaps similar to how I proposed handling that desire in the preload proposal. --Kyle On Jul 22, 2013, at 4:00 PM, Jonas Sicking jo...@sicking.cc wrote: On Tue, Jul 9, 2013 at 12:39 PM, Ian Hickson i...@hixie.ch wrote: The proposals I've seen so far for extending the spec's script preloading mechanisms fall into two categories: - provide some more control over the mechanisms already there, e.g. firing events at various times, adding attributes to make the script loading algorithm work differently, or adding methods to trigger particular parts of the algorithm under author control. - provide a layer above the current algorithm that provides strong semantics, but that doesn't have much impact on the loading algorithm itself. I'm very hesitant to do the first of these, because the algorithm is _so_ complicated that adding anything else to it is just going to result in bugs in browsers. There comes a point where an algorithm just becomes so hard to accurately test that it's a lost cause. The second seems more feasible, though. FWIW, I don't really know what functionality you put in the first category, and what you put in the second. However, as an implementor, I definitely think that the current proposal is more complicated to implement than the proposal that I pushed for before. I.e. adding a noexecute attribute on the script element which causes the script element not to execute when it normally would. Instead it fires the load event when the script has been loaded and does nothing more. Once the page wants the script to execute, it would call a new .execute() function on the script which would cause the loaded script to execute. If the function is called before the load event has fired, an InvalidStateError exception would be thrown. I could absolutely believe that this is harder to specify than your proposal. I haven't looked at the spec in enough detail to know. But it's definitely easier to implement in at least Gecko. I'd be interested to hear what other implementors think. And implementations have a higher priority than spec writing in the hierarchy of constituents. I also think it's a simpler model for authors to understand. Now, even higher priority in the hierarchy of constituents are authors. So if your proposal above is written with the goal of creating something authors prefer over the noexecute proposal, then that definitely seems like the right goal. I haven't read enough of the feedback here to get a clear picture of if the proposal in this thread is considered better than noexecute. I could definitely see that the dependencies feature could be attractive if it indeed would let authors avoid manually scheduling scripts for execution. But as always when building high-level features, there's a risk that if they
Re: [whatwg] Script preloading
On Mon, Jul 22, 2013 at 2:35 PM, Kyle Simpson get...@gmail.com wrote: FWIW, I'd be much more in favor of Jonas' proposal, at this point, than the dependencies=.. proposal. The `noexecute/execute()` is conceptually pretty similar to the preload proposal I've been pushing. As far as I can tell from how Jonas describes it, it looks like it would fit most of the use-cases I've put forth as caring about. There's a few details to iron out, however: 1. Will it cause confusion for authors that the behavior of the `onload` event on script elements is modified from its current long-standing loaded and executed to just loaded when in the presence of the `noexecute` attribute/property? Seems like it could cause a fair bit of confusion. That's why the preload proposal proposed another event (`onpreload`), to reduce the conflation/confusion. But it might be tenable for authors. I'm sure as a script loader author I can work around it just fine if I need to. Do you have a link to your preload proposal? Either way, I agree about the concern with onload. I personally have a hard time telling if it'll be confusing. Having the load event anytime we are done with a network request also seems beneficial. Rather than having most APIs use load whereas this would use preload. Generally speaking load means loaded and processed. The 'noexecute' flag would change what the and processed piece includes. But I'm fine either way here. The same question and risk of confusion seems to exist with the whenneeded attribute. In general whenneeded seems very similar to noexecute, but with a little bit more stuff done automatically, for better or worse. 2. What will the interaction be, if any different, with the `onerror` events? Script preloading not-withstanding, there's little cross-browser compatibility on the topic of just what exactly constitutes a script error event. Some browsers fire it for all of the common network error conditions (404, 5xx), others only some of them. There are three opportunities to fire error stuff here: 1. Failed network request 2. Failed JS compilation 3. Exception thrown from execution And there are two error reporting mechanisms in play A. Fire an error event on the script element. B. Fire the window.onerror callback (like an event, but not exactly the same). 1 and 2 seems like they could behave exactly the same for noexecute scripts as for normal scripts. I'm not sure if that includes firing both A and B in current browsers? This would require implementations to do syntax checking (though not full compilation) of the script even before the execute() function is called. I *think* this is ok, but I'm not sure. Measurements in browsers would likely be needed. 3 presumably only triggers B currently for normal scripts? In particular, if we're just building off existing mechanisms and not inventing whole new ones, it would be nice, from an author perspective, if EITHER the `onload` or the `onerror` event ALWAYS fired, and never both, and never neither, and if it was consistent when each happened. I asked a couple of years ago on this list for that exact thing to be clarified in the spec, and was told at that time that implementors were left with the discretion, which accounted for the disparity. I of course would renew my request to reverse that and land on some common spec. Indeed. Though we're only talking about the A mechanism about, right? I.e. the following would cause both a load event to be fired on the script, and window.onerror to be triggered? script src=data:text/plain,throw new Error();/script I would definitely be in support of that. Though compatibility with existing content could be a problem. 3. The main reason people seem to favor the `dependencies=..` proposal or its variants is the idea of markup-only preloading, where the loading of a subsequent script tag or tags can implicitly be the signal to execute another previously loaded-and-waiting script. Not clear if/how Jonas' proposal could suit that view. Perhaps similar to how I proposed handling that desire in the preload proposal. Can we get a good markup-only solution while still keeping both acceptable performance as well as correct functionality in downlevel browsers? I.e. something like: script src=script1.js id=s1 script src=script2.js dependencies=s1 would run correctly in downlevel browsers, but would force the scripts to be blocking. script src=script1.js id=s1 async script src=script2.js async dependencies=s1 would give you performant non-blocking behavior in downlevel browsers, but at the expense of the scripts not always running in scripts in the right order. / Jonas --Kyle On Jul 22, 2013, at 4:00 PM, Jonas Sicking jo...@sicking.cc wrote: On Tue, Jul 9, 2013 at 12:39 PM, Ian Hickson i...@hixie.ch wrote: The proposals I've seen so far for extending the spec's script preloading mechanisms fall into two categories: - provide some more
Re: [whatwg] Script preloading
Do you have a link to your preload proposal? My main `script preload` proposal (skip the first section of this LONG email, proposal starts at Summary: several paragraphs down): http://lists.whatwg.org/htdig.cgi/whatwg-whatwg.org/2013-July/039973.html Then proposal slightly amended here: http://lists.whatwg.org/htdig.cgi/whatwg-whatwg.org/2013-July/039974.html Either way, I agree about the concern with onload. I personally have a hard time telling if it'll be confusing. Having the load event anytime we are done with a network request also seems beneficial. Rather than having most APIs use load whereas this would use preload. FWIW, I believe script loaders, at least as I envision them, would use BOTH the `onpreload` AND the `onload` events, since marking a script as ready-to-execute, however that's done, is unlikely to be a synchronouse event, so the script loader would still want to listen for when it finished running (hopefully pretty soon after being told it's OK to run!? :) I see the `onpreload` as similar in spirit to the non-standard and now-phased-out-as-of-IE11 `script.onreadystate` mechanism, which provided more detail about the status of a script as progressed from request to completion. `onpreload` just, to me, fills the spot of what semantically the word load meant, but since everyone knows load in the context of scripts means load and process/run, we can't lightly just change load. If `onpreload` seemed to imply something too far outside the normal state progression of a script, it could be called `onfinishload` or `onfinishrequest` or something like that. In the `onreadystatechange` world, they called that state loaded, FWIW. Generally speaking load means loaded and processed. The 'noexecute' flag would change what the and processed piece includes. Understood. I still think, though, that it's problematic to overload load, because as mentioned above, as a script loader, I'd want to know about both events (finished load and finished execution), not just a binary switch between one or the other. If load fired twice, that seems (potentially) awfully confusing. If load fired early (at load finish), and there was no more event for finished execution, script loaders would be quite hampered (at least as I envision architecting one) because they couldn't know if a script had really run yet or not, only that they asked it to be eligible to run. There are three opportunities to fire error stuff here: 1. Failed network request 2. Failed JS compilation 3. Exception thrown from execution And there are two error reporting mechanisms in play A. Fire an error event on the script element. B. Fire the window.onerror callback (like an event, but not exactly the same). Agreed. `window.onerror` serves fine case #3. What we don't seem to have as consistent cross-browser behavior, or even terribly well defined in the spec, is #1 and #2, especially #1. Various older browsers had different interpretations as to which network conditions constituted load complete or not. Obviously, the 200 (and several other 2xx's) should be success. And I'd think it would be obvious that any of the 4xx and 5xx codes were error. But perhaps it should just be: did the network request result in a non-empty payload? Now, for #2, to my non-implementor eye, that seems pretty well definable too. But again, cross-browser mayhem was bad with this. IIRC, Opera fired the onerror in the case of bad compilation, but none of the others did. Or maybe it was vice versa. Been awhile since I looked specifically. Just for sure recall inconsistency here. 1 and 2 seems like they could behave exactly the same for noexecute scripts as for normal scripts. Yes, as long as all the spec makes it clear what the do's and don'ts here are, and everyone complies. :) I'm not sure if that includes firing both A and B in current browsers? They do not seem to fire `window.onerror` in either #1 or #2 IIRC, but they do in #3. If I could have it my way, I'd have all three errors firing on the script.onerror, and not involve window.onerror. The reason is because `window.onerror` is notoriously hijacked by various RUM libraries and such, to do remote logging of errors, so a script loader attaching to window.onerror and catch is not terribly reliable in my experience. But I'm fine with whatever combination gives reliable and non-overlapping and non-gaping error handling coverage. :) 3 presumably only triggers B currently for normal scripts? AFAICT, yes. Indeed. Though we're only talking about the A mechanism about, right? Correct. Although in an ideal world (for me), B would be more reliable, as noted above. I.e. the following would cause both a load event to be fired on the script, and window.onerror to be triggered? script src=data:text/plain,throw new Error();/script Sure. Though as noted, script loaders may have limited utility of window.onerror when they run
Re: [whatwg] Script preloading
On Mon, Jul 22, 2013 at 4:01 PM, Kyle Simpson get...@gmail.com wrote: Do you have a link to your preload proposal? My main `script preload` proposal (skip the first section of this LONG email, proposal starts at Summary: several paragraphs down): http://lists.whatwg.org/htdig.cgi/whatwg-whatwg.org/2013-July/039973.html Then proposal slightly amended here: http://lists.whatwg.org/htdig.cgi/whatwg-whatwg.org/2013-July/039974.html Either way, I agree about the concern with onload. I personally have a hard time telling if it'll be confusing. Having the load event anytime we are done with a network request also seems beneficial. Rather than having most APIs use load whereas this would use preload. FWIW, I believe script loaders, at least as I envision them, would use BOTH the `onpreload` AND the `onload` events, since marking a script as ready-to-execute, however that's done, is unlikely to be a synchronouse event, so the script loader would still want to listen for when it finished running (hopefully pretty soon after being told it's OK to run!? :) In the noexecute proposal I believe that .execute() would be a synchronous operation. Though we could change it to be an asynchronous operation if that's desired. In which case I agree that we need some sort of notification once the script has run. There are three opportunities to fire error stuff here: 1. Failed network request 2. Failed JS compilation 3. Exception thrown from execution And there are two error reporting mechanisms in play A. Fire an error event on the script element. B. Fire the window.onerror callback (like an event, but not exactly the same). Agreed. `window.onerror` serves fine case #3. What we don't seem to have as consistent cross-browser behavior, or even terribly well defined in the spec, is #1 and #2, especially #1. Various older browsers had different interpretations as to which network conditions constituted load complete or not. Obviously, the 200 (and several other 2xx's) should be success. And I'd think it would be obvious that any of the 4xx and 5xx codes were error. But perhaps it should just be: did the network request result in a non-empty payload? Now, for #2, to my non-implementor eye, that seems pretty well definable too. But again, cross-browser mayhem was bad with this. IIRC, Opera fired the onerror in the case of bad compilation, but none of the others did. Or maybe it was vice versa. Been awhile since I looked specifically. Just for sure recall inconsistency here. Given that compatibility with existing content is the main issue here. I think finding out where different UAs are consistent, and where they are not is the first step here. I'm not sure if that includes firing both A and B in current browsers? They do not seem to fire `window.onerror` in either #1 or #2 IIRC, but they do in #3. If I could have it my way, I'd have all three errors firing on the script.onerror, and not involve window.onerror. The reason is because `window.onerror` is notoriously hijacked by various RUM libraries and such, to do remote logging of errors, so a script loader attaching to window.onerror and catch is not terribly reliable in my experience. Well, a script loader shouldn't really care about #3, should it? At that point the script loader has fulfilled its responsibility. Having #1 and #2 cause A to happen, and #3 cause B to happen, then I think that's a pretty good state of affairs. Indeed. Though we're only talking about the A mechanism about, right? Correct. Although in an ideal world (for me), B would be more reliable, as noted above. I thought the above asked for A to be more reliable? Also, more reliable probably is in the eye of the beholder. So rather than talking about what's more reliable and less reliable it's better to talk about specific behaviors. I.e. the following would cause both a load event to be fired on the script, and window.onerror to be triggered? script src=data:text/plain,throw new Error();/script Sure. Though as noted, script loaders may have limited utility of window.onerror when they run in unfamiliar/hostile pages which already hijack that error. Ideally they can always call window.addEventListener(error, ...), but apparently that doesn't always work. Not sure what specs say though. / Jonas
Re: [whatwg] Script preloading
About a week ago, I presented a set of code comparing the script dependencies=.. approach to the script preload approach, as far as creating generalized script loaders. There were a number of concerns presented in those code snippets, and the surrounding discussions. I asked for input on the code and the issues raised. Later in the thread, I also identified issues with needing to more robustly handle error recovery and it was suggested that Navigation Controller was a good candidate for partnering with script loading for this task. I asked for some code input in that respect as well. AFAICT, the thread basically went dormant at roughly the same time. I'm sure people are busy with plenty of other things, so I'm not trying to be annoying or impatient. But I would certainly like for the thread not to die, but to instead make productive progress. If you have any feedback on the code comparisons I posted earlier (https://gist.github.com/getify/5976429) please do feel free to share. Thanks! --Kyle
Re: [whatwg] Script preloading: Browser Pre-compiled Scripts Cache?
Taking about executing script as quickly as possible (threads from 1012 which I missed and tried to glanced through just get better educated about previous conversations). Wouldn't browsers be able to store pre-parsed/compiled' scripts in a separate byte code cache, with scripts promoted to the sticky cache based on their access frequency (up to cache expiration)? Say similarly to the way Fusion Drives or Seagate Adaptive Memory SSHDs work. i.e. Why do we have to keep re-parsing and re-evaluating the very same scripts, especially CDN libraries and social apis largely shared among websites, over and over? If javascript can't be as truly fast a native apps: http://sealedabstract.com/rants/why-mobile-web-apps-are-slow/ It seems that for frequently visited sites and frequently accessed libraries across websites, the whole parse/evaluation time, could be cut 'partially', yet very significantly, just like opcode does for php. And make CDN libraries even more useful and relevant that way. Or is this wildly nuts? In which case no need to answer. Bruno From: Andy Davies dajdav...@gmail.com Date: Saturday, July 13, 2013 5:55 AM To: Bruno Racineux br...@hexanet.net, WHATWG List wha...@whatwg.org Subject: Re: [whatwg] Script preloading On 12 July 2013 01:25, Bruno Racineux br...@hexanet.net wrote: On browser preloading: There seems to an inherent conflict between 'indiscriminate' Pre-parsers/ PreloadScanner and responsive design for mobile. Responsive designs mostly implies that everything needed for a full screen desktop is provided in markup to all devices. The pre-loader is a tradeoff, it's aiming to increase network utilisation by speculatively downloading resources it can discover. Some of the resources downloaded may be not be used but with good design and mobile first approaches hopefully this number can be minimised. Even if some unused resources get downloaded how much it matter? By starting the downloads earlier, connections will be opened sooner, and the TCP congestion window to grow sooner. Of course this has to be balanced against visitors who might be paying to download those unused bytes, and whether the unused resources are blocking something on the critical path from being downloaded (believe some preloaders can re-prioritise resources if they need them before the preloader has downloaded them) Although we talk about *the preloader*, it's worth remembering different browsers (and versions) have different preloading approaches - compare the connection view charts (at bottom of page) for www.channel4.com http://www.channel4.com in Chrome, Firefox and IE10 and you'll see subtle differences: Chrome http://www.webpagetest.org/result/130713_0J_PC1/1/details/ Firefox http://www.webpagetest.org/result/130713_P2_PBZ/1/details/ IE10 http://www.webpagetest.org/result/130713_9A_PBW/1/details/ Isn't the Pre-parsers/PreloadScanner's inability to take into account the display[none:yes] factor be a potential significant blow to 'mobile' performance. Use case: What if I have a set of images in an element set as display:none; only designated to be show on desktop or tablet screens and not on mobile phone? What if I have an inline script in that node? Isn't the PreloadScanner loading a lot more than I need, a problem here? Challenge with this approach is the browser has to build the render tree before it can decide whether to download a resource i.e. download HTML, parse it, build a DOM, download CSS, parse it, build CSSOM, then build render tree. In addition to the need to preload, with responsive design taken into consideration, and for lack of not being able to remove part of the body before the browser parses the document. I see an increasing potential need for the ability to indicate to the browser not to load selective assets before DOMReady and suppress such preload. The proposed lazyload attribute should help here https://dvcs.w3.org/hg/webperf/raw-file/tip/specs/ResourcePriorities/Overview. html Yoav Weiss has raised the idea of being able to use media queries with scripts and other resources too. Responsive design is young, I think we still have a lot to learn and it's going to take a while before we really understand what features we need. Cheers Andy
Re: [whatwg] Script preloading: Browser Pre-compiled Scripts Cache?
On Mon, Jul 15, 2013 at 9:42 AM, Bruno Racineux br...@hexanet.net wrote: Taking about executing script as quickly as possible (threads from 1012 which I missed and tried to glanced through just get better educated about previous conversations). Wouldn't browsers be able to store pre-parsed/compiled' scripts in a separate byte code cache, with scripts promoted to the sticky cache based on their access frequency (up to cache expiration)? Say similarly to the way Fusion Drives or Seagate Adaptive Memory SSHDs work. i.e. Why do we have to keep re-parsing and re-evaluating the very same scripts, especially CDN libraries and social apis largely shared among websites, over and over? I've raised some similar concerns and made a possibly unrealistic proposal to resolve them at the Extensible Web mailing list[1] I believe some form of JS code installation so that it can be used across sites would provide a major performance boost, if it can be done in a secure way, without throwing URLs under the bus. It will enable users to avoid re-downloading frameworks and polyfills again and again for each site they visit, and will also enable browsers to optimize these frameworks' generated machine code. [1] http://lists.w3.org/Archives/Public/public-nextweb/2013Jun/0050.html
Re: [whatwg] Script preloading: Browser Pre-compiled Scripts Cache?
On 7/15/13 3:42 AM, Bruno Racineux wrote: Wouldn't browsers be able to store pre-parsed/compiled' scripts in a separate byte code cache, You mean like https://bugzilla.mozilla.org/show_bug.cgi?id=679942 ? There's some discussion in there about whether this is a worthwhile optimization with modern JS engines, which feature lazy compilation and even lazy parsing to a large extent Measurement is needed of the various pieces discussed in https://bugzilla.mozilla.org/show_bug.cgi?id=679942#c6 and https://bugzilla.mozilla.org/show_bug.cgi?id=679942#c7. In either case, note that there is already caching of this sort to some extent in SpiderMonkey; see https://bugzilla.mozilla.org/show_bug.cgi?id=883154 which is fixed. Note that in the context of that bug a script is what you probably think of as a function body: that's the fundamental unit of compilation in SpiderMonkey now that we do lazy compilation. i.e. Why do we have to keep re-parsing and re-evaluating the very same scripts, especially CDN libraries and social apis largely shared among websites, over and over? The re-evaluating is because evaluation has little things like side-effects. ;) the whole parse/evaluation time, could be cut 'partially', yet very significantly Some hard data would be useful here, as I said above. -Boris
Re: [whatwg] Script preloading, ES6 modules
ES6 modules[1] have a script loader API[2]. That API is pretty powerful to the point it can emulate other script loaders, load files that are not ES6 modules, and even load text files that aren't JS (intended for compilation of coffeescript-like languages, but could be abused for anything): https://gist.github.com/wycats/51c96e3adcdb3a68cbc3#using-existing-libraries-as-modules There's a very high overlap between module dependencies and script dependencies proposal. I think at very least it would be useful to define script dependencies in terms of ES6 modules, or even abandon markup solution to avoid duplicating features. ES6 modules however do not solve the performance problem. In fact they would benefit from UA having a list of all dependencies up front (otherwise file's dependencies can only be discovered after that file is loaded, which costs as many RTTs as the height of the dependency tree). So I think that eventually ES6 modules + link[rel=subresource] could be the answer. The link would expose URLs to (pre)load for performance, but modules would handle actual loading/execution for flexibility and reliability. -- regards, Kornel [1] http://wiki.ecmascript.org/doku.php?id=harmony:modules [2] http://wiki.ecmascript.org/doku.php?id=harmony:module_loaders
Re: [whatwg] Script preloading: Browser Pre-compiled Scripts Cache?
On 7/15/13 6:12 AM, Yoav Weiss y...@yoav.ws wrote: On Mon, Jul 15, 2013 at 9:42 AM, Bruno Racineux br...@hexanet.net wrote: Taking about executing script as quickly as possible (threads from 1012 which I missed and tried to glanced through just get better educated about previous conversations). Wouldn't browsers be able to store pre-parsed/compiled' scripts in a separate byte code cache, with scripts promoted to the sticky cache based on their access frequency (up to cache expiration)? Say similarly to the way Fusion Drives or Seagate Adaptive Memory SSHDs work. i.e. Why do we have to keep re-parsing and re-evaluating the very same scripts, especially CDN libraries and social apis largely shared among websites, over and over? I've raised some similar concerns and made a possibly unrealistic proposal to resolve them at the Extensible Web mailing list[1] I believe some form of JS code installation so that it can be used across sites would provide a major performance boost, if it can be done in a secure way, without throwing URLs under the bus. It will enable users to avoid re-downloading frameworks and polyfills again and again for each site they visit, and will also enable browsers to optimize these frameworks' generated machine code. [1] http://lists.w3.org/Archives/Public/public-nextweb/2013Jun/0050.html It goes beyond frameworks if based on pure 'access frequency'. For example, a site backend you use daily or you favorite web app would be also benefit. Including the G+, Twitter and Facebook site's scripts, Map APIs, Google News, or whatever you access most frequently from your machine. And I am not thinking 'installation' or 'packages' in the sense that you expressed. That was my early thinking too, but say Google providing jQuery and all the hosted APIs preloaded in Chrome seems too difficult to handle, due to versioning aspects as well as limited scope. To be truly worth, it needs to be broad, based on access frequency by urls. Browsers already have a way to tell what your top sites are. Doing it for scripts doesn't seem too far fetched from there. And top sites can be used as additional priority factors.
Re: [whatwg] Script preloading: Browser Pre-compiled Scripts Cache?
It goes beyond frameworks if based on pure 'access frequency'. For example, a site backend you use daily or you favorite web app would be also benefit. Including the G+, Twitter and Facebook site's scripts, Map APIs, Google News, or whatever you access most frequently from your machine. For scripts that are always delivered through a single URL, no standard change is needed in order to make this optimization happen. As Boris pointed out, this is already done in Firefox [1] And I am not thinking 'installation' or 'packages' in the sense that you expressed. That was my early thinking too, but say Google providing jQuery and all the hosted APIs preloaded in Chrome seems too difficult to handle, due to versioning aspects as well as limited scope. To be truly worth, it needs to be broad, based on access frequency by urls. Unfortunately, for framework caching, using only URLs for caching purposes have proven to be insufficient, resulting in very little code reuse across sites, because of multiple CDNS and versioning [2] [1] https://bugzilla.mozilla.org/show_bug.cgi?id=883154 [2] http://statichtml.com/2011/google-ajax-libraries-caching.html
Re: [whatwg] Script preloading: Browser Pre-compiled Scripts Cache?
On 7/15/13 3:02 PM, Yoav Weiss y...@yoav.ws wrote: It goes beyond frameworks if based on pure 'access frequency'. For example, a site backend you use daily or you favorite web app would be also benefit. Including the G+, Twitter and Facebook site's scripts, Map APIs, Google News, or whatever you access most frequently from your machine. For scripts that are always delivered through a single URL, no standard change is needed in order to make this optimization happen. As Boris pointed out, this is already done in Firefox [1] Nods, I think I get what Boris said for the most part, reading the links afterwards. And I am not thinking 'installation' or 'packages' in the sense that you expressed. That was my early thinking too, but say Google providing jQuery and all the hosted APIs preloaded in Chrome seems too difficult to handle, due to versioning aspects as well as limited scope. To be truly worth, it needs to be broad, based on access frequency by urls. Unfortunately, for framework caching, using only URLs for caching purposes have proven to be insufficient, resulting in very little code reuse across sites, because of multiple CDNS and versioning [2] Well just to be clear, my suggested approach rely on URL 'access frequency' beyond browser sessions, and beyond libraries. i.e. The compiled cache only gets recycled for frequently accessed scripts. If the most frequently accessed scripts turn out to be jquery 1.8.2 and 1.10.2 and 2.0.3, then all three are cached of even 10 versions is that's the case. Then possibly put to disk on browser shutdown and back to memory on start. And say reserve a sticky cache of up to XMB of ram for those. They oviously have to be re-cached as per given cache expiration. But in that it doesn't really care about a particular library, it's popularity or even it's code. It's code agnostics and mostly concerned that the script you access every day are pre-compiled and never re-downloaded until cache expiry. That's the idea. [1] https://bugzilla.mozilla.org/show_bug.cgi?id=883154 The outline there suggest: - When compiling a lazy script with no inner functions, do a table lookup for a script with the same source location (filename, lineno, column, source begin/end I am no going that far with the overhead. My suggestion is to be only interested in the unique URL hash (not line no, column, or source begin/end). Just how many times that script has been accessed in the last day, week or month. Perhaps I am wrongly thinking of whole scripts vs thinking of script as a function body like Boris suggested. I am not a browser-dev or c coder, and only relying on php opcode as limited basis for my though process... Or the fundamental unit of compilation for JS is incompatible with my approach. IDK [2] http://statichtml.com/2011/google-ajax-libraries-caching.html
Re: [whatwg] Script preloading: Browser Pre-compiled Scripts Cache?
On 7/15/13 7:28 PM, Bruno Racineux wrote: The outline there suggest: - When compiling a lazy script with no inner functions, do a table lookup for a script with the same source location (filename, lineno, column, source begin/end So just to be clear: that bug is talking about script in the sense that SpiderMonkey thinks of it, which again is either a toplevel script or a function body. The above lookup is basically an optimization: once the lookup is done the result of the lookup is a pair: script chars and compiled code. The script chars are then compared to the chars of the script that needs to be compiled, and if those match the compiled code is used. The reason for factoring in lineno and column is to minimize the number of chars compares that need to be done (recall that script here is a function body in many cases, and there are lots of those on a single line of a single file in a typical minified script). I am no going that far with the overhead. My suggestion is to be only interested in the unique URL hash (not line no, column, or source begin/end). Just how many times that script has been accessed in the last day, week or month. Sure, but then what gets done with that information? Current UAs for the most part do the following, for a whole script: 1) Do a fast tokenization pass to catch syntax errors and determine function boundaries. 2) Compile and run the toplevel parts of the script. Functions are then compiled the first time they're actually called. Turns out your typical web page includes lots of functions (mostly in libraries) that it never calls. I assume the proposal is to cache, for a given URL, not just the string for the script but also the results of the initial syntax-check pass and whatever things we compiled, right? That might be worth it, as I said, but needs careful measurement: to the extent that the storage is slow and the CPU is fast and the compiler is fast and simple (which the first-pass compiler typically tries to be) recompiling may be faster than deserializing a compiled representation. Or the fundamental unit of compilation for JS It's only the fundamental unit because of the above observation that many functions never get called. -Boris
Re: [whatwg] Script preloading, optional dependencies
On Fri, 12 Jul 2013 21:20:57 +0100, Kyle Simpson get...@gmail.com wrote: So, just to clarify, `script dependencies=…` waiting on some other script tag is ONLY waiting on that script tag loading to have some sort of positive network result, whether that be a 2xx, 3xx, 4xx, or 5xx, and it cares not whether the script in question actually loaded, nor whether it fired its `onerror` event? Do I have that correct? What should happen is an interesting question. If execution continued when dependency fails to load/parse, then later scripts could try to recover/use fallback/run with reduced functionality (e.g. if jQuery plugin for fancy animations fails to load the application can disable fancy animations and run anyway). OTOH aborting execution of the rest of the dependency chain is probably what most developers expect, and it often makes sense as most scripts without dependencies met will fail. So maybe a concept of optional dependency would be useful? e.g. error handler could signal somehow that execution should continue: script id=fancy-animations src=//flaky.cdn/js onerror=return false; / or there could be a microsyntax in dependencies: script dependencies=fancy-animations? required-stuff / or: script id=fancy-animations-cdn src=//flaky.cdn/js / script id=fancy-animations-local src=/fancy-animations-copy.js / script id=nothing / script dependencies=(fancy-animations-cdn or fancy-animations-local or nothing) required-stuff / -- regards, Kornel
Re: [whatwg] Script preloading, non-script dependencies
On Tue, 09 Jul 2013 20:39:45 +0100, Ian Hickson i...@hixie.ch wrote: Would something like this, based on proposals from a variety of people in the past, work for your needs? 1. Add a dependencies attribute to script that can point to other scripts to indicate that execution of this script should be delayed until all other scripts that are (a) earlier in the tree order and (b) identified by this attribute have executed. script id=jquery src=jquery.js async/script script id=shims src=shims.js async/script script dependencies=shims jquery src=myscript.js async/script On a basic level it's similar to JS async module definition pattern (https://github.com/amdjs/amdjs-api/wiki/AMD), which is good, but may be insufficient. require.js (AMD implementation) has useful concept of loader plugins for dependencies (https://github.com/millermedeiros/requirejs-plugins). A plugin is basically a function that is told to load a path and calls callback when it's done. It solves two problems: 1. not all dependencies are JS files, e.g. authors use plugins to load template files, JSON, images, etc. script dependencies=load_template('view.hbs') src=view.js script function load_template(url, callback) { fetch(url).then(callback); // in require.js result is directly passed to the module. } /script 2. not all dependencies are usefully satisfied immediately after their JS file is loaded, e.g. some libraries may need asynchronous initialization. In require.js it's possible to wrap initialization in a plugin that will wait until it's done, so modules dependent on it can start using initialized library right away. script id=load-library src=library.js / script dependencies=load-library function library_initialized(callback) { $library.on('ready', callback) } /script script dependencies=library_initialized() src=use-it-now.js/ Another common kind of dependency scripts have is presence of certain element in the DOM, e.g. `dropdown-menu.js` may require `nav id=menu` to be in the document _and_ have its content fully parsed before the script can run. So, could script dependencies point to non-script elements? script dependencies=menu src=dropdown-menu.js/ nav id=menu !-- script not run yet -- ul.../ul /nav !-- script run at this point -- It would be nice if the browser also deferred rendering of the element until scripts that depend on it are run to avoid Flash of Unbehaviored Content (e.g. elements listed in dependencies have display:none until scripts are run). -- regards, Kornel
Re: [whatwg] Script preloading
So maybe a concept of optional dependency would be useful? 1. not all dependencies are JS files, e.g. authors use plugins to load template files, JSON, images, etc. 2. not all dependencies are usefully satisfied immediately after their JS file is loaded, e.g. some libraries may need asynchronous initialization. These are relevant statements of other use-cases that are common. I just want to point out that my script preload proposal easily handles (via a script-based script loader, not markup-only) both of these use-case variations, no matter how deep you chase their rabbit holes. In my proposal, the script loader (or module loader, or whatever) is fully in control of when the next waiting script is told that it's eligible to execute, so it can accept any arbitrary amount of complexity into its configuration for how to decide that it's OK to proceed from A to B. For example, if, in the execution of A, A registers that it needs C, then B won't auto-run just because A finishes. If C is not a script, but is a template or stylesheet or series of images or Ajax call for some data or whatever... none of that complication affects the script preload mechanism whatsoever. It simply leaves B preloaded, paitiently waiting around until it's told that its dependencies are fulfilled, and the script loader can wait as long as it needs to until A and anything A needs (C, C*) are loaded and processed. In the script dependencies proposals and variations, we have to follow the rabbit trail of inventing micro-syntaxes or other attribute complexities to handle these markup expressions of dependency that are not as trivial/simplistic as a prior completed network connection and, if applicable, parsing and processing, as you're seeing in Kornel's two messages. * Of course, I don't share the same mindset of some here that any markup-only solution we could invent, no matter how complex or intricate or involved, is better than a script-based equivalent. * To me, markup should be able to handle the majority case(s), and minority cases (while important) should be handled in script-based loading. script preload (including the markup extension I suggested) does exactly that: it handles basic preload/dependency annotation with markup-only, and it provides the full preload-defer-execute mechanism to the script-based loader for handling *everything* else you can dream up (AND you can mix-n-match). By contrast, the prior simple statement of script dependencies=... proposal (without Kornel's extensions) handles basic preload/dependency annotation in markup-only, but then the other more complex use-cases appear to have to be filled by pulling in and weaving together other (proposed) mechanisms like Navigation Controller. I'm not saying that's a bad option, but we need to be able to compare what the script-based approach is going to look in both scenarios, and see which one is more suitable/practical/desireable. --Kyle
Re: [whatwg] Script preloading
On 7/10/13, Jake Archibald jaffathec...@gmail.com wrote: On 9 July 2013 22:31, Garrett Smith dhtmlkitc...@gmail.com wrote: On 7/9/13, Ian Hickson i...@hixie.ch wrote:script id=jquery src=jquery.js async/script script id=shims src=shims.js async/script script dependencies=shims jquery src=myscript.js async/script Why limit depends to be used by only scripts to refer only to other scripts? If you put link depends=idref on style then stylesheet evaluation could be deferred, too. I like this idea and want to start a family with it. Sorry, I didn't get that. A 'depends' attribute would work like the 'for' attribute of SCRIPT element in older versions MSIE, with a difference: if (any of) the resource(s) has a fetching algorithm associated, the event does not fire until that has successfully completed. Also, depends=[DomTokenList] could be, instead of depends=IDREF -- Garrett Twitter: @xkit personx.tumblr.com
Re: [whatwg] Script preloading
On 7/13/13 5:55 AM, Andy Davies dajdav...@gmail.com wrote: On 12 July 2013 01:25, Bruno Racineux br...@hexanet.net wrote: On browser preloading: There seems to an inherent conflict between 'indiscriminate' Pre-parsers/ PreloadScanner and responsive design for mobile. Responsive designs mostly implies that everything needed for a full screen desktop is provided in markup to all devices. The pre-loader is a tradeoff, it's aiming to increase network utilisation by speculatively downloading resources it can discover. Some of the resources downloaded may be not be used but with good design and mobile first approaches hopefully this number can be minimised. Even if some unused resources get downloaded how much it matter? By starting the downloads earlier, connections will be opened sooner, and the TCP congestion window to grow sooner. Of course this has to be balanced against visitors who might be paying to download those unused bytes, and whether the unused resources are blocking something on the critical path from being downloaded (believe some preloaders can re-prioritise resources if they need them before the preloader has downloaded them) Although we talk about *the preloader*, it's worth remembering different browsers (and versions) have different preloading approaches - compare the connection view charts (at bottom of page) for www.channel4.com in Chrome, Firefox and IE10 and you'll see subtle differences: Chrome http://www.webpagetest.org/result/130713_0J_PC1/1/details/ Firefox http://www.webpagetest.org/result/130713_P2_PBZ/1/details/ IE10 http://www.webpagetest.org/result/130713_9A_PBW/1/details/ Isn't the Pre-parsers/PreloadScanner's inability to take into account the display[none:yes] factor be a potential significant blow to 'mobile' performance. Use case: What if I have a set of images in an element set as display:none; only designated to be show on desktop or tablet screens and not on mobile phone? What if I have an inline script in that node? Isn't the PreloadScanner loading a lot more than I need, a problem here? Challenge with this approach is the browser has to build the render tree before it can decide whether to download a resource i.e. download HTML, parse it, build a DOM, download CSS, parse it, build CSSOM, then build render tree. Well the crazy idea I had in mind here, is more of a scenario like: Download and parse HEAD, my script, download BODY, parse BODY, build a DOM, let me interact with the DOM with JS first, PreloadScanner, parse CSS, build CSSOM, then build render tree... But it's javascript only and a whole new level of DOMReady approach :) In addition to the need to preload, with responsive design taken into consideration, and for lack of not being able to remove part of the body before the browser parses the document. I see an increasing potential need for the ability to indicate to the browser not to load selective assets before DOMReady and suppress such preload. The proposed lazyload attribute should help here https://dvcs.w3.org/hg/webperf/raw-file/tip/specs/ResourcePriorities/Overv iew.html Thanks for pointing that out. Interesting solution. It's actually quite on topic with this thread. Noting that the 'lazyload' proposal, which tries to do the opposite of preload, somewhat also introduces a notion of dependencies with scripts and other elements via a simple priority mechanism. That is, as per current specs: script src=jquery-plugin1.js lazyload/script script src=jquery-plugin2.js lazyload/script script src=jquery.js/script It implies that I want to load my plugins for later use, they depend on jquery which will load and execute first, and the dependent scripts do not delay the load of the document. Now it'd be interesting to see how 'lazyload' deals with async or async=false which is not fully specified. Or wether 'deferred' scripts execution precedes 'lazyload' scripts or not. It a bit unclear there. But in a sense 'lazyload' can defer a stylesheet evaluation like Garrett suggested. And 'lazyload' has implications with such 'dependency' or 'whenneeded' markup. It gets complicated. Yoav Weiss has raised the idea of being able to use media queries with scripts and other resources too. Nods, raising the idea makes sense. Responsive design is young, I think we still have a lot to learn and it's going to take a while before we really understand what features we need. Cheers Andy
Re: [whatwg] Script preloading
Nobody should be arguing about 'pet projects' or 'ignorance' here, it's really uncalled for. Characterizing strong counter arguments or strong views as 'attacks' is also unnecessary. May I remind you Alex that this thread's request for feedback started with two simple questions: Would something like this, based on proposals from a variety of people in the past, work for your needs? Is there something this doesn't handle which it would need to handle? Ian even implied not quite understanding these requirements with the proposal. As such, refusing to considerate any new requirements, or shooting down strong critics, as EYE-WATERING-LENGTH as they may be, AND/OR suggesting that Ian's early proposal is an already foolproof (completely thought through solution) seems a bit misplaced. If my English as a second language serves me well, that's not quite the initial premise of this thread and its original questions. Anyway, I just want to make additional arguments as best I can with a use-case below; in support to Kyle Simpson's apparently struggle to try and get part of his points across, along with one of his remark; and a more direct attempt to answer Ian's questions. On 7/12/13 8:31 AM, Kyle Simpson get...@gmail.com wrote: It'd be great if it just could automatically re-try or fallback to another URL. Yeah, that sounds cool. Sure, will do. Re-try or fallback is/was a first requirement for me, before even considered using a CDN for jQuery. The consideration for such ability for a reliable fallback with script.fail event is quite basic. To demonstrate than MANY people care about that. This page has been viewed over 6 times with high reputation scores: http://stackoverflow.com/questions/1014203/best-way-to-use-googles-hosted-j query-but-fall-back-to-my-hosted-library-on-go Yet, that thread offers a fallback that may not even work depending on DNS/network conditions. Most people blindly assume it will. But the fact is, it doesn't. As a minimum you are looking at a 10-30sec delay. i.e. Page considered dead! Visitor likely gone... Fallback(s) in a cloud-centric environment is moot. Right now we have nothing to prevent a page from being partially or fully down due to external js failures. Let's take this premise. I am gonna use Google's CDN because it's recommended and improve performance. And CNDJS for the shim library because it's convenient and fast. So: script id=jquery src=googleCDN/jquery.js async/script script id=shims src=CDNJS/shims.js async/script script dependencies=shims jquery src=mysite/myscript.js async/script Ok, so I rely on the browser to automatically load dependencies for me right? Use case: Either googleCDN's or CDNJS fail for whatever reason. What does the browser do? Try one more time, report me an error? Let me down with a failed load all together? My one time visitor, which I also happen to have payed Google Adwords for the click, cannot visit my site. Wasted $5 bucks? Lost a potential sale? So how does this proposal handle such situation, or better put: gives me control to determine what has loaded or wether it's going to succeed in loading at all? Is it not sufficient in this regard, and does not propose to handle fallbacks. Also using scripts id(s) have the problem of possible conflict with other elements using duplicate ids in the document, in an unpredictable fashion (unique identifier must). I.e. IDs can't be used. I actually faced that conflict myself early on... Nor can 'class', nor can 'name' (which I use but it only works when used dynamically, and not allowed officially as markup). That would leave you with 'title' or the need for a new attribute. And no easy/fast document.getElementById('myscript') possible. Overall, the ex2-getify.js's approach to address control, failures, execution, and fallback matters is a better way to deal with this, or at least simpler to comprehend for a developer at large, in my view. https://gist.github.com/getify/5976429#file-ex2-getify-js I personally wouldn't go as far as 'script.error', I think that's maybe pushing it. Although a richer script.readyState(s) type protocol could surely benefit from it. But having such states as 'waiting', 'failed', 'loading' and 'loaded' are needed when it comes to 'guaranteed' pre-loading/loading. script.onload being rather insufficient. If link[rel=subresource] is adopted and works in comprehensive way with possible states/events of its own. The need to pause execution is not necessarily a requirement here. But if it's to use a basic link[rel=subresource] and implement whenneeded/markNeeded() on top of it, both without any notion of 'waiting', 'failed', 'loading' or 'loaded', to fully accomplish one goal, it feels redundant and still missing critical components for reliability sake. I for one wouldn't really foresee myself using whenneeded/markNeeded() anyway. While existing method for delayed parsing/execution work and are supported. They are still considered a hack. And as
Re: [whatwg] Script preloading
On 12 July 2013 01:25, Bruno Racineux br...@hexanet.net wrote: On browser preloading: There seems to an inherent conflict between 'indiscriminate' Pre-parsers/ PreloadScanner and responsive design for mobile. Responsive designs mostly implies that everything needed for a full screen desktop is provided in markup to all devices. The pre-loader is a tradeoff, it's aiming to increase network utilisation by speculatively downloading resources it can discover. Some of the resources downloaded may be not be used but with good design and mobile first approaches hopefully this number can be minimised. Even if some unused resources get downloaded how much it matter? By starting the downloads earlier, connections will be opened sooner, and the TCP congestion window to grow sooner. Of course this has to be balanced against visitors who might be paying to download those unused bytes, and whether the unused resources are blocking something on the critical path from being downloaded (believe some preloaders can re-prioritise resources if they need them before the preloader has downloaded them) Although we talk about *the preloader*, it's worth remembering different browsers (and versions) have different preloading approaches - compare the connection view charts (at bottom of page) for www.channel4.com in Chrome, Firefox and IE10 and you'll see subtle differences: Chrome http://www.webpagetest.org/result/130713_0J_PC1/1/details/ Firefox http://www.webpagetest.org/result/130713_P2_PBZ/1/details/ IE10 http://www.webpagetest.org/result/130713_9A_PBW/1/details/ Isn't the Pre-parsers/PreloadScanner's inability to take into account the display[none:yes] factor be a potential significant blow to 'mobile' performance. Use case: What if I have a set of images in an element set as display:none; only designated to be show on desktop or tablet screens and not on mobile phone? What if I have an inline script in that node? Isn't the PreloadScanner loading a lot more than I need, a problem here? Challenge with this approach is the browser has to build the render tree before it can decide whether to download a resource i.e. download HTML, parse it, build a DOM, download CSS, parse it, build CSSOM, then build render tree. In addition to the need to preload, with responsive design taken into consideration, and for lack of not being able to remove part of the body before the browser parses the document. I see an increasing potential need for the ability to indicate to the browser not to load selective assets before DOMReady and suppress such preload. The proposed lazyload attribute should help here https://dvcs.w3.org/hg/webperf/raw-file/tip/specs/ResourcePriorities/Overview.html Yoav Weiss has raised the idea of being able to use media queries with scripts and other resources too. Responsive design is young, I think we still have a lot to learn and it's going to take a while before we really understand what features we need. Cheers Andy
Re: [whatwg] Script preloading
On 7/11/13 6:00 AM, Jake Archibald jaffathec...@gmail.com wrote: link rel=subresource almost 50% of scripts sent without proper caching headers. If the browser is doing what it should do, it won't cache those This is not how link[rel=subresource] should work, the first request for the subresource should pick up from where the link left off. If it doesn't do that, let's fix it, then we get the feature working properly for more than just scripts. 6. Use-case: I want to preload a script which is hosted somewhere that I don't control caching headers, and to my dismay, I discover that they are serving the script with incorrect/busted/missing caching headers. If I use a cache-preload technique, it will fail to work as I had hoped. I will pay the double-download penalty because the browser didn't actually cache it the first time, and my user will pay the extra UX penalty of having to wait longer for the second load, when my whole goal was to remove that UX visible delay. Use-case: (as above) I should be able to preload scripts served by a third party with no cache headers link[rel=subresource] has you covered and should be fixed if it isn't working. Kyle, on the caching I don't think its legit to cache a file that is not sent to be cached, as bad or involuntary as it might be from the provider. Jake, now I that I am more familiarized with link[rel=subresource] it seems to indeed solve some the preloading without executing side of things. And good for performance especially if they can be provided in the HEADER. Is there a benefit from having a 'subresource' in the HEADER with the same blocking script in the head? I am thinking jQuery and the main css for example. It seems like css and jQuery could be partially or even already available by the time /head is received. Assuming the HEADER is received and processed before the head start downloading (I am mot sure if this is the case). It'd be useful that a broader scope of link[rel=subresource] be specified, or pre-formalized. There is little documentation other than the chromium page right now, and no reference on: http://wiki.whatwg.org/wiki/RelExtensions, where it has a proposal status. A couple question I would have right about it, based on its current implementation are: Can multiple subresource(s) be specified in the HEADER? If specified in the HEADER can the Request send 'current' cookies? Does the Response of a link[rel=subresource] from the HEADER set cookies normally? One issue, I am seeing right now in Opera/Blink is that the script seem to download twice if requested with XHR. That shouldn't be.
Re: [whatwg] Script preloading
On 9 July 2013 20:39, Ian Hickson i...@hixie.ch wrote: A topic that regularly comes up is script loading. I sent an e-mail responding to related feedback last year, though it didn't get any replies to the script loading parts of it: http://lists.w3.org/Archives/Public/public-whatwg-archive/2012Dec/0221.html Pretty sure the cases I mentioned are met by the proposed lazyload attribute
Re: [whatwg] Script preloading
Ok, and I'm saying they shouldn't be asking LABjs to handle it, they should be asking the devtools teams at browser vendors to give them ways to deal with it. You're not going to be able to pause execution for code, implement future breakpoints, or debug root causes for this sort of thing well from script. You can do SOMETHING, but not with the fidelity that devtools can. I'm not sure why you keep focusing on this being a devtools centric question, because I think you're missing the point. The developers that are asking for these features from LABjs are NOT asking for the capability to debug what's going on with failed loads while testing their app in their development environment. IF what they're trying to do is diagnose and fix such failed loads while developing their app, then certainly that would squarely be a devtools type of task. LABjs also has a debug-build available, and it has certain extra tracing going on inside it when used, that aids developers in understanding, from its perspective, what is going on as things proceed through loading. That debug mode, in addition to whatever great devtools that exist or will exist, are all fantastic ways for developers to work on and fix problems. *** But all that is ENTIRELY ORTHGONAL to what the developers are actually presently asking from LABjs. *** They are asking, repeatedly, for the ability to have logic deployed in their *production* builds, which sits in front of end users which have no knowledge of or relation to any developer tools in whatever browser they use. Certainly, these developers are not interested in whether or not their end-users happen to be in a browser that has devtools, because end users don't care about devtools, and the developers who do care aren't actually using the user's browser anyway. At this point, whether or not a browser has certain devtools is entirely irrelevant to what the developer wants from LABjs. What seems to be their mindset and internal narrative is this: OK, no matter how good we are at figuring out how to build a bug-free app, we rely on third-party external resources that we don't control. We cannot guarantee that our request for 'jquery.js' from the Google CDN will actually work. It should work. It usually works. But it doesn't always work. Sometimes Google goes down. Sometimes the DNS lookup fails. Sometimes a proxy server misbehaves. Sh$$ happens. SO! We'll just accept that fact. We look at our RUM logs and we see that about 2% of our users experience one of these dead page loads. But, hey, I've got an idea, how about we try to write code into our production code which detects when something like that happens, and tries to gracefully recover, if possible, to maybe reduce the 2% down to 1%. Yeah, that's a good idea. How do we do that? Oh, I know! We're already using a script loader. Let's have that script loader tell us when `script.onerror` fires, which tells us that a script load failed (right!?!?), and we'll just re-request it from a fallback location on our own CDN. Sounds like a plan. Can you file a feature request at LABjs for them to expose when `script.onerror` fires? It'd be great if it just could automatically re-try or fallback to another URL. Yeah, that sounds cool. Sure, will do. I understand clearly at this point that you don't agree with their mindset. I understand you think their desire is misguided. I admit sometimes I am skeptical of the efficacy of such efforts. But respectfully speaking, your opinion is not the only one that matters here. Who are we to tell some in-good-faith developer that they are objectively WRONG to hope their script loader could not only LOAD scripts but RELOAD or ALTLOAD scripts. Think about the conceptual and semantic there. It's a pretty sensible expectation for most non-browser-author devs. We'll be able to do this from the Navigation Controller: https://github.com/slightlyoff/NavigationController/blob/master/explainer.md Never heard of it before. Thanks for the link. But I don't see how the idea that this may (likely) happen (someday) automatically moots the discussion at hand. For you to fairly exercise some sort of veto vote over what we discuss, which it seems like you're trying to do, you've gotta come to the table with some real tangible thing that's standardized (or clearly headed that way) and ready to evaluate for fitness to the use-cases. I glanced through (it's long, haven't digested it yet) and didn't immediately see a section called RETRYING AND FALLBACK LOADING. :) I don't see an MDN page entry for `Navigation Controller`. I can't find Navigation Controller on http://caniuse.com yet. So far, the only google result I've found for it is your writeup. So having only seen it for a few moments as of the writing of this email, and finding no other evidence about it, it's hard to judge if it's a valid alternative for the requested use-cases or not. Would you be able to make a
Re: [whatwg] Script preloading
On Fri, Jul 12, 2013 at 4:31 PM, Kyle Simpson get...@gmail.com wrote: Ok, and I'm saying they shouldn't be asking LABjs to handle it, they should be asking the devtools teams at browser vendors to give them ways to deal with it. You're not going to be able to pause execution for code, implement future breakpoints, or debug root causes for this sort of thing well from script. You can do SOMETHING, but not with the fidelity that devtools can. I'm not sure why you keep focusing on this being a devtools centric question, because I think you're missing the point. The developers that are asking for these features from LABjs are NOT asking for the capability to debug what's going on with failed loads while testing their app in their development environment. IF what they're trying to do is diagnose and fix such failed loads while developing their app, then certainly that would squarely be a devtools type of task. LABjs also has a debug-build available, and it has certain extra tracing going on inside it when used, that aids developers in understanding, from its perspective, what is going on as things proceed through loading. That debug mode, in addition to whatever great devtools that exist or will exist, are all fantastic ways for developers to work on and fix problems. *** But all that is ENTIRELY ORTHGONAL to what the developers are actually presently asking from LABjs. *** They are asking, repeatedly, for the ability to have logic deployed in their *production* builds, which sits in front of end users which have no knowledge of or relation to any developer tools in whatever browser they use. Certainly, these developers are not interested in whether or not their end-users happen to be in a browser that has devtools, because end users don't care about devtools, and the developers who do care aren't actually using the user's browser anyway. Ok, I think I understand what you're saying now. At this point, whether or not a browser has certain devtools is entirely irrelevant to what the developer wants from LABjs. What seems to be their mindset and internal narrative is this: OK, no matter how good we are at figuring out how to build a bug-free app, we rely on third-party external resources that we don't control. We cannot guarantee that our request for 'jquery.js' from the Google CDN will actually work. It should work. It usually works. But it doesn't always work. Sometimes Google goes down. Sometimes the DNS lookup fails. Sometimes a proxy server misbehaves. Sh$$ happens. SO! We'll just accept that fact. We look at our RUM logs and we see that about 2% of our users experience one of these dead page loads. But, hey, I've got an idea, how about we try to write code into our production code which detects when something like that happens, and tries to gracefully recover, if possible, to maybe reduce the 2% down to 1%. Yeah, that's a good idea. How do we do that? Oh, I know! We're already using a script loader. Let's have that script loader tell us when `script.onerror` fires, which tells us that a script load failed (right!?!?), and we'll just re-request it from a fallback location on our own CDN. Sounds like a plan. Can you file a feature request at LABjs for them to expose when `script.onerror` fires? It'd be great if it just could automatically re-try or fallback to another URL. Yeah, that sounds cool. Sure, will do. I understand clearly at this point that you don't agree with their mindset. I understand you think their desire is misguided. I admit sometimes I am skeptical of the efficacy of such efforts. It's not scepticism at that level that I'm expressing. Accepting everything you just typed out (AT EYE-WATERING-LENGTH), changes to Ian's proposal are still a poor place to attack the issue. The Navigation Controller can give you everything you want here and more. It's the right hammer for this particular nail, not dependency attributes. But respectfully speaking, your opinion is not the only one that matters here. Who are we to tell some in-good-faith developer that they are objectively WRONG to hope their script loader could not only LOAD scripts but RELOAD or ALTLOAD scripts. Think about the conceptual and semantic there. It's a pretty sensible expectation for most non-browser-author devs. We'll be able to do this from the Navigation Controller: https://github.com/slightlyoff/NavigationController/blob/master/explainer.md Never heard of it before. Thanks for the link. But I don't see how the idea that this may (likely) happen (someday) We're working on implementing it in Chrome. So yes, both likely and soon. automatically moots the discussion at hand. For you to fairly exercise some sort of veto vote over what we discuss, which it seems like you're trying to do, you've gotta come to the table with some real tangible thing that's standardized (or clearly headed that way) and ready to evaluate for fitness to the
Re: [whatwg] Script preloading
(AT EYE-WATERING-LENGTH) I'm sorry I'm too verbose on the list for everyone's taste. Every time I'm brief and make assumptions, I get accusations like Jake's repeated ones that I'm just asserting without reason. FWIW, my exhaustion of this process is not about my eyes, but my fingers sure take a beating. :) Ok, I think I understand what you're saying now. Happy we're on the same page there, then. :) It's not scepticism at that level that I'm expressing. Accepting everything you just typed out (AT EYE-WATERING-LENGTH), changes to Ian's proposal are still a poor place to attack the issue. The Navigation Controller can give you everything you want here and more. It's the right hammer for this particular nail, not dependency attributes. I'm not arguing for dependency attributes, nor am I arguing that they should or should not do this or that. Jake and Ian are. I'm only trying to give them due consideration, through my prior posted code snippets (and others I'm working on) to examine what they do and do not afford as it relates to the use-cases I believe are important to consider. But I've stated that I actually don't like the dependency attribute, for many reasons previously stated, and further reasons I hope to demonstrate through the code comparisons Jake suggested. That is an ongoing effort to examine and explore the pros-and-cons, and is done in good faith. Again: my question (which remains unanswered), the reason I stated the error/retry/fallback use case in detail, is whether or not the dependency attributes proposal, as put forth by Jake (and Ian) will or will not, factually speaking, have any sensitivity to the error conditions (network load error, compile error, run-time error) or not, or somewhere in between? If `dependencies` IS sensitive, in any way, then it clearly overlaps Navigation Controller, right? That may or may not be a good thing. If OTOH it has no sensitivity whatsoever, and it will trigger a subsequent waiting resource regardless of ANY particular network condition or result, that is vital information to know, as well. Either way, shouldn't we afford enough discussion here to discuss how little or how much, or if at all, that sensitivity would be? I certainly can't adequately judge the proposal in the absence of that information. Isn't it fair enough for me to inquire as to the actual nature of their proposal, given that they've asserted in no uncertain terms that it is fully sufficient for all my use-cases? Aren't I entitled to examine that with the assistance and participation of this list? None of that means I necessarily think that Navigation Controller is or is not ALSO suitable. I have no opinion on that yet. I stated the reasons why I have no opinion on it yet. Presenting an alternate proposal for one or more use-cases, as you have done, is fine. But that doesn't mean that it answers the questions I have about the other proposal, by Jake and Ian. Those pre-existing questions are my concern, presently. We're working on implementing it in Chrome. So yes, both likely and soon. I look forward to seeing more great documentation on it as we've all come to appreciate from the Chrome and Developer relations teams. It's unfair of you to expand the scope of a proposed feature to include your pet issue when, logically, it can be separated. See what we both just did there? Expand the scope? I am not expanding the scope beyond that which I've pushed for over and over again for 3+ years, this thread just being the latest incarnation. That others (like you) may come to this list with a pre-conceived notion of what is and is not in scope doesn't mean that me stating (in response to repeated appeals from Jake and others) at length the use-cases *I* care about is actually expanding that scope. Moreover, I am the originator, or at least one of them, of the proposed feature, so I hardly think it's fair for you assert that I'm changing the game. In reality, I'm clarifying the proposed feature as it relates to my viewpoint, as an interested party acting in good faith. I'm recounting the substantial prior art in the discussions and discovery and experimentation. No, I'm not expanding the scope. You (and others) appear to want to be narrowing the scope that well pre-dates this thread. My scope (as it always has been) put simply: I want (for all the reasons here and before) to have a silver bullet in script loading, which lets me load any number of scripts in parallel, and to the extent that is reasonable, be fully in control of what order they run in, if at all, responding to conditions AS THE SCRIPTS EXECUTE, not merely as they might have existed at the time of initial request. I want such a facility because I want to continue to have LABjs be a best-in-class fully-capable script loader that sets the standard for best-practice on-demand script loading. Better to ask how best to accomplish our goals, not
Re: [whatwg] Script preloading
On Fri, Jul 12, 2013 at 7:56 PM, Kyle Simpson get...@gmail.com wrote: [ snip ] Again: my question (which remains unanswered), the reason I stated the error/retry/fallback use case in detail, is whether or not the dependency attributes proposal, as put forth by Jake (and Ian) will or will not, factually speaking, have any sensitivity to the error conditions (network load error, compile error, run-time error) or not, or somewhere in between? As per the existing outline, I don't see how it could have any sensitivity. If `dependencies` IS sensitive, in any way, then it clearly overlaps Navigation Controller, right? That may or may not be a good thing. If OTOH it has no sensitivity whatsoever, and it will trigger a subsequent waiting resource regardless of ANY particular network condition or result, that is vital information to know, as well. Either way, shouldn't we afford enough discussion here to discuss how little or how much, or if at all, that sensitivity would be? I certainly can't adequately judge the proposal in the absence of that information. Isn't it fair enough for me to inquire as to the actual nature of their proposal, given that they've asserted in no uncertain terms that it is fully sufficient for all my use-cases? Aren't I entitled to examine that with the assistance and participation of this list? None of that means I necessarily think that Navigation Controller is or is not ALSO suitable. I have no opinion on that yet. I stated the reasons why I have no opinion on it yet. Presenting an alternate proposal for one or more use-cases, as you have done, is fine. But that doesn't mean that it answers the questions I have about the other proposal, by Jake and Ian. Those pre-existing questions are my concern, presently. We're working on implementing it in Chrome. So yes, both likely and soon. I look forward to seeing more great documentation on it as we've all come to appreciate from the Chrome and Developer relations teams. I owe this list (and others) mail about it. Hoping to have that ready soon. It's unfair of you to expand the scope of a proposed feature to include your pet issue when, logically, it can be separated. See what we both just did there? Expand the scope? I am not expanding the scope beyond that which I've pushed for over and over again for 3+ years, this thread just being the latest incarnation. That others (like you) may come to this list with a pre-conceived notion of what is and is not in scope doesn't mean that me stating (in response to repeated appeals from Jake and others) at length the use-cases *I* care about is actually expanding that scope. I think you missed the second sentence... Moreover, I am the originator, or at least one of them, of the proposed feature, so I hardly think it's fair for you assert that I'm changing the game. In reality, I'm clarifying the proposed feature as it relates to my viewpoint, as an interested party acting in good faith. I'm recounting the substantial prior art in the discussions and discovery and experimentation. No, I'm not expanding the scope. You (and others) appear to want to be narrowing the scope that well pre-dates this thread. My scope (as it always has been) put simply: I want (for all the reasons here and before) to have a silver bullet in script loading, which lets me load any number of scripts in parallel, and to the extent that is reasonable, be fully in control of what order they run in, if at all, responding to conditions AS THE SCRIPTS EXECUTE, not merely as they might have existed at the time of initial request. I want such a facility because I want to continue to have LABjs be a best-in-class fully-capable script loader that sets the standard for best-practice on-demand script loading. Better to ask how best to accomplish our goals, not fight over where to do that. And that's the spirit I offered the NC in (and pour my work into it over). Happy to discuss NC over at the github repo, FWIW. Fair enough. That spirit is certainly appreciated. At the request of this list, I presented the use-cases as they stand, and as they always have. Any solution(s) which reasonably meet them would be a good candidate. We're seeking solutions, but we're doing so by exploring the fitness of various proposals. Over the years, I've championed no fewer than 3 different proposals for how I see a single coherent solution that solves all the use cases. That alone ought to demonstrate sufficient good-faith that I'm looking for solutions, not impetuously defending my pet. Moreover, especially with this most recent proposal (script preload), I believe it not only sufficient to (trivially) handle *all* the use-cases I've presented, but also it is of the nature that it basically would answer nearly any other use-case you could imagine in script loading. Certainly my list is long but not fully exhaustive of every niche need/desire. In light of
Re: [whatwg] Script preloading
(being as brief as I possibly can...) As per the existing outline, I don't see how it could have any sensitivity. So, just to clarify, `script dependencies=…` waiting on some other script tag is ONLY waiting on that script tag loading to have some sort of positive network result, whether that be a 2xx, 3xx, 4xx, or 5xx, and it cares not whether the script in question actually loaded, nor whether it fired its `onerror` event? Do I have that correct? I think you missed the second sentence… Did I miss some rhetorical levity? Sorry. :) That's only your ignorance speaking. There are examples in the repo which you can use to extrapolate examples, or if you a code snippet showing the problem, I did show a code snippet with the problem already. Specifically: https://gist.github.com/getify/5976429#file-ex2-jaffathecake-js-L54-L68 As I said, I only glanced at your long writeup on Navigation Controller. Ignorance is a tiny bit of a pejorative term for my lack of knowledge of some non-trivial you just dropped onto the list right in the middle of lots of other discussion. But I'll take it in a pleasant light and agree, indeed, that I'm ignorant so far of how Navigation Controller can help. Had it been clear and obvious to me in my initial glances at your document immediately how to address the code problem above, I certainly wouldn't have exposed such ignorance. In any case… either Jake or I can show how NC would address it. I would certainly appreciate input on that part of the code I highlighted. As I said… I look forward to you helping remedy that. :) --Kyle
Re: [whatwg] Script preloading
On Wednesday, 10 July 2013, Kyle Simpson wrote: You know, I keep relying on the fact that the body of work on this topic for almost 3 years … I've spent more time over the last 4+ years obsessing on script loading than any other developer … I am saying the same things I've been saying for 3 years. This is the open web, length of service does not excuse anyone from reasoning and evidence. But sure, I'll say them, AGAIN, because now someone wants to hear them again. If you feel you're repeating content from elsewhere, you could have linked to it (hurrah for the web)! If you hadn't compiled your use-cases requirements in one place before, then excellent, you have now. You can link to this in future. I doubt anyone is going to read this crazy long message and actually read all these, but I'll put them here nonetheless. I am reading this, and I will show how Hixie's #1 solution (plus the minor additions I suggested) meet your use-cases. For others reading I'll also detail the use-case in a complete but succinct way. 1. Premise: I'm the author of a popular and wide-spread used script loader. It's a general utility that's used in tens of thousands of different sites, under a myriad of conditions and in different ways, and in a huge swath of different browsers and devices. I need the ability inside this general utility to do consistent, 100% reliable, predictable script loading for sites, without making ANY assumptions about the site/markup/environment itself. I need to be as unintrusive as possible. It needs to be totally agnostic to where it's used. Use-case: Script loaders such as LabJS should continue to work at least as well as they do now. As you've stated previously, LabJS is complete in that it continues to work without much development effort. LabJS could either improve by using the new feature, or not, and continue as is. 2. Premise: I need a solution for script (pre)loading that works not JUST in markup at page-load time, but in on-demand scenarios long after page-load, where markup is irrelevant. Markup-only solutions that ignore on-demand loading are insufficient, because I have cases where I load stuff on-demand. Lots of cases. Bookmarklets, third-party widgets, on-demand loading of heavy resources that I only want to pay the download penalty for if the user actually goes to a part of the page that needs it (like a tab set, for instance). In fact, most of the code I write ends up in the on-demand world. That's why I care so much about it. Use-case: I want to preload scripts that execute straight away, such as social media scripts, and defer their execution. The need for the script may be determined by script (eg feature detection), so you need to be able to trigger preload via script. Executing the script should be optional (user may not interact with the button). (this is actually many of the use-cases in this email rolled into one, to save on reading and repetition) Anyway, here's how you'd preload two scripts and have them execute in order some time later (but not be held up by other scripts like async=false). If the script have more flexibility in terms of execution order, you can specify that and get better performance. link rel=subresource href=path/to/script.js class=preload link rel=subresource href=path/to/another-script.js class=preload script // scripts are preloading at this point function loadScripts(done) { var toLoad = document.querySelectorAll('.preload'); var script; for (var i = 0, len = toLoad.length; i len; i++) { script = document.createElement('script'); // depend on the previous script if (i) script.dependencies = 'script[src=' + toLoad[i-1].href + ']'; script.src = toLoad[i].href; document.head.appendChild(script); } script.onload = done; } loadScripts(function() { // scripts are ready! }); /script The without-markup solution is the same as above, but the link[rel=subresource] elements are created conditionally with JS. link[rel=subresource] is the right solution for preloading, it's what it's for and it works on more than just script. If there are issues with this cache headers, there shouldn't be, let's fix that. 3. Premise: this is NOT just about deferring parsing. Some people have argued that parsing is the expensive part. Maybe it is (on mobile), maybe not. Frankly, I don't care. What I care about is deferring EXECUTION, not parsing (parsing can happen after-preload or before-execution, or anywhere in between, matters not to me). Why? Because there's still lots of legacy content on the web that has side-effects when it runs. I need a way to prevent those side effects through my script loading, NOT just hoping someday they rewrite their code so that it has no side effects upon execution. Use-case: this is just the previous use-case with more words. See above. Although most libraries etc defer major execution to function calls
Re: [whatwg] Script preloading
On 10 July 2013 17:37, Jake Archibald jaffathec...@gmail.com wrote: On 10 July 2013 16:39, Kyle Simpson get...@gmail.com wrote: I personally don't care about scripts being discoverable by pre-parsers. I have done testing and am not convinced that something appearing earlier (in markup) leads to better performance than allowing my script loading logic to load things when I want, and just relying on the browser to do that as quickly as possible. Pre-parsers can kick in before a page is actually opened, but script cannot be executed. Let me dig up some numbers on the benefits of this report back. Here it is: https://plus.sandbox.google.com/+IlyaGrigorik/posts/8AwRUE7wqAE ~20% improvement.
Re: [whatwg] Script preloading
Here's the Plus URL without the googler cruft: https://plus.google.com/u/1/+IlyaGrigorik/posts/8AwRUE7wqAE On Thu, Jul 11, 2013 at 3:47 PM, Jake Archibald jaffathec...@gmail.comwrote: On 10 July 2013 17:37, Jake Archibald jaffathec...@gmail.com wrote: On 10 July 2013 16:39, Kyle Simpson get...@gmail.com wrote: I personally don't care about scripts being discoverable by pre-parsers. I have done testing and am not convinced that something appearing earlier (in markup) leads to better performance than allowing my script loading logic to load things when I want, and just relying on the browser to do that as quickly as possible. Pre-parsers can kick in before a page is actually opened, but script cannot be executed. Let me dig up some numbers on the benefits of this report back. Here it is: https://plus.sandbox.google.com/+IlyaGrigorik/posts/8AwRUE7wqAE ~20% improvement.
Re: [whatwg] Script preloading
On Thu, Jul 11, 2013 at 9:41 PM, Kyle Simpson get...@gmail.com wrote: I'm still going to respond, in detail, with code comparisons, to Jake's suggestions that the other proposals besides mine handle all my stated use-cases. However, before I do that, just to document for posterity, I just recalled another use-case which is a feature very frequently requested of LABjs, but is impossible with the current web platform. It's so common, I'm not sure why I forgot it in the other list, except perhaps sheer exhaustion. 12: Use-case: you have a string of scripts (A.js, B.js, and C.js) loading which constitute a dependency chain. A must run before B, which must run before C. However, if you detect an error in loading, you stop the rest of the executions (and preferably loading too!), since clearly dependencies will fail for further scripts, and the errors will just unnecessarily clutter the developer console log making it harder to debug. How is this any different from the case today when script elements are fetched and run in the situation where one 404's? And why is the fix not a stop on first script error devtools option rather than a change to the intrinsics for loading? This is the usual recourse for most debuggers. Or are you saying we should be able to detect (via HTTP status code? some other mechanism?) that a script load as failed before we even attempt to run the code which might depend on it? I'm unsure how any of this is apropos to the debate at hand. Changes to this proposal seem entirely the wrong place to be dealing with this sort of failure/recovery issue. One reason developers want this ability to pause/abort part of a chain of dependencies is the idea of graceful recovery, where they could re-try the failed download again a few times, or perhaps try fallback URLs for a script, etc. In any case, the desire is to stop C from running if B fails to load, for whatever reason. In fact, some developers have even requested to be able to stop the chain and prevent further executions if the script loads, but there's some compile-time syntax error or run-time error that happens during the execution. For them, it's not enough for B to simply finish loading successfully, but that it must fully execute without error. Generally speaking, separate JS files are treated as separate programs and are NOT prevented from executing if there's an error running a previous file. These developer requests are that they'd like script loaders to be able to give them that stop the presses! sort of error handling which they currently do not have. From my observation of Jake's proposed code, the former part of this use-case seems possible, assuming `dependencies` would fail to match on a script which resulted in a load error (4xx, 5xx). There would be the extra complication that the script loader might switch to an alternate fallback URL for a script, in which case it'd have to go find any script elements waiting on the previous (failed) URL and update their `dependencies` list to the new URL. However, it's less clear to me if `dependencies` would fail a match on a script that loaded successfully and started trying to run, but had some uncaught error happen during compile or execute? If so, fine. Would that also mean that if the script loader were to retry (either with same or alternate URL) B, and that were to succeed finally, then C would then recognize that eventual success (in spite of previous failures) and run as expected? If so, fine. If however `dependencies` can't be made sensitive to unerrored-execution, and there's no other event that a script loader can intercept **between** B and C and have a chance to stop C from running (yet), then I think this would be a use-case not fully served by what I've seen so far. Also, there's the question of what it would mean/tak to stop C from running (yet). Perhaps the suggestion is to remove C's script element from the DOM for the time being? Would that actually be sufficient to prevent it from executing (even if it had already finished loading and was just paused waiting)? Or perhaps the suggestion would be to temporarily change C's `dependencies` list to have some selector in it that's made up and not possibly fulfilled, like a made up/impossible script URL, so that C remains paused, until a later time when the script loader can come back and set the dependencies list back to something sane so that C can resume? --Kyle
Re: [whatwg] Script preloading
How is this any different from the case today when script elements are fetched and run in the situation where one 404's? Right now, without any script loader, AFAICT, if A loads fine, B 404's or 500's, and C loads fine, both A and C will run, and usually C will have lots of cascading errors because it assumes B ran when it clearly didn't. What I'm saying is that quite a few developers have repeatedly asked for LABjs to provide some relief to that, because they would like to be able to have code-driven logic that tries to gracefully handle such an error. As I said, some developers have expressed the desire to have a script loader be able to re-try a failed script load a few times. Others have expressed the desire to have alternate fallback URL(s) if a script fails to load at its primary location. The point is, normal script tags don't let devs do that AT ALL, and when they want to do such things, they hope that a script loader could give them that capability. Since LABjs currently relies on script elements in pretty much all cases, LABjs can't give them what they want. As far as I'm concerned, this is absolutely a *candidate* for a perfect silver-bullet next-generation script loading mechanism that handles all the complex use-cases under discussion thus far under discussion. And why is the fix not a stop on first script error devtools option rather than a change to the intrinsics for loading? This is the usual recourse for most debuggers. As stated, this isn't as much about developers doing things in dev-mode, it's about them wanting to have more robust loading logic in their production installations that is capable of doing things like script-load-retries or script-load-fallback-URLs. Certainly developers asking LABjs for this don't care nearly as much whether other developers can effectively deal with the issue using their devtoosl as they care that their production website in front of end-users has the ability to respond more robustly, if they care that much in the first place. Or are you saying we should be able to detect (via HTTP status code? some other mechanism?) that a script load as failed before we even attempt to run the code which might depend on it? I was suggesting if we're inventing a new mechanism called `depends` as Jake has suggested, it would be nice if that new mechanism was made sensitive to things like did the script load successfully (non 4xx/5xx), and even better if it could also be sensitive to things like the script load successfully, but was there an uncaught error thrown during its main execution? The more sensitive the mechanism is, the more capable it would be to handling the use-cases these developers care about. I'm unsure how any of this is apropos to the debate at hand. Changes to this proposal seem entirely the wrong place to be dealing with this sort of failure/recovery issue. Why so hostile? Isn't it quite apropos/germane to discuss HERE what real-world developers want to do (and cannot do currently!) in their code as it relates to script loading? I exhaustively listed out 11 other use-cases of things I care about, as a script loader author/maintainer. Are none of those use-cases apropos? Then I noted an additional 12th use-case here that I may not personally care as much about, but dozens of times developers have filed issues against LABjs begging/insisting for. It appears that some people care enough about production loading robustness that they go to extraordinary efforts in their code to detect and respond to such conditions. I felt like those many requests to LABjs (and I'm sure other script loaders get similar requests) was evidence enough that there's a valid use-case to consider and I was just bringing it up for such consideration. --Kyle
Re: [whatwg] Script preloading
I am interested to see how the above use-cases would be met in your counter proposal(s) to see if it would be simpler/faster. If LabJS is a requirement, it must be factored in as a unit of complexity and load-step. Please do this rather than declare anything to be insufficient without reasoning. It's gonna take a lot of time to write proof-of-concept code for all the different nuances and use-cases I've brought up. I'm presenting 2 here. There's more to come. Unfortunately, Jake made a number of simplifying assumptions, or simply missed various nuances, in his attempt to combine/reduce/restate my use-case list. I'm not ascribing any ill-will to that, but just pointing out that it's not nearly as easy as his list might suggest. I've spent some time trying to put together a first set of code comparisons between the `script preload` proposal I've put forth and the `link rel=subresource` + `script dependencies=..` proposal Jake is advocating. This is by no means an exhaustive comparison or even nearly stating the many issues I forsee, but it starts the discussion with actual code instead of theoretical concepts. https://gist.github.com/getify/5976429 There's lots of code comments in there to explain intended semantics, outstanding questions/issues, etc. Some observations/clarifications: * ex1-getify.js is my attempt at creating a simple `loadScripts()` script loader that loads scripts in parallel, but executes them strictly in request order, serially. -- ONE KEY NOTE: my implementation accomplishes my use case #11 quite easily, in that it doesn't start executing any of the scripts in a group until ALL the scripts are finished preloading, thus minimizing any gaps/delays between them running. I'm able to do this easily because every script fires a preload event, so it's trivial to know when all such events have fired as my clue on when to start execution. * ex1-jaffathecake.js is my attempt at doing something as close as possible using Jake's proposed way. I've asked for his feedback on this code, so until he has a chance to feedback, take it with a grain of salt. In any case, the code is certainly simpler, but it's missing a KEY COMPONENT: it's NOT able to assure what my script loader code does. That is, a.js might run long before b.js runs, whereas in my implementation, there should be almost no gaps, because a.js doesn't run until b.js is loaded and ready to go. Jake suggested a hack to address this use-case which is based on the idea of hiding the whole page while scripts load with gaps in between. This hack is not only terribly ugly, but it also misses a big point of my motivation for that use-case. The point is NOT can we hide stuff visually, it's can we make sure stuff doesn't run until EVERYTHING is ready to run. Moreover, as I note in the code comments, it is impossible/impractical for a generalized script loader to be able to determine all or parts of a page that it should hide, and under what conditions. The script loader is agnostic of what it's loading, and it certainly is supposed to be as unobtrusive to the hosting page as possible, so it's out of the question to consider that a script loader would go and do nuclear-level things like hiding the document element. The key thing that's missing in Jake's proposal that's necessary to address this use-case is that there's no way to be notified that all the scripts have finished pre-loading. Instead, his approach obfuscates when things finish loading by simply letting the script element internally listen for loads of its dependencies. This is what I mean when I keep saying chicken-and-the-egg, because I want to know everything's finished preloading BEFORE I start the execution cursor, but in Jake's world, I can't know stuff is finished loading until after I observe that it's running. * ex2-getify.js is a more complex script loader, that takes into account the ability to have sub-groups of scripts, where within the sub-group, ASAP execution order is desired, and serial-request-order execution order is desired across the various sub-groups. Simply stated: All of C, D, E, and F scripts load in parallel. When it comes to execution, C.js runs, then a sub-group of D.js and E.js will run, where within the sub-group, either D or E runs first, ASAP (they don't block each other), and then when both have run, finally, F.js executes. This scenario is quite common: I load jquery.js, then I load 4 jquery plugins (which are independent), then I load my page's app.js code runs. jquery.js is the firs to execute, then the 4 plugins run in ASAP order, then when they're all done, finally my app.js code executes. Also, this more complex script loader listens for `script.onerror` events, and if it detects one, it aborts any of the rest of the execution. Any such error handling is trivial in my loader, because I am always fully in control over which script is loading at any given time. *
Re: [whatwg] Script preloading
On browser preloading: There seems to an inherent conflict between 'indiscriminate' Pre-parsers/ PreloadScanner and responsive design for mobile. Responsive designs mostly implies that everything needed for a full screen desktop is provided in markup to all devices. Isn't the Pre-parsers/PreloadScanner's inability to take into account the display[none:yes] factor be a potential significant blow to 'mobile' performance. Use case: What if I have a set of images in an element set as display:none; only designated to be show on desktop or tablet screens and not on mobile phone? What if I have an inline script in that node? Isn't the PreloadScanner loading a lot more than I need, a problem here? In addition to the need to preload, with responsive design taken into consideration, and for lack of not being able to remove part of the body before the browser parses the document. I see an increasing potential need for the ability to indicate to the browser not to load selective assets before DOMReady and suppress such preload. Bruno On 7/11/13 8:23 AM, Alex Russell slightly...@google.com wrote: Here's the Plus URL without the googler cruft: https://plus.google.com/u/1/+IlyaGrigorik/posts/8AwRUE7wqAE On Thu, Jul 11, 2013 at 3:47 PM, Jake Archibald jaffathec...@gmail.comwrote: On 10 July 2013 17:37, Jake Archibald jaffathec...@gmail.com wrote: On 10 July 2013 16:39, Kyle Simpson get...@gmail.com wrote: I personally don't care about scripts being discoverable by pre-parsers. I have done testing and am not convinced that something appearing earlier (in markup) leads to better performance than allowing my script loading logic to load things when I want, and just relying on the browser to do that as quickly as possible. Pre-parsers can kick in before a page is actually opened, but script cannot be executed. Let me dig up some numbers on the benefits of this report back. Here it is: https://plus.sandbox.google.com/+IlyaGrigorik/posts/8AwRUE7wqAE ~20% improvement.
Re: [whatwg] Script preloading
On 9 July 2013 20:39, Ian Hickson i...@hixie.ch wrote: 1. Add a dependencies attribute to script that can point to other scripts to indicate that execution of this script should be delayed until all other scripts that are (a) earlier in the tree order and (b) identified by this attribute have executed. script id=jquery src=jquery.js async/script script id=shims src=shims.js async/script script dependencies=shims jquery src=myscript.js async/script This would download jquery.js, shims.js, and myscript.js ASAP, without blocking anything else, and would then run jquery.js and shims.js ASAP, in any order, and then once both have executed, it would execute myscript.js. This works for me can we have it now please? The dependencies attr should make loading non-blocking, even without the async attr. This produces a nice fallback: script dependencies id=jquery src=jquery.js/script script dependencies id=shims src=shims.js/script script dependencies=#shims, #jquery src=myscript.js/script Browsers without dependencies support will load the above in a blocking way, but at least in a dependable order. Dependencies should be resolved when the element is inserted into the document, which avoids circular dependencies. script dependencies=#shims id=jquery src=jquery.js/script script dependencies=#jquery id=shims src=shims.js/script The first script above would have no dependencies and will execute as soon as it downloads, as there was no element with ID shims when dependencies were resolved. Also, as above, it'd be great if dependencies took CSS selectors rather than IDs, this means: script dependencies=script id=shims src=shims.js/script becomes the declarative form of async=false. The CMS plugins from Kyle's example would use dependencies=script until they become more script-aware. The dependencies attribute should also work on scripts without src, eg script dependencies id=jquery src=jquery.js/script script dependencies=#jquery // jquery is ready /script 2. Add an whenneeded boolean content attribute, a markNeeded() method, and an internal is-needed flag (initially false) to the script element. When a script is about to execute, if its whenneeded= attribute is set, but its is-needed flag is not, then delay execution. Calling markNeeded() on a script that has a whenneeded boolean but that has not executed yet first causes the markNeeded() method on all the script's dependencies to be called, and then causes this script to become ready to execute. script id=jquery src=jquery.js async whenneeded/script script id=shims src=shims.js async whenneeded/script script id=myscript dependencies=shims jquery src=myscript.js async whenneeded/script This would download jquery.js, shims.js, and myscript.js ASAP, and then wait for further instructions. document.getElementById('myscript').markNeeded(); This would then cause the scripts to execute, first jquery.js and shims.js (in any order), and then myscript.js. If any hadn't finished downloading yet, it would first wait for that to finish. (We could make markNeeded() return a promise, too.) I'm similarly not-convinced on delayed parsing/execution. This is better solved by moving parsing onto a different thread, then the whole web benefits rather than just those using this new feature. I'm open to evidence to the contrary. I've delayed/avoided parsing to great performance benefit on ancient devices, but this feature won't be adopted there. In this edge-case, hacks such as HTML comments are best and supported today. However, if this feature were adopted, dependencies would be redundant, as I could do it all myself with markNeeded(). script id=jquery src=jquery.js whenneeded/script script id=shims src=shims.js whenneeded/script script id=myscript src=myscript.js whenneeded/script script Promise.every( document.querySelector('#jquery').markNeeded(), document.querySelector('#shims').markNeeded() ).then(function() { document.querySelector('#myscript').markNeeded() }); /script Is there a need for delaying the download of a script as well? (If so, we could change whenneeded= to have values, like whenneeded=execute vs whenneeded=download or something.) I don't have a use-case for this that isn't handled by dynamic script insertion. Is there something this doesn't handle which it would need to handle? The dependencies attribute, along with the CSS selector stuff, 'async'-like behaviour by default if it's allowed on inline scripts meets all my use-cases. For completeness, here are my requirements: - Does not block page rendering - Provides an adoption path for browsers that don't support the new feature (happy for the fallback to be blocking document-order execution) - Allows scripts to execute in any order as along as their dependencies are met (so async=false is not enough) - Is
Re: [whatwg] Script preloading
On 9 July 2013 21:41, Kyle Simpson get...@gmail.com wrote: http://wiki.whatwg.org/wiki/Script_Execution_Control My proposal was to standardize what IE4-10 did, which is to start loading a script even if it's not in the DOM, but not execute it until it's in the DOM. Then, you monitor an event to know if one or more scripts have finished this preloading, and then you can decide if and when and in what order to add the corresponding script elements to the DOM to allow execution to proceed. The IE4-10 technique is invisible to pre-parsers, if we're chasing performance here it's not good enough. Setting aside IE's non-standard event mechanism, Nicholas' proposal was also perfectly sensible, and pretty simple. He suggested the same mechanism for execution (adding a script to the DOM), but suggested a `preload` attribute on the element to prevent auto-execution, and a `onpreload` event to notify you of loading-complete. Also invisible to preloaders. You could make preload an attribute which does a non-blocking download but not execution. This is visible to preloaders and falls back to standard ordered blocking loading which is fine. Then you'd have a method to trigger execution of the script later. This is Hixie's whenneeded proposal. However, whenneeded is more complex than dependencies. Unless there's a good use-case for deferred parsing that can't be handled by link[rel=subresource] and similar, dependencies is the better option. 1. Add a dependencies attribute to script that can point to other scripts to indicate that execution of this script should be delayed until all other scripts that are (a) earlier in the tree order and (b) identified by this attribute have executed. script id=jquery src=jquery.js async/script script id=shims src=shims.js async/script script dependencies=shims jquery src=myscript.js async/script …content-management-systems (through plugins) load different items into a page independently of other plugins. Those plugins have no knowledge of the complete content/markup-structure of the page… If dependencies took a CSS selector it could be: script dependencies=.cms-core src=cmd-plugin.js/script Now the number of scripts with class cms-core can change between versions of the CMS but the plugin still waits for them all. No ID generation needed. Does this fix the issue for you? Moreover, this ignores some use-cases for script preloading which are basically speculative preloading. I may want to load several plugins, but not execute any of them, and then only use one of them depending on what the user does. This can be better achieved with things like link[rel=subresource] which work for more than just scripts. When the script is required, it can be added to the page with js, using something like LabJS or the dependencies attribute to control execution order if necessary. So, the real need here is NOT just to chain a set of scripts together, but to put the author in control of pausing a script between load and execute, and then they get to decide when/if they unpause a script. Given the above, is there a usecase that isn't catered for by dependencies and existing preloading features? 2. Add an whenneeded boolean content attribute… It doesn't solve the I need an event to know when load is finished. If I'm waiting for a bunch of stuff to load before asking any of them to execute (in the order I want), I need a way to know that each of them are in fact fully loaded. Sorry to keep being Mr Use-case, but what do you need to do that isn't catered for? You can call markNeeded() when you want the script executed both a promise and the script's load event will tell you when it's done. Why would you need to know when it's downloaded but not executed? Secondly, it seems like a bit more complex version of Nicholas' proposal, with just different names. Not sure why the complecting of API with (mostly) his same semantics. To me, it seems like a simplification of Nicholas' proposal, but still more complicated than dependencies without good reason. Also, it works with preparsers. Can you provide a comparison that shows another suggestion to be simpler than both of Hixie's proposals and match/beat it's performance?
Re: [whatwg] Script preloading
On 9 July 2013 22:31, Garrett Smith dhtmlkitc...@gmail.com wrote: On 7/9/13, Ian Hickson i...@hixie.ch wrote:script id=jquery src=jquery.js async/script script id=shims src=shims.js async/script script dependencies=shims jquery src=myscript.js async/script Why limit depends to be used by only scripts to refer only to other scripts? If you put link depends=idref on style then stylesheet evaluation could be deferred, too. I like this idea and want to start a family with it. This would then cause the scripts to execute, first jquery.js and shims.js (in any order), and then myscript.js. If any hadn't finished downloading yet, it would first wait for that to finish. (We could make markNeeded() return a promise, too.) Or use a callback. Blocking on resource loading is bad. Promises don't block. New APIs that want callbacks for async success/failure should use Promises.
Re: [whatwg] Script preloading
On 7/9/13 7:09 PM, Kyle Simpson get...@gmail.com wrote: I have been wrestling pretty hard with script loading issues lately. I'd say that having the browser manage script interdependency is probably a bad and cumbersome way to solve these issues. What do you mean by having the browser manage script interdependency? As far as I am aware, this thread and these feature requests are not about the browser managing script interdependencies in fact, quite the opposite. What we're asking and hoping for is a facility that allows the app code to manage the dependencies and the loading order, while only relying on the browser to do the actual loading for us the way it always has. Maybe we diverge on semantics. When you say while only relying on the browser to do the actual loading for us the way it always has. That's not really what I am seeing. The suggestion #2. given by Ian is not only doing the loading per say. The browser has to figure out the dependencies from the dependency information given in a DOM format. That's essentially what I mean by delegating the dependency management to the browser. Anyway, as per your previous email I think we mostly agree that solution #1 is not very practical (or infeasible per your word) and #2 is awfully complex. The only part of that puzzle that's missing is a way to tell the browser to pause between finishing-loading and starting-executing. Asking for such a mechanism has really nothing to do with offloading dependency management to the browser to handle. It's empowering the app code to be more in control, not less. I think that preloading without executing is really what we should are after. But there has to be a simpler way to do this. I think one of the reason that people may ask for this Interdependency feature, is due to the weakness of the platform they use, Again, I think you may possibly be misunderstanding the goal of what's being asked for. But I'll agree with you that there's a weakness. The weakness, IMO, is in the web platform itself, in not giving us more fine-grained control over script loading. That is why we keep having this discussion every 6 months or so for the least several years. The use-cases never go away, and the hacks we use to deal with them never get any less ugly. And 'async', while good for independent scripts such as social media apis, is not really a good tools for dependency management. Again, possibly a case of misunderstanding or missed context from previous conversations. When I bring up async, I'm not talking about script async in markup as you suggest, but actually `script.async = false` being set on dynamcially created script elements (in code). async=false (aka ordered async) is a relatively new feature added to the platform about 2.5 years ago that gives us async parallel loading, but the browser automatically enforces execution order to be request order, instead of ASAP order. async=false is actually a good feature. The problem is not the feature itself, but that it's only part of what we needed. I see. I am shamefully new to the notion that async=false is ordered async. It apparently went quite off specs through vendors first to make this work, with no much of an official documentation, hence me missing it I guess... Though it kind of make me cringe that vendors jumped on implementing such new slightly unintuitive feature, while HTML4 specs like 'defer' were left unreliable. It feel like priorities worked slightly backwards... Nevertheless ordered async is very useful as solving part of the problem indeed. My main issue against using external script loaders like LABjs and others, has always been that if the browser must download a script first, before starting to download the dependencies. It presents a drawback already, for delayed the scripts by the script loader's latency and download time (at least for the first uncached page load) similarly to having scripts at the bottoms. For LABjs' part, I never suggest to people to load LABjs in a separate file. I suggest that people use a bootstrap type code file, which would be a single .js file they load with a single script tag in their markup, and it contains all the bare-minimum code necessary to bootstrap the page/app. It would include the code for LABjs, also the $LAB chains for loading other scripts, even basic event handling or other bootstrap type logic. Moreover, the extra ~2k of gzip-bytes that LABjs costs (even if it's a separate file, but especially if it's included in another bootstrap file) is almost always made up for in savings by being able to take advantage of consistent parallel loading of scripts. If your page only has 3-5k of JS on it, then you shouldn't use a script loader. But if you're like most sites, and you're loading 100-300k of JS, then a tiny 2k of JS for loading optimization is not even a drop in the ocean. It's not the size that bothers me. It's the inevitable first time delay. Ideally all scripts needed before
Re: [whatwg] Script preloading
On 10 July 2013 11:31, Bruno Racineux br...@hexanet.net wrote: Anyway, as per your previous email I think we mostly agree that solution #1 is not very practical (or infeasible per your word) Given the suggestions I made to #1 in http://lists.whatwg.org/htdig.cgi/whatwg-whatwg.org/2013-July/039968.html, do you still think it's impractical (and why)? I think that preloading without executing is really what we should are after. *hits usecase button* Why would you want to do that? Are those cases already (better) solved by link[rel=subresource] and dynamic script insertion?
Re: [whatwg] Script preloading
The IE4-10 technique is invisible to pre-parsers, if we're chasing performance here it's not good enough. ... Also invisible to preloaders. I personally don't care about scripts being discoverable by pre-parsers. I have done testing and am not convinced that something appearing earlier (in markup) leads to better performance than allowing my script loading logic to load things when I want, and just relying on the browser to do that as quickly as possible. For instance, I've added like link rel=prefetch annotations for my scripts into the head of my document, and then done my normal script-based script loading as usual, and benchmarked if them being in the markup somehow magically sped up the page. I saw no appreciable increase in average page load speed in my testing. It's quite possible that this is because when I use script loading, generally speaking, I'm only loading the scripts I consider to be most critical for actual page load (not everything and the kitchen sink), so my script-based script loading during page-load usually is pretty darn quick. I defer the rest of my code that's not as critical until later (perhaps until when needed, strictly), which is something that markup alone doesn't let me do. I like the fact that I can have my bootstrapper load.js file either at the very top (and thus it starts loading them nearly immediately) if the scripts I want to load are more important than the images and stylesheets in the markup, OR I can put my load.js file at the bottom of the markup and thus give a chance for other content to start loading slightly before my scripts start loading. The fact that browsers are trying to second guess developers and look-ahead to find and prioritize certain resources is NOT something I consider a positive benefit that I'm eager to assist. I still come from a world where a developer ought to get to decide what's higher priority. There's certainly a strong pre-disposition among a lot of developers to falling in love with declarative markup-only solutions. I share no such obsession, when it comes to script loading. I think script loading is far more complex than markup is ever going to be equipped to handle. To be clear, I will not be satisfied with a markup-only approach. No matter how complex it is, it does not handle all the use-cases I care about. I feel like a broken record on these threads, because I keep talking about why markup-only is insufficient, and people keep trying to convince me they can make markup more and more complex and certainly they'll eventually convince me that markup-only is superior. The more complex you make the markup-only proposals, the more I'm convinced (and self-validated) that markup is the wrong tool for the complex use-cases I care about. --- All that having been said, I am not trying to block a solution that would BOTH serve those who have a subset of (simpler) use-cases which are markup-centric, and those of us who care about serving more complex use-cases via code. A solution that both camps can accept is better than either camp being happy to the exclusion of the other. I would be fine if we went with a variation of Nicholas' proposal. Let me state that new proposal here: ** Summary: 1. `preload` attribute on script tags in markup, `preload` property on script elements created by code. In either case, its presence tells the browser not to execute the script once it finishes loading. 2. `onpreload` event fired on any script which has `preload` attribute or property on it at the time its (pre)loading finishes (and execution is thus suppressed). Otherwise, not fired. 3. To execute a script that was preloaded in code, remove the `preload` attribute or property from the element, which signals to the browser that it's OK to execute it now. If you remove it before loading finishes, the browser acts as if it was never marked as preload and continues as normal. If you remove it after preloading finishes, the browser is free to execute that script ASAP now. 4. If you are doing markup-only loading, you signal to a preloaded script that its eligible for execution by putting a matching selector to it into a `fulfills` attribute on another script element. If a script finishes loading and it's already been signaled by another `fulfills`, it will run right away. Otherwise, it'll wait until some script executes that has a matching `fulfills` attribute on it. Details: The behavior of preload-but-don't-execute is controlled by the markup presence of a `preload` attribute on script tags (thus discoverable by pre-parsers), or a corresponding `preload` property in the script-based loading scenario. BOTH sides of the feature have to be implemented -- markup only is NOT enough for my needs. That attribute/property being present/set would be the only thing that signals to the browser load this script, but DON'T auto-execute it until told to do
Re: [whatwg] Script preloading
** Summary: 1. `preload` attribute on script tags in markup, `preload` property on script elements created by code. In either case, its presence tells the browser not to execute the script once it finishes loading. 2. `onpreload` event fired on any script which has `preload` attribute or property on it at the time its (pre)loading finishes (and execution is thus suppressed). Otherwise, not fired. 3. To execute a script that was preloaded in code, remove the `preload` attribute or property from the element, which signals to the browser that it's OK to execute it now. If you remove it before loading finishes, the browser acts as if it was never marked as preload and continues as normal. If you remove it after preloading finishes, the browser is free to execute that script ASAP now. 4. If you are doing markup-only loading, you signal to a preloaded script that its eligible for execution by putting a matching selector to it into a `fulfills` attribute on another script element. If a script finishes loading and it's already been signaled by another `fulfills`, it will run right away. Otherwise, it'll wait until some script executes that has a matching `fulfills` attribute on it. A variation on my proposal which gives a little more symmetry between markup-based loading and script-based loading: Instead of removing the `preload` attribute/property to signal it's OK to execute now, I just set another property on it called `fulfilled`. That attribute/property, if present at time of preload completion, means it's OK, go ahead an execute, or if added after preload, says go ahead and execute it now ASAP. The symmetry is that in markup-only usage, I use `fulfills` on another script tag (because with markup only I can't modify another script element) to signal that the preloaded script element is now fulfilled. But in script-based loading, I can just signal the preloaded script element directly that it's fulfilled now by setting a `fulfilled` property on it. I like that even a lot better than deleting/removing the `preload` attribute/property. --Kyle
Re: [whatwg] Script preloading
On 10 July 2013 16:39, Kyle Simpson get...@gmail.com wrote: The IE4-10 technique is invisible to pre-parsers, if we're chasing performance here it's not good enough. ... Also invisible to preloaders. I personally don't care about scripts being discoverable by pre-parsers. I have done testing and am not convinced that something appearing earlier (in markup) leads to better performance than allowing my script loading logic to load things when I want, and just relying on the browser to do that as quickly as possible. Pre-parsers can kick in before a page is actually opened, but script cannot be executed. Let me dig up some numbers on the benefits of this report back. But logically, [parse html]-[load script] is always going to be faster than [parse html]-[parse inline script]-[execute inline script]-[load script]. And I imagine, more bytes and complex. It's quite possible that this is because when I use script loading, generally speaking, I'm only loading the scripts I consider to be most critical for actual page load (not everything and the kitchen sink), so my script-based script loading during page-load usually is pretty darn quick. I defer the rest of my code that's not as critical until later (perhaps until when needed, strictly), which is something that markup alone doesn't let me do. If it's something likely to be used later you're better off loading it with the page. Waking up the radio on a mobile connection is slow and uses battery. Having said that, there's nothing in either of the original proposals that prevents adding scripts dynamically. It's the more complex option if you want more complex behaviour. The fact that browsers are trying to second guess developers and look-ahead to find and prioritize certain resources is NOT something I consider a positive benefit that I'm eager to assist. I still come from a world where a developer ought to get to decide what's higher priority. Browsers already do this to proven benefit, but download priority is outside the scope of this discussion. There's certainly a strong pre-disposition among a lot of developers to falling in love with declarative markup-only solutions. I share no such obsession, when it comes to script loading. I think script loading is far more complex than markup is ever going to be equipped to handle. To be clear, I will not be satisfied with a markup-only approach. No matter how complex it is, it does not handle all the use-cases I care about. Which of your use-cases have not been met? So far I've seen only I want X, Y, Z but not what you need X, Y, Z to achieve that isn't covered by other simpler proposals or existing features. I would be fine if we went with a variation of Nicholas' proposal. Let me state that new proposal here: … 2. `onpreload` event fired on any script which has `preload` attribute or property on it at the time its (pre)loading finishes (and execution is thus suppressed). Otherwise, not fired. What do you need to do that requires this event? I don't understand what this proposal has over Hixie's proposal other than proposed-by-Kyle :) It continues to be wrongly asserted that the current `onload` event on scripts is sufficient. It is not. It's a chicken-and-the-egg, because `onload` is fired strictly when scripts have loaded AND executed. We need an event to tell us when it's ONLY loaded but strictly HASN'T executed yet, which makes `onload` insufficient. For the rest of this discussion I need you to understand that saying We need x is not proof enough that we need x. Please explain why it's needed and how you would use it to do something that couldn't be done without it. script id=jquery src=jquery.js whenneeded/script script id=shims src=shims.js whenneeded/script script id=myscript src=myscript.js whenneeded/script script Promise.every( document.querySelector('#jquery').markNeeded(), document.querySelector('#shims').markNeeded() ).then(function() { document.querySelector('#myscript').markNeeded() }); /script The above doesn't need an extra event. In fact, your proposal doesn't need an extra event, I could remove the preload attribute and wait for onload, it doesn't matter if the script has been preloaded or not. Maybe I'm missing a use-case, but I need you to show what that is. It's quite clear and obvious how the `onpreload` event is useful to script-based loading. Don't tell us it's clear and obvious, just make it clear and obvious. Provide an example that requires it. Before we look closer at this load-but-don't-execute pattern we need a good reason. One that isn't already covered by the #1 idea in the first email + link[rel=subresource] + dynamic script adding. Given the above, is there a usecase that isn't catered for by dependencies and existing preloading features? Yeah, consider this scenario: I want to preload 1.js and 2.js, but I'm not sure right now if I'll execute 1.js, or 2.js, or both. The user
Re: [whatwg] Script preloading
On Wed, 10 Jul 2013 16:39:42 +0100, Kyle Simpson get...@gmail.com wrote: I personally don't care about scripts being discoverable by pre-parsers. [...] For instance, I've added like link rel=prefetch annotations for my scripts into the head of my document, and then done my normal script-based script loading as usual, and benchmarked if them being in the markup somehow magically sped up the page. I saw no appreciable increase in average page load speed in my testing. The result you've seen is expected, as pre-parser and link prefetching are different mechanisms. Prefetching of resources from rel=prefetch is only done after page completely finishes loading, so it won't affect loading time of page that contains it (it's for future navigation, like step1.html containing prefetch for step2.html). There's rel=subresource that's for immediate prefetching in the way you'd expect. You should see some improvement with it in cases where script loader makes it impossible for browser to start fetching scripts before the script loader is run: http://www.chromium.org/spdy/link-headers-and-server-hint/link-rel-subresource HTML pre-parser is basically equivalent of having rel=subresource for all script elements. -- regards, Kornel
Re: [whatwg] Script preloading
This is a good proposal and I'm hugely excited to see this getting more attention! Thanks so much for bringing it up again. There's one state that's not represented here which is download but do not run, an inactive flag, if you will. I know this is important is some situations where the overhead to compile code is potentially large...but it's an edge-case. markNeeded() might cover it. Regarding dependencies=...; have you considered a way to set up script groups instead of ID-based dependencies? E.g.: script group=core src=jquery.js async whenneeded/script script group=shims src=shims.js async whenneeded/script script id=myscript group=core shims src=myscript.js async whenneeded/script With the idea being that each item depends on other items in the specified group in document order. I'm not sure it's better, but it might enable less a-priori collaboration across large sets of dependent scripts. Also, have you talked at all with Yehuda, Dave, and Sam about how this might interact with ES6 Module Loaders? It might be worth a discussion just to see if there are any bits of common infrastructure that both designs can identify/re-use. They'll all bottom out at fetch() someplace, but understanding how they interact might be helpful. E.g., could I specify a named module loader for a script? That'd make transpilers infinitely more useful. Again, thanks for posting this. I'm incredibly excited about this design and would support it without changes. On Tue, Jul 9, 2013 at 8:39 PM, Ian Hickson i...@hixie.ch wrote: A topic that regularly comes up is script loading. I sent an e-mail responding to related feedback last year, though it didn't get any replies to the script loading parts of it: http://lists.w3.org/Archives/Public/public-whatwg-archive/2012Dec/0221.html It seems that people want something that: - Lets them download scripts but not execute them until needed. - Lets them have multiple interdependent scripts and have the browser manage their ordering. - Do all this without having to modify existing scripts. I must admit to not really understanding these requirements (script execution can be made more or less free if they are designed to just expose some functions, for example, and it's trivial to set up a script dependency mechanism for scripts to run each other in order, and there's no reason browsers can't parse scripts off the main thread, etc). But since everyone else seems to think these are issues, let's ignore that. The proposals I've seen so far for extending the spec's script preloading mechanisms fall into two categories: - provide some more control over the mechanisms already there, e.g. firing events at various times, adding attributes to make the script loading algorithm work differently, or adding methods to trigger particular parts of the algorithm under author control. - provide a layer above the current algorithm that provides strong semantics, but that doesn't have much impact on the loading algorithm itself. I'm very hesitant to do the first of these, because the algorithm is _so_ complicated that adding anything else to it is just going to result in bugs in browsers. There comes a point where an algorithm just becomes so hard to accurately test that it's a lost cause. The second seems more feasible, though. Would something like this, based on proposals from a variety of people in the past, work for your needs? 1. Add a dependencies attribute to script that can point to other scripts to indicate that execution of this script should be delayed until all other scripts that are (a) earlier in the tree order and (b) identified by this attribute have executed. script id=jquery src=jquery.js async/script script id=shims src=shims.js async/script script dependencies=shims jquery src=myscript.js async/script This would download jquery.js, shims.js, and myscript.js ASAP, without blocking anything else, and would then run jquery.js and shims.js ASAP, in any order, and then once both have executed, it would execute myscript.js. 2. Add an whenneeded boolean content attribute, a markNeeded() method, and an internal is-needed flag (initially false) to the script element. When a script is about to execute, if its whenneeded= attribute is set, but its is-needed flag is not, then delay execution. Calling markNeeded() on a script that has a whenneeded boolean but that has not executed yet first causes the markNeeded() method on all the script's dependencies to be called, and then causes this script to become ready to execute. script id=jquery src=jquery.js async whenneeded/script script id=shims src=shims.js async whenneeded/script script id=myscript dependencies=shims jquery src=myscript.js async whenneeded/script This would download jquery.js, shims.js, and myscript.js ASAP, and then wait
Re: [whatwg] Script preloading
Which of your use-cases have not been met? So far I've seen only I want X, Y, Z but not what you need X, Y, Z to achieve that isn't covered by other simpler proposals or existing features. You know, I keep relying on the fact that the body of work on this topic for almost 3 years ought NOT have to be re-visited every few months when these threads wake from dormancy. I keep hoping that someone who really cares about actually addressing all the concerns, and not just some of them, will do the due dilligence to look at all the previous stuff before criticizing me for not providing enough detail. I've written nearly a book's worth on this over all the threads and sites and blog posts over the years. In fact, I think its fair to say at this point that I've spent more time over the last 4+ years obsessing on script loading than any other developer, anywhere, ever. I don't like the implication that I'm apparently just an impetuous little child demanding my way with no reasoning. So, fine. Here it is. I'm going to state explicitly the use-cases I care about. This is nothing new. I am saying the same things I've been saying for 3 years. But sure, I'll say them, AGAIN, because now someone wants to hear them again. I doubt anyone is going to read this crazy long message and actually read all these, but I'll put them here nonetheless. And I'm listing them here because they are not covered fully by any of the other proposals besides the 2 or 3 I keep pushing for. You may think they are covered, but I think the nuances prove that they aren't. The devil is always in the details. Or you may think my use-cases are irrelevant and so you dismiss them as unimportant. Guess there's nothing I can do about that. - 1. Premise: I'm the author of a popular and wide-spread used script loader. It's a general utility that's used in tens of thousands of different sites, under a myriad of conditions and in different ways, and in a huge swath of different browsers and devices. I need the ability inside this general utility to do consistent, 100% reliable, predictable script loading for sites, without making ANY assumptions about the site/markup/environment itself. I need to be as unintrusive as possible. It needs to be totally agnostic to where it's used. 2. Premise: I need a solution for script (pre)loading that works not JUST in markup at page-load time, but in on-demand scenarios long after page-load, where markup is irrelevant. Markup-only solutions that ignore on-demand loading are insufficient, because I have cases where I load stuff on-demand. Lots of cases. Bookmarklets, third-party widgets, on-demand loading of heavy resources that I only want to pay the download penalty for if the user actually goes to a part of the page that needs it (like a tab set, for instance). In fact, most of the code I write ends up in the on-demand world. That's why I care so much about it. 3. Premise: this is NOT just about deferring parsing. Some people have argued that parsing is the expensive part. Maybe it is (on mobile), maybe not. Frankly, I don't care. What I care about is deferring EXECUTION, not parsing (parsing can happen after-preload or before-execution, or anywhere in between, matters not to me). Why? Because there's still lots of legacy content on the web that has side-effects when it runs. I need a way to prevent those side effects through my script loading, NOT just hoping someday they rewrite their code so that it has no side effects upon execution. NOTE: there ARE people who care about the expense of parsing. Gmail-mobile (at one point, anyway) was doing the /* here's my code */ comment-execute trick to defer parsing. So me not caring about it doesn't make it not an important use-case. Perhaps it IS something to consider. But it doesn't change any of my proposals or opinions -- it leaves the door open for the browser to decide when parsing is best. 4. Use-case: I am dynamically loading one of those social widgets that, upon load, automatically scans a page and renders social buttons. I need to be able to preload that script so it's ready to execute, but decide when I want it to run against the page. I don't want to wait for true on-demand loading, like when my user clicks a button, because of the loading delay that will be visible to the user, so I want to pre-load that script and have it waiting, ready at a moment's notice to say it's ok to execute, do it now! now! now!. There is not this script has loaded, so run the other one scenario here. It's some run-time environment condition, such as user-interaction, which needs to be the trigger. For instance, it might be when I finish using a templating engine client-side to render the markup that the social widget will search for and attach to. Or it might be like clicking to open a tab, which isn't rendered until made visible, and so we can't run the social widget code until that tab is rendered and
Re: [whatwg] Script preloading
Pre-parsers can kick in before a page is actually opened, but script cannot be executed. Let me dig up some numbers on the benefits of this report back. But logically, [parse html]-[load script] is always going to be faster than [parse html]-[parse inline script]-[execute inline script]-[load script]. And I imagine, more bytes and complex. That they *can* do that is not sufficient proof that in the real-world, it actually does speed up page loads. In my testing, the way I do script loading, annotating scripts in the markup and then doing my normal script loading did not, on average, provide any noticeable speed up. But anyway, this is a moot discussion, because I already conceded that if we want a solution that helps markup-only advocates, that's fine. script preload does that. Why are we going to keep arguing that point? No matter how that plays out, it doesn't change the fact that I need a solution which works for on-demand loading long after page-load, where what was or wasn't in the markup during that magical not rendered yet state is completely irrelevant. I feel like we're on a merry-go-round the last few years where someone says but, look, this is better in markup at page-load and then I say whatever, fine, but it doesn't help on-demand and then we go back around to no no, this is better for page-load. I don't consider this an either/or proposition. You have your thing you care about, I have my thing I care about. Both should be important. If it's something likely to be used later you're better off loading it with the page. Waking up the radio on a mobile connection is slow and uses battery. Having said that, there's nothing in either of the original proposals that prevents adding scripts dynamically. It's the more complex option if you want more complex behaviour. This is a big over-simplification of the scenarios involved. Sure, in general, you want to minimize waking the radio back up, but if there's 10% of script code I need to render the page initially, and 90% of my code is needed later (or maybe, conditionally, never at all), it's not supportable performance-wise to say well, just slow down the initial page render for that 90%. We have the techniques of post-loading and on-demand loading for a reason, and there are cases where you can prove, through testing, that doing dynamic loading after page-load is objectively better than slowing down the initial page load. Not only *can* you prove it, I have proven it on my own sites. Time and again. I'm sure there are ALSO cases where requesting everything at once is better. But there is no proof yet presented that always requesting everything all at once is always, unconditionally, the best option. If you have such evidence, and can prove that 100% of sites/apps which use on-demand loading are doing it wrong, please present that evidence. Short of that evidence, I live in a world that accepts that sometimes one is better, sometimes the other is better. And I want a solution that equally empowers both sides of the coin, not just one. - I'm going to stop this email here, and reply with another reply regarding your request for use-cases detail. That one is going to be QUITE long. --Kyle
Re: [whatwg] Script preloading
I'm supportive of this proposal, and I think it'd help declarative script loading. I've recently contemplated the slightly related issue of adding the media attribute to script, for declarative loading of scripts that are only relevant to some viewports [1] While it may complicate certain things (e.g. execution when media conditions change, dependencies), I believe it's worth while to give it some thought, as it'd enable preloaders to fetch these scripts as soon as possible, in case they are needed. Regarding Kyle's list of use-cases, I think it can be summed up to something like: Authors often need to load 3rd party scripts into their pages (e.g. ads, widgets, analytics). These scripts are out of their control, and often do not allow the hosting page to determine when they are executed. In many cases, either for performance (they trigger download of their own resources) or for UX purposes (they display something on the screen), authors need to control when these scripts are executed. IMO, the proposed whenneeded attribute can answer that need. rel=subresource can also answer it (assuming that browsers will optimize on it: download the resource, detect its type and parse it (as low priority) if needed, and keep it in memory regardless of its caching headers), but IMO whenneeded is cleaner. For the #11 use-case, where you want to delay the execution of some scripts until an entire group of scripts have finished downloading, but have yet to run, it could be done with: script id=A src=A.js dependencies=B C async whenneeded/script script id=B src=B.js async whenneeded/script script id=C src=C.js async whenneeded/script script var a=document.getElementById(A), b=document.getElementById(B), c=document.getElementById(C); a.markNeeded().then(function(){b.markNeeded()}).then({function(){c.markNeeded()}); /script That would work, as long as a dependency when the script we're dependent on is defined as whenneeded becomes dependency on its download, rather than its execution. Does that make sense? [1] http://lists.w3.org/Archives/Public/public-whatwg-archive/2013May/0112.html
Re: [whatwg] Script preloading
On 7/10/13 4:20 AM, Jake Archibald jaffathec...@gmail.com wrote: On 10 July 2013 11:31, Bruno Racineux br...@hexanet.net wrote: Anyway, as per your previous email I think we mostly agree that solution #1 is not very practical (or infeasible per your word) Given the suggestions I made to #1 in http://lists.whatwg.org/htdig.cgi/whatwg-whatwg.org/2013-July/039968.html, do you still think it's impractical (and why)? I think the very idea of having the concept of 'dependency' attributes and relying or asking to the browser to handle it through markup is misguided. This is somehow throwing the entire (or a portion of) dependency information of your platform, asking the browser to deal with it. I can already imagine bloated pages with an entire set of script markup, bigger than that of the page itself. That's not very good for performance. I think Kyle has given more than enough substantiated arguments in: http://lists.whatwg.org/htdig.cgi/whatwg-whatwg.org/2013-July/039981.html not to have me repeat them. I think that preloading without executing is really what we should are after. *hits usecase button* Why would you want to do that? Are those cases already (better) solved by link[rel=subresource] and dynamic script insertion? Again I'll differ to Kyle's extensive list for the use case. Modular approach, widgets, etc. As for link [rel=subresource] I am slightly unclear at to its full purpose really. Unless I am mistaken, (and if so correct me) it's a priority-prefetch. No a preload. While slightly useful. It doesn't really address, the pre-load that script and have it waiting, ready at a moment's notice to say it's ok to execute, do it now! now! now!. :) An alternative perhaps ignorant suggestion: Wouldn't a link[rel=preload] sending cookies would be simpler tool for basic script-preloading? In that I could dynamically insert a list of subresources to have them ready. Leaving the loading part to markup. And the request part to javascript. In order to address caching caveats (or possible lack of caching headers) that Kyle mentioned. rel=preload would guarantee a one time cache as well a pre-parsing the resource according, to its link 'type' if provided (i.e. css, js, etc). Now wether a HXR request from there has a cross-browser hurdle when the script is already in the cache is something I am not familiar with... And I am unfortunately very confused on the link[prerender] spec for scripts.
[whatwg] Script preloading
A topic that regularly comes up is script loading. I sent an e-mail responding to related feedback last year, though it didn't get any replies to the script loading parts of it: http://lists.w3.org/Archives/Public/public-whatwg-archive/2012Dec/0221.html It seems that people want something that: - Lets them download scripts but not execute them until needed. - Lets them have multiple interdependent scripts and have the browser manage their ordering. - Do all this without having to modify existing scripts. I must admit to not really understanding these requirements (script execution can be made more or less free if they are designed to just expose some functions, for example, and it's trivial to set up a script dependency mechanism for scripts to run each other in order, and there's no reason browsers can't parse scripts off the main thread, etc). But since everyone else seems to think these are issues, let's ignore that. The proposals I've seen so far for extending the spec's script preloading mechanisms fall into two categories: - provide some more control over the mechanisms already there, e.g. firing events at various times, adding attributes to make the script loading algorithm work differently, or adding methods to trigger particular parts of the algorithm under author control. - provide a layer above the current algorithm that provides strong semantics, but that doesn't have much impact on the loading algorithm itself. I'm very hesitant to do the first of these, because the algorithm is _so_ complicated that adding anything else to it is just going to result in bugs in browsers. There comes a point where an algorithm just becomes so hard to accurately test that it's a lost cause. The second seems more feasible, though. Would something like this, based on proposals from a variety of people in the past, work for your needs? 1. Add a dependencies attribute to script that can point to other scripts to indicate that execution of this script should be delayed until all other scripts that are (a) earlier in the tree order and (b) identified by this attribute have executed. script id=jquery src=jquery.js async/script script id=shims src=shims.js async/script script dependencies=shims jquery src=myscript.js async/script This would download jquery.js, shims.js, and myscript.js ASAP, without blocking anything else, and would then run jquery.js and shims.js ASAP, in any order, and then once both have executed, it would execute myscript.js. 2. Add an whenneeded boolean content attribute, a markNeeded() method, and an internal is-needed flag (initially false) to the script element. When a script is about to execute, if its whenneeded= attribute is set, but its is-needed flag is not, then delay execution. Calling markNeeded() on a script that has a whenneeded boolean but that has not executed yet first causes the markNeeded() method on all the script's dependencies to be called, and then causes this script to become ready to execute. script id=jquery src=jquery.js async whenneeded/script script id=shims src=shims.js async whenneeded/script script id=myscript dependencies=shims jquery src=myscript.js async whenneeded/script This would download jquery.js, shims.js, and myscript.js ASAP, and then wait for further instructions. document.getElementById('myscript').markNeeded(); This would then cause the scripts to execute, first jquery.js and shims.js (in any order), and then myscript.js. If any hadn't finished downloading yet, it would first wait for that to finish. (We could make markNeeded() return a promise, too.) Is there a need for delaying the download of a script as well? (If so, we could change whenneeded= to have values, like whenneeded=execute vs whenneeded=download or something.) Is there something this doesn't handle which it would need to handle? -- Ian Hickson U+1047E)\._.,--,'``.fL http://ln.hixie.ch/ U+263A/, _.. \ _\ ;`._ ,. Things that are impossible just take longer. `._.-(,_..'--(,_..'`-.;.'
Re: [whatwg] Script preloading
This is a long and complicated topic with lots of history. Please bear with the length of my reply. It seems that people want something that: - Lets them download scripts but not execute them until needed. - Lets them have multiple interdependent scripts and have the browser manage their ordering. - Do all this without having to modify existing scripts. I think it's important to note that the primary motivation here is performance. If all I cared about was serial loading (and the performance of that was irrelevant), I could, with today's mechanisms, load one script at a time, only when I was ready to execute it, and if there were multiple scripts, do so in the correct order. The fly in in the ointment is if I need to load multiple scripts at once, specifically if those come from different locations (one is jQuery from the CDN, another is a plugin from my server), and for performance reasons I want these scripts to load in parallel, but their execution order still matters. Now, if THAT was the only concern, the new (well, 2 years old now) `async=false` (or, as I call it, ordered async) mechanism would be enough. But it's not. Because there's only one ordered async queue, which means all such scripts have to go into the same bucket, and it's all or nothing for preserving execution order. What if I want to load jQuery, then I want (in ASAP order) for 4 independent plugins to run? Ordered async will run jQuery, then each plugin in request order, which might make one small plugin wait much longer than it needs to for an earlier plugin. Here, it's a performance issue because a plugin like a calendar widget might not appear and render as early as it could otherwise, because some other non-related plugin is coming from a slow location but was requested first. Very quickly, ordered async starts to not be sufficient for various use-cases. It's like the 75% solution, but the 25% are still a concern, performance wise. I must admit to not really understanding these requirements (script execution can be made more or less free if they are designed to just expose some functions, for example, and it's trivial to set up a script dependency mechanism for scripts to run each other in order, and there's no reason browsers can't parse scripts off the main thread, etc). But since everyone else seems to think these are issues, let's ignore that. In an ideal world, we could tell everyone hey, there's a new mandate, rewrite all your code by XYZ deadline. Kthxbai. That's not how it works. The fact is that the web platform and the browsers move MUCH quicker than legacy content. This is, and always has been, a question of if you think we should just wait around for years and years until every script we care about (but don't control since we didn't author it) gets rewritten, and while that's happening, web performance in this area just can't be addressed? I maintain still that we can and should fix the platform so we have more options than just tough luck. The proposals I've seen so far for extending the spec's script preloading mechanisms fall into two categories: - provide some more control over the mechanisms already there, e.g. firing events at various times, adding attributes to make the script loading algorithm work differently, or adding methods to trigger particular parts of the algorithm under author control. - provide a layer above the current algorithm that provides strong semantics, but that doesn't have much impact on the loading algorithm itself. I'm very hesitant to do the first of these, because the algorithm is _so_ complicated that adding anything else to it is just going to result in bugs in browsers. There comes a point where an algorithm just becomes so hard to accurately test that it's a lost cause. Can you please elaborate on how either of the two prominent proposals that Nicholas Zakas and I detailed years ago here are insufficient in that they fall into your first category? http://wiki.whatwg.org/wiki/Script_Execution_Control My proposal was to standardize what IE4-10 did, which is to start loading a script even if it's not in the DOM, but not execute it until it's in the DOM. Then, you monitor an event to know if one or more scripts have finished this preloading, and then you can decide if and when and in what order to add the corresponding script elements to the DOM to allow execution to proceed. The spec already suggests the core of this: For performance reasons, user agents may start fetching the script as soon as the attribute is set, instead, in the hope that the element will be inserted into the document. Either way, once the element is inserted into the document, the load must have started. If the UA performs such prefetching, but the element is never inserted in the document, or the src attribute is dynamically changed, then the user agent will not execute the script, and the fetching
Re: [whatwg] Script preloading
On 7/9/13, Ian Hickson i...@hixie.ch wrote: A topic that regularly comes up is script loading. Yes, for years it has come up. I jumped on the topic around 2009 here and on comp.lang.javascript to add the idea about chain of responsibility to this solution. The chain of responsibility pattern is not new, and some examples include FilterChain and in Apache ANT. The concept seems to apply well to this context. I sent an e-mail responding to related feedback last year, though it didn't get any replies to the script loading parts of it: http://lists.w3.org/Archives/Public/public-whatwg-archive/2012Dec/0221.html It seems that people want something that: - Lets them download scripts but not execute them until needed. - Lets them have multiple interdependent scripts and have the browser manage their ordering. - Do all this without having to modify existing scripts. I must admit to not really understanding these requirements (script execution can be made more or less free if they are designed to just expose some functions, for example, and it's trivial to set up a script dependency mechanism for scripts to run each other in order, and there's no reason browsers can't parse scripts off the main thread, etc). But That is a good point and it is a good approach. since everyone else seems to think these are issues, let's ignore that. The proposals I've seen so far for extending the spec's script preloading mechanisms fall into two categories: - provide some more control over the mechanisms already there, e.g. firing events at various times, adding attributes to make the script loading algorithm work differently, or adding methods to trigger particular parts of the algorithm under author control. - provide a layer above the current algorithm that provides strong semantics, but that doesn't have much impact on the loading algorithm itself. I'm very hesitant to do the first of these, because the algorithm is _so_ complicated that adding anything else to it is just going to result in bugs in browsers. There comes a point where an algorithm just becomes so hard to accurately test that it's a lost cause. The second seems more feasible, though. Would something like this, based on proposals from a variety of people in the past, work for your needs? 1. Add a dependencies attribute to script that can point to other scripts to indicate that execution of this script should be delayed until all other scripts that are (a) earlier in the tree order and (b) identified by this attribute have executed. script id=jquery src=jquery.js async/script script id=shims src=shims.js async/script script dependencies=shims jquery src=myscript.js async/script Why limit depends to be used by only scripts to refer only to other scripts? If you put link depends=idref on style then stylesheet evaluation could be deferred, too. I explained some cases about why this is desirable here: http://lists.whatwg.org/htdig.cgi/whatwg-whatwg.org/2009-February/018435.html The test cases I'd posted aren't live, but they did show some confusion at the time regarding load order of resources. Surety of misunderstanding seemed to be what caused the idea to be so offhandedly dismissed. This would download jquery.js, shims.js, and myscript.js ASAP, without blocking anything else, and would then run jquery.js and shims.js ASAP, in any order, and then once both have executed, it would execute myscript.js. 2. Add an whenneeded boolean content attribute, a markNeeded() method, A disabled/execute was mentioned here, before: http://lists.w3.org/Archives/Public/public-whatwg-archive/2013Apr/0158.html document.getElementById('myscript').markNeeded(); I'd rather call execute() than tell Mark he's needed. This would then cause the scripts to execute, first jquery.js and shims.js (in any order), and then myscript.js. If any hadn't finished downloading yet, it would first wait for that to finish. (We could make markNeeded() return a promise, too.) Or use a callback. Blocking on resource loading is bad. -- Garrett Twitter: @xkit personx.tumblr.com
Re: [whatwg] Script preloading
But I'd settle for anything, no matter how complex, as long as it actually solves the many use cases. Your proposed option has potential, as long as the missing event part is addressed. It seems to me that from an IE-perspective, the only missing piece is the event itself. Well, strictly speaking, IE4-10 had a suitable event already, as you surely know. Unfortunately, IE11 has, currently, removed those event handlings, as they are non-standard. I wrote this blog post a few days ago begging the IE11 team to bring them back: http://blog.getify.com/ie11-please-bring-real-script-preloading-back/ I know it was passed on to at least a few of the decision makers there, but I've not heard anything official in response yet. Any update? :) As it stands, the IE version of real preloading is in limbo and in danger of dying, as it's quite neutered without some event. IF we could act quickly enough to standardize some preloading approach, even if that were different than how IE did it before, *maybe* it could make it into IE11 before final release? I dunno. Just one final side note on the above linked-to proposals (Zakas's and mine). Over 2 years ago, I implemented feature-detects in LABjs script loader for both of those proposals. Of course, the `readyState` one actually works in IE4-10 and works beautifully I might add. In head-to-head loading tests I've done from time to time, the IE real preloading mechanism often beats out the good-but-not-great ordered async of the other modern browsers. The `preload` one doesn't currently work of course (it's just dormant code for now), but I thought it to be a sufficiently good enough proposal, and likely enough to eventually happen, that I put in those few lines of code to LABjs, as speculative future-proofing. The LABjs source code uses a feature-detect for the real preloading by looking for the existence of the preload Boolean DOM attribute. After thinking about it for a bit, I'm not sure I understand why that attribute is necessary. I believe the reason that Nicholas suggested that the attribute needed to be there was two-fold: 1) he was concerned about the implicit nature of IE's behavior by sort of indirectly preloading simply by developer non-action (not inserting into the DOM). Adding a positive attribute to a tag to say yes, I want this preload-and-defer-execution behavior was certainly more explicit, and opt-in, and thus maybe more attractive, since it had perhaps less potential to create accidental problems for legacy content or developer ignorance. 2) it makes for a simple/effective feature-detect. :) Whatever mechanism we do have, we need a feature detect for it, obviously. `preload in document.createElement(script)` is nice and clean and semantic. The IE way, I detect by looking at the readyState and noticing its initial value, which was an IE only behavior. Opera was the only other browser to support `script.readyState` (but NOT support the actual preloading concept), but Opera's version of the property has a different initial value. I asked an Opera developer specifically and he asserted that Opera would not ever have an occasion to change that initial value to the same as IE's unless they were also matching IE's preloading behavior. Thus, we avoided (tenuously, in the absence of standards) any false-positives on that feature detect. If I were to only introduce the event handler (onpreload) it seems to address the use cases, but then your 2+ year old dormant code would stay dormant :( I'm not nearly as concerned about dormant code staying dormant forever. I made the judgement call back then that the extra ~100 gzip-bytes were worth it if a future day ever came that it just magically worked. I'd love it, for LABjs' sake, if whatever was standardized was one of the two approaches, either one. But even if we standardized a third option, and I had to change LABjs, that would be FAR BETTER in my mind than never addressing this use case at all, especially in light of IE11 sort of retreating on this topic (either intentionally or not). --Kyle
Re: [whatwg] Script preloading
I just joined the list and glad this subject is brought up. I have been wrestling pretty hard with script loading issues lately. I'd say that having the browser manage script interdependency is probably a bad and cumbersome way to solve these issues. I'll try to explain, talk about the defer approach, as well as critical IE bugs that relate to this very subject. I think one of the reason that people may ask for this Interdependency feature, is due to the weakness of the platform they use, its plugins or the poor management of such script (with often poorly conceived plugins not takign dependency into account), which too often has the approach of loading all scripts at all times regardless of the page context. What's important to keep in mind, is that if you must have the browser managing the interdependency, by association, you also have to manage it at the app/platform level properly in the first place. Which seems awfully redundant... And would probably lead to more page bloat or bad programming habits. As Kyle Simpson said, the primary motivation here is performance. Putting scripts at the bottom, while preserving the scripts order has performance drawbacks. And 'async', while good for independent scripts such as social media apis, is not really a good tools for dependency management. My main issue against using external script loaders like LABjs and others, has always been that if the browser must download a script first, before starting to download the dependencies. It presents a drawback already, for delayed the scripts by the script loader's latency and download time (at least for the first uncached page load) similarly to having scripts at the bottoms. What we truly want is keep the order while loading script in a non-blocking way. Why not simply load all such scripts early in the head with 'defer', which preserves the dependency order as determined by your app. Using 'defer' in head scripts is actually a very good way to preserve script order with non-blocking scripts. And by loading the scripts very early in the head, the possibility of a incurred significant delay of DOMContentLoaded, for an eventual large script not yet downloaded, is minimal to none. In that sense, I think that too much focus has been placed on 'async', with 'defer' having been extremely overlooked as such an adequate method to non-blocking script loading with dependencies preserved. 'defer' after all, is partly designed to guarantees that scripts execute in the order they were specified and be delayed until document.readyState = interactive; I sadly know there is a big hurdle for using 'defer' right now with interdependencies, mainly with this IE9 bug http://bugs.jquery.com/ticket/11310 Debunked in further details here (coincidentally, in part by Kyle Simpson): https://github.com/h5bp/lazyweb-requests/issues/42 And may I get into further IE hate when it comes to the 'interactive' state inconsistencies, by pointing to this very recent bug report I've had to file: https://connect.microsoft.com/IE/feedback/details/792880/document-readystat e-interactive-firing-too-early-misfiring-in-ie11-9-and-10 Or should I beg the question, as to why it took my initiative yesterday after almost a year of the problem being reported by others on github in multiple occasions, to have this looked at so that IE11's final release get it right, or not, who knows... This problem exist since IE7! Is that really the best Microsoft can do? There is something really wrong with the fixing process here. That, or too big of a disconnect between those who test and those who are supposed to fix things. Or it is that developers are too fed up with those bugs, having to find ways around them, to find the energy to report them appropriately? Thankfully, the IE7-9 'defer' bug is has been fixed in IE10. Yet it's likely postponing proper use of 'defer' for another what? 5 years?. Thanks to Microsoft once again for holding the internet back and make our life harder? Is that all we can come up with? I would actually advocate to petition Microsoft to release patches for IE8, IE9 and IE10 for these particular stupid overlooked bugs, which some days honestly make me want to kill myself. I understand that in some areas, older browsers cannot add or remove features to the same major release for good reasons. But it's a real problem if bugs of this kind ( which wouldn't break any site if fixed now), cannot be fixed on older browsers using regular Windows updates. The idea that a browser is set in stone on release, and cannot be touched become a real issue to progress. Aren't those two particular bugs good example of thing that should be fixed and applied along security patches? And not have to wait 5 to 10 years coping with buggy browsers for no good reasons I can think of. I would also strongly favor restoring the previous spec portion of 'defer' which allow to have defer on inline script blocks (i.e. if the src attribute is not present). I don't know
Re: [whatwg] Script preloading
I have been wrestling pretty hard with script loading issues lately. I'd say that having the browser manage script interdependency is probably a bad and cumbersome way to solve these issues. What do you mean by having the browser manage script interdependency? As far as I am aware, this thread and these feature requests are not about the browser managing script interdependencies… in fact, quite the opposite. What we're asking and hoping for is a facility that allows the app code to manage the dependencies and the loading order, while only relying on the browser to do the actual loading for us the way it always has. The only part of that puzzle that's missing is a way to tell the browser to pause between finishing-loading and starting-executing. Asking for such a mechanism has really nothing to do with offloading dependency management to the browser to handle. It's empowering the app code to be more in control, not less. I think one of the reason that people may ask for this Interdependency feature, is due to the weakness of the platform they use, Again, I think you may possibly be misunderstanding the goal of what's being asked for. But I'll agree with you that there's a weakness. The weakness, IMO, is in the web platform itself, in not giving us more fine-grained control over script loading. That is why we keep having this discussion every 6 months or so for the least several years. The use-cases never go away, and the hacks we use to deal with them never get any less ugly. And 'async', while good for independent scripts such as social media apis, is not really a good tools for dependency management. Again, possibly a case of misunderstanding or missed context from previous conversations. When I bring up async, I'm not talking about script async in markup as you suggest, but actually `script.async = false` being set on dynamcially created script elements (in code). async=false (aka ordered async) is a relatively new feature added to the platform about 2.5 years ago that gives us async parallel loading, but the browser automatically enforces execution order to be request order, instead of ASAP order. async=false is actually a good feature. The problem is not the feature itself, but that it's only part of what we needed. My main issue against using external script loaders like LABjs and others, has always been that if the browser must download a script first, before starting to download the dependencies. It presents a drawback already, for delayed the scripts by the script loader's latency and download time (at least for the first uncached page load) similarly to having scripts at the bottoms. For LABjs' part, I never suggest to people to load LABjs in a separate file. I suggest that people use a bootstrap type code file, which would be a single .js file they load with a single script tag in their markup, and it contains all the bare-minimum code necessary to bootstrap the page/app. It would include the code for LABjs, also the $LAB chains for loading other scripts, even basic event handling or other bootstrap type logic. Moreover, the extra ~2k of gzip-bytes that LABjs costs (even if it's a separate file, but especially if it's included in another bootstrap file) is almost always made up for in savings by being able to take advantage of consistent parallel loading of scripts. If your page only has 3-5k of JS on it, then you shouldn't use a script loader. But if you're like most sites, and you're loading 100-300k of JS, then a tiny 2k of JS for loading optimization is not even a drop in the ocean. Lastly, I advocate the techniques of deferring certain parts of your scripts to not loading during page-load at all, but instead post-loading or on-demand loading at later times. This amounts to needing to have the ability to do dynamic loading during the lifetime of the page. Markup alone is never enough for that. You have to have a script loader of some sort. So, I advocate that a tiny but powerful script loader that you use for BOTH uses is a win. You use the same script loading techniques for page-load loading as you do for on-demand loading. Consistency of toolset here makes coding and maintenance easier in the long run. Why not simply load all such scripts early in the head with 'defer', As you mention below, defer is horribly buggy and unreliable. The chances of IE8+ (not to mention IE6-8) being patched to have better defer are roundable to zero. 'defer' in head scripts is actually a very good way to preserve script order with non-blocking scripts. But it only works for external scripts (as you note below), and it only works for markup loading during page-load, and gives no answer for dynamic/on-demand loading later. As such, by design, it's insufficient for the use-cases presented. I would actually advocate to petition Microsoft to release patches for IE8, IE9 and IE10 for these particular stupid overlooked bugs