Re: [whatwg] Preloading and deferred loading of scripts and other resources
On Tue, Oct 7, 2014 at 6:50 PM, Ilya Grigorik igrigo...@gmail.com wrote: On Thu, Sep 11, 2014 at 7:55 PM, Ryosuke Niwa rn...@apple.com wrote: On Sep 8, 2014, at 10:54 PM, Ilya Grigorik igrigo...@gmail.com wrote: On Mon, Sep 8, 2014 at 7:59 PM, Ian Hickson i...@hixie.ch wrote: The platform is missing a lower-level primitive (declarative and imperative) that is able to explain resource loading with the same expressive power as requests initiated by the browser itself. That isn't a problem. I don't follow. To me that *is* the core problem that we should solve first and ship as soon as possible: if we keep the surface area low, we can ship it quickly and let developers experiment and move the platform forward. Adding more layers of higher-level APIs only slows the deployment process. What problem(s) are those developers going to solve with such a low level API other than the use cases A through Z listed here? Responding to Ryosuke (I wasn't on the list then), a low level API is exactly what's missing. IMO, the idea that browsers should provide convenient, high-level, spot solutions to some common problems is flawed. Instead, the browser should expose the lowest-level, most-capable APIs and let libraries sort out the convenience and common idioms. It's less work for browser vendors and empowers library authors and the developer community. I want to be able to fill a page with a thousand img tags and specify that they download in order of distance from the viewport. I want to be able to set priorities of XMLHttpRequests. I want to be able to set XHR priorities relative to image loads (that actually came up _today_ in profiling our application). I want to be able to deprioritize arbitrary resources after first paint. I want to adjust priorities as the application is being used. In short, I agree 100% with Ilya: Instead of hypothesizing about use cases, the web is better-served by exposing the primitive features of the web platform, which lets library authors and web developers decide for themselves how to take advantage of them. Cheers, Chad -- Chad Austin Technical Director, IMVU http://chadaustin.me
Re: [whatwg] Preloading and deferred loading of scripts and other resources
On Thu, Sep 11, 2014 at 7:55 PM, Ryosuke Niwa rn...@apple.com wrote: On Sep 8, 2014, at 10:54 PM, Ilya Grigorik igrigo...@gmail.com wrote: On Mon, Sep 8, 2014 at 7:59 PM, Ian Hickson i...@hixie.ch wrote: The platform is missing a lower-level primitive (declarative and imperative) that is able to explain resource loading with the same expressive power as requests initiated by the browser itself. That isn't a problem. I don't follow. To me that *is* the core problem that we should solve first and ship as soon as possible: if we keep the surface area low, we can ship it quickly and let developers experiment and move the platform forward. Adding more layers of higher-level APIs only slows the deployment process. What problem(s) are those developers going to solve with such a low level API other than the use cases A through Z listed here? For one, its restricted to script, link, style, video, img, object, iframe, audio. My app is fetching JSON blobs to construct the DOM: there is no way for me to upgrade a JSON fetch to high priority (XHR is low priority compared to other elements and requires JS execution); there is no way for me get the preloader to initiate this fetch. Replace JSON blob with texture pack for a WebGL app, fancy delta-diff format applicable to my content, or any other format. To be clear, this is not an argument against providing needs and load-policy. I'm just pointing out that we (a) need a generic, declarative fetch (rel=preload) mechanism that is content-type agnostic and is able to express all the necessary transport options (transport priority, transport dependencies, etc), and (b) this mechanism should not be coupled to other primitives that are being proposed here. (I think we're in agreement here, just repeating as a sanity check) To be clear, I'm not against the core premise of unifying various import mechanisms, but to me that's a secondary goal -- good housekeeping, but not the problem that the actual web developers (not implementers) are actually up against today. And, at least personally, I think we should prioritize developer needs over implementers. That said, I don't think we're actually that far apart… What are problems Web developers actually up against today? Not having a low-level network API, on its own, isn’t a problem. Please give us a concrete real world use case for which the proposed API doesn’t work. Any sufficiently large web application has at least one perf-crippled attempt at a smarter resource loader. All of them start with good intentions and sound observation that browser defaults are sometimes at odds with app priorities, and all of them end up realizing that (a) XHR is only reasonable game in town, (b) XHR does not expose the necessary fetch primitives (prioritization being the biggest one), and (c) XHR hurts their on first-load performance due to loss of preloader processing. Browsers fall into similar traps. Our (Chrome) experience with rel=subresource is a good illustration: https://code.google.com/p/chromium/issues/detail?id=312327 - simple on the surface, and hard to get right in practice. A longer rant on related topic(s): https://www.igvita.com/2014/10/02/extensible-web-resource-loading-manifesto/ On Sep 13, 2014, at 2:02 PM, Ryosuke Niwa rn...@apple.com wrote: On Sep 8, 2014, at 1:33 PM, Ian Hickson i...@hixie.ch wrote: I haven't discussed in detail with my colleagues but my impression is that we're quite concerned about the number of load policy options and the complexity they introduce. I'm not certain if there is a value in having a load policy for fetch when needed since that could be achieved by inserting an script/style/etc... element when needed. Are there any use cases for having script/style/etc... elements that before they start fetching respective sub resources? Agreed. Also, we tried to define a similar concept (postpone) in Resource Priorities [1], but that didn't get far because when needed is app specific. Further, even definitions like when it comes into viewport were contentious because they are not universal best practices - e.g. you probably want to initiate fetches well before an asset comes into a viewport to have it ready ahead of time (e.g. app should start prefetching resources when said resources are X screens away); lazy fetching can be an anti-pattern on mobile (energy use concerns: we want apps to prefetch and bundle requests); and so on. [1] https://dvcs.w3.org/hg/webperf/raw-file/tip/specs/ResourcePriorities/Overview.html It also appears that apply when needed can also be achieved by inserting link[rel=preload] first and later inserting an element of the appreciate type since the resource would have been cached by the browser at that point in practice. Agreed. However, note that there are some caching/matching gotchas that need to be considered here: http://w3c.github.io/resource-hints/#matching-hint-responses-with-requests
Re: [whatwg] Preloading and deferred loading of scripts and other resources
On 8/23/14, Kyle Simpson get...@gmail.com wrote: Surely our goal should be to make script loaders unnecessary. Complexity is best avoided, sure. There's unquestionably a lot of folks on this thread for whom that is their main concern. I think it's a mistake to assume that because they mostly seem to be working as browser developers (which strongly influences their perspective, I believe) that this is a universal goal. OK. 1. A hand-authorable markup only (aka zero script loaders) approach is, and always will be, limited. Limited to what? To the initial page load. I'm not really interested in arguing the validity of that premise that one way or the other. 2. There is, intuitively, some threshold of complexity of markup beyond which most hand-authors will not go. Lets not make the advertisement against the `needs` attribute proposal. And to be fair, that is really my 2009 depends Chain of Responsibility proposal, renamed. They may author: script src=http://some.url.1; async id=s1 script src=http://some.url.2; async needs=s1 That accomplishes powerful things simply. Should be useful with HTML imports:-- link rel=import href=footer.html id=footer-import async script src=footer.js needs=footer-import async Load the footer html and js, don't block, but make sure that the HTML is loaded before the script. No matter how good we are at inventing a markup syntax that handles all the script loading use-cases, only a simple subset of that will ever be hand-authored. The rest? YOU GUESSED IT!!! Will be handled by a script loader. And by that, I don't just mean a script in the runtime, I mean some tool in the build process on the server that's generating markup that has to go through some manifest of dependencies and construct a tree and figure out all that interconnected markup and inject it. Popular and ever burgeoning libraries that use script loaders. Markup solutions (for the simple cases), and script loaders (for the more complicated markup page-load AND for the on-demand script loading during page lifetime), must exist, if we're really going to handle everyone's script loading needs. We can't just favor one and forget the other. OK. I dislike all the current markup-centric approaches because they do just that. And it's all summed up by the quote that I vehemently disagree with: Surely our goal should be to make script loaders unnecessary. What if the goal is to simplify dependency loading using declarative-based chain-of-responsibility pattern for common cases? It realize you don't like it. But if you think about it, goals to make things unnecessary aren't necessarily wrong, even if the thing to be made unnecessary is still, in some cases, needed. Particularly if the thing to be aimed toward obsolescence is in someways costly or detrimental. -- Garrett @xkit ChordCycles.com garretts.github.io
Re: [whatwg] Preloading and deferred loading of scripts and other resources
Different aspects of priority are expressed in some of Ian’s loadpolicy attributes (block, async, optimistic, low-priority). Currently web browsers use the type of loadable element to determine priority. In Ilya’s proposal this can be found in the “as” attribute in the case of LINK rel=preload. While it’s not ideal, this approach at least allows us to get agreement on preload without having to get agreement on a new comprehensive spec on request prioritization. I’m just agreeing that the current preload spec seems like a good first step and we should go ahead with it once issues are resolved if we can get agreement from implementors. Thanks, Peter On Sep 13, 2014, at 2:02 PM, Ryosuke Niwa rn...@apple.com wrote: On Sep 8, 2014, at 1:33 PM, Ian Hickson i...@hixie.ch wrote: I got some feedback on my last e-mail to the effect that having the proposal sandwiched between the rationale and the examples of how it would be used made it hard to find, so I'm reproducing the proposal here (slightly updated based on feedback): --- These loadable elements: script, link, style, video, img, object, iframe, audio ...get the following new attributes: needs= Gives a list of IDs of other elements that this one needs, known as The Dependencies. Each dependency is added to this element's [[Dependencies]] in the ES6 loader. loadpolicy= The load policy. Consists of a space-separated set of keywords, of which one may be from the following list: block, async, optimistic, when-needed, late-run, declare. The other allowed keywords are precache, low-priority, and force. (Maybe we disallow block and force since they're for legacy only.) Different elements have different defaults. precache isn't allowed if the keywords block or async are specified, since those always load immediately. The keywords' meanings are as follows: block - stop parsing until this resource is applied async - fetch now, apply asap optimistic - fetch when needed, apply asap when-needed - fetch when needed, apply when needed declare - fetch when needed, don't apply precache - for fetch with needed, consider fetching earlier low-priority - let other things go first force - always fetch anew, don't de-dupe I haven't discussed in detail with my colleagues but my impression is that we're quite concerned about the number of load policy options and the complexity they introduce. I'm not certain if there is a value in having a load policy for fetch when needed since that could be achieved by inserting an script/style/etc... element when needed. Are there any use cases for having script/style/etc... elements that before they start fetching respective sub resources? It also appears that apply when needed can also be achieved by inserting link[rel=preload] first and later inserting an element of the appreciate type since the resource would have been cached by the browser at that point in practice. If we wanted to make that explicit, we could add a method like loadFromPreload to script and syle elements and have it take link[rel=reload]. These two changes should dramatically reduce the number of load policies we need. - R. Niwa
Re: [whatwg] Preloading and deferred loading of scripts and other resources
On Sep 8, 2014, at 1:33 PM, Ian Hickson i...@hixie.ch wrote: I got some feedback on my last e-mail to the effect that having the proposal sandwiched between the rationale and the examples of how it would be used made it hard to find, so I'm reproducing the proposal here (slightly updated based on feedback): --- These loadable elements: script, link, style, video, img, object, iframe, audio ...get the following new attributes: needs= Gives a list of IDs of other elements that this one needs, known as The Dependencies. Each dependency is added to this element's [[Dependencies]] in the ES6 loader. loadpolicy= The load policy. Consists of a space-separated set of keywords, of which one may be from the following list: block, async, optimistic, when-needed, late-run, declare. The other allowed keywords are precache, low-priority, and force. (Maybe we disallow block and force since they're for legacy only.) Different elements have different defaults. precache isn't allowed if the keywords block or async are specified, since those always load immediately. The keywords' meanings are as follows: block - stop parsing until this resource is applied async - fetch now, apply asap optimistic - fetch when needed, apply asap when-needed - fetch when needed, apply when needed declare - fetch when needed, don't apply precache - for fetch with needed, consider fetching earlier low-priority - let other things go first force - always fetch anew, don't de-dupe I haven't discussed in detail with my colleagues but my impression is that we're quite concerned about the number of load policy options and the complexity they introduce. I'm not certain if there is a value in having a load policy for fetch when needed since that could be achieved by inserting an script/style/etc... element when needed. Are there any use cases for having script/style/etc... elements that before they start fetching respective sub resources? It also appears that apply when needed can also be achieved by inserting link[rel=preload] first and later inserting an element of the appreciate type since the resource would have been cached by the browser at that point in practice. If we wanted to make that explicit, we could add a method like loadFromPreload to script and syle elements and have it take link[rel=reload]. These two changes should dramatically reduce the number of load policies we need. - R. Niwa
Re: [whatwg] Preloading and deferred loading of scripts and other resources
On Sep 8, 2014, at 10:54 PM, Ilya Grigorik igrigo...@gmail.com wrote: On Mon, Sep 8, 2014 at 7:59 PM, Ian Hickson i...@hixie.ch wrote: The platform is missing a lower-level primitive (declarative and imperative) that is able to explain resource loading with the same expressive power as requests initiated by the browser itself. That isn't a problem. I don't follow. To me that *is* the core problem that we should solve first and ship as soon as possible: if we keep the surface area low, we can ship it quickly and let developers experiment and move the platform forward. Adding more layers of higher-level APIs only slows the deployment process. What problem(s) are those developers going to solve with such a low level API other than the use cases A through Z listed here? To be clear, I'm not against the core premise of unifying various import mechanisms, but to me that's a secondary goal -- good housekeeping, but not the problem that the actual web developers (not implementers) are actually up against today. And, at least personally, I think we should prioritize developer needs over implementers. That said, I don't think we're actually that far apart… What are problems Web developers actually up against today? Not having a low-level network API, on its own, isn’t a problem. Please give us a concrete real world use case for which the proposed API doesn’t work. and it also hides requests from the preload scanner, which is a deal-break for performance. That's why the proposal in this thread uses the existing import mechanisms to define how the dependencies. But restricts it to a subset of resource types. Granted, this is not an issue if you give me a generic way to load any resource, ala rel=preload. Right. (2) We also need a declarative, content-type agnostic primitive to express resource loads, such that the preload scanner is able to pickup and processes these fetches on par with all other resources -- hence my rel=preload suggestion. I don't disagree that we need a way to declarative way to import non-browser-native resources (like some text file the script uses for storing game level data or something). But I don't think we need a redundant mechanism to import resource types that already have existing import mechanisms. That's not a primitive, it's just a redundant mechanism. I went into more detail on this very topic, considering a wide array of options, in the big e-mail I sent recently: http://lists.w3.org/Archives/Public/public-whatwg-archive/2014Aug/0177.html It's only redundant insofar as XHR is a redundant mechanism for loading arbitrary resources. There are cases where fetching an image / stylesheet / etc, via XHR is both a reasonable and a required step - {pre,post}processing, and so on. Moving forward, I think the intent is to explain resource loading via Fetch. I'm asking for a declarative Fetch that's preloader friendly and has the same expressive capabilities. I think rel=preload gives us a declarative preloader friendly syntax for Fetch. Note that I'm looking for declarative syntax that allows me to set arbitrary fetch priorities - e.g. upgrade my JSON payload to high priority because I need it to render content on the screen. This is the part that we *need* to solve. rel=preload with the proposal on this thread handles this fine, as far as I can tell. Yes, I think it's close! A few considerations to account for in the processing model, based on real-world use cases and feedback from the webperf group: - https://igrigorik.github.io/resource-hints/#preload - *https://igrigorik.github.io/resource-hints/#processing https://igrigorik.github.io/resource-hints/#processing* All I'm arguing for here is that the MVP for giving web developers the power to start solving these problems is rel=preload. Everything else is a nice to have. As a result, I'd love to uncouple rel=preload from the rest... Once/if the other mechanisms are ready, rel=preload would just inherit them as part of coverage of link. As I said earlier, I don't think we're that far apart. Which values of loadpolicy content attribute are you proposing to support? - R. Niwa
Re: [whatwg] Preloading and deferred loading of scripts and other resources
I got some feedback on my last e-mail to the effect that having the proposal sandwiched between the rationale and the examples of how it would be used made it hard to find, so I'm reproducing the proposal here (slightly updated based on feedback): --- These loadable elements: script, link, style, video, img, object, iframe, audio ...get the following new attributes: needs= Gives a list of IDs of other elements that this one needs, known as The Dependencies. Each dependency is added to this element's [[Dependencies]] in the ES6 loader. loadpolicy= The load policy. Consists of a space-separated set of keywords, of which one may be from the following list: block, async, optimistic, when-needed, late-run, declare. The other allowed keywords are precache, low-priority, and force. (Maybe we disallow block and force since they're for legacy only.) Different elements have different defaults. precache isn't allowed if the keywords block or async are specified, since those always load immediately. The keywords' meanings are as follows: block - stop parsing until this resource is applied async - fetch now, apply asap optimistic - fetch when needed, apply asap when-needed - fetch when needed, apply when needed declare - fetch when needed, don't apply precache - for fetch with needed, consider fetching earlier low-priority - let other things go first force - always fetch anew, don't de-dupe loadsettings= A JSON-encoded dictionary to pass to the Request constructor. (Or some other syntax. Proposals welcome. JSON isn't great in an attribute.) ...and API: .addDependency() Passed a promise, makes this element depend on that promise. Passed a loadable element, does the same as if that element's ID was mentioned in needs=. .load() Mark the element as needed, and apply or execute it as soon as possible. Returns the new .loaded promise (any earlier one is rejected). .readyPromise indicating calling load() will immediately apply or execute when load() is called. .loaded Promise indicating that the element has applied or executed. .request The current Request object, if a fetch has been started. .needsreflects needs, maybe as a custom object, or otherwise as a DOMTokenList .loadPolicy reflects load-policy, maybe as a custom object, or otherwise as a DOMTokenList .loadSettings reflects load-settings, maybe as a custom object These elements can be in six states. The first five are sequential; elements try to go through them in turn: - idle (the initial state at creation time) - prefetching... - ready (matches the .ready promise) - loading... - loaded (matches the .loaded promise) ...and the sixth is error, meaning something failed permanently. Setting src=, or whatever causes the element's state to be reset, immediately rejects the preexisting .loaded promise and creates a new one, moving the element back to idle. When an element is created, it's added to the ES6 module registry. (When one of these elements has its ID or URL changed, its entries in the registry are updated.) The ES6 LoadModule() operation is called for this module (that's how it is added to the registry). Except if the load policy has the force flag, when the element is added to the registry it's done in such a way as to rely on ES6 deduping. An element can be needed. By default it's not, unless it has a loadpolicy of block or async. Upon creation, and when its needs= is changed while the element is still not ready, or when another element's ID is changed and that matches an ID in an element's needs=, the element's [[Dependencies]] list is updated accordingly. When an element is marked as needed, all the things in its [[Dependencies]] get marked as needed also. An element in idle moves to prefetching if the loadpolicy is optimistic and the browser has nothing better to do, or the loadpolicy has precache declared and the browser has nothing to do, or the element is marked as needed somehow. An element's fetch hook blocks until the element reaches prefetching. Once it does, if this is
Re: [whatwg] Preloading and deferred loading of scripts and other resources
On Mon, Sep 8, 2014 at 1:33 PM, Ian Hickson i...@hixie.ch wrote: I really like your proposal for as=... Concretely it could look something like this: link rel=preload href=/some/asset.css as=stylesheet(used to initialize default priority, headers, etc) load-settings={} (JSON payload with custom headers, priority [2], etc) media= ... (relevant media queries..) probability=([0.0-1.0] used for speculative fetches [3]) I don't understand why this would be better than: link rel=stylesheet loadpolicy=declare href=/some/asset.ass loadsettings=... media=... Better or worse is not the point. I think the current proposal fails to address the larger underlying problem. The platform is missing a lower-level primitive (declarative and imperative) that is able to explain resource loading with the same expressive power as requests initiated by the browser itself. XHR provides arbitrary resource loading, but it lacks the power to express transport-layer options such as relative request priority and dependencies, and it also hides requests from the preload scanner, which is a deal-break for performance. To address this, we need two things: (1) Fetch API with load-settings addresses the imperative side of the problem. (2) We also need a declarative, content-type agnostic primitive to express resource loads, such that the preload scanner is able to pickup and processes these fetches on par with all other resources -- hence my rel=preload suggestion [1]. We can augment img, script, and other elements, with load-settings and other flags, but that still doesn't cover all the necessary cases. For example, how do I fetch a font file, or an arbitrary JSON payload with app-data, etc? Note that I'm looking for declarative syntax that allows me to set arbitrary fetch priorities - e.g. upgrade my JSON payload to high priority because I need it to render content on the screen. This is the part that we *need* to solve. Once we have the low-level declarative+imperative primitives for loading resources, we can build up all other loading and dependency patterns in app-space. The loadpolicy/needs attributes are syntax sugar for select resource types -- nice, but (IMO) not strictly necessary and not sufficient for the more general case of content-types not covered by dedicated elements. ig [1] https://igrigorik.github.io/resource-hints/#preload
Re: [whatwg] Preloading and deferred loading of scripts and other resources
On Mon, 8 Sep 2014, Ilya Grigorik wrote: Better or worse is not the point. I think the current proposal fails to address the larger underlying problem. If it did, then that would be worse. The platform is missing a lower-level primitive (declarative and imperative) that is able to explain resource loading with the same expressive power as requests initiated by the browser itself. That isn't a problem. XHR provides arbitrary resource loading, but it lacks the power to express transport-layer options such as relative request priority That is fixed by exposing Request initialisation flags on XHR. and dependencies, That's fixed by using the proposal in this thread. and it also hides requests from the preload scanner, which is a deal-break for performance. That's why the proposal in this thread uses the existing import mechanisms to define how the dependencies. (2) We also need a declarative, content-type agnostic primitive to express resource loads, such that the preload scanner is able to pickup and processes these fetches on par with all other resources -- hence my rel=preload suggestion. I don't disagree that we need a way to declarative way to import non-browser-native resources (like some text file the script uses for storing game level data or something). But I don't think we need a redundant mechanism to import resource types that already have existing import mechanisms. That's not a primitive, it's just a redundant mechanism. I went into more detail on this very topic, considering a wide array of options, in the big e-mail I sent recently: http://lists.w3.org/Archives/Public/public-whatwg-archive/2014Aug/0177.html We can augment img, script, and other elements, with load-settings and other flags, but that still doesn't cover all the necessary cases. For example, how do I fetch a font file http://dev.w3.org/csswg/css-font-loading/ ...which presumably would have loadSettings exposed. or an arbitrary JSON payload with app-data, etc? XHR, or link rel=preload. I assume you're not expecting us to preparse the JSON file. Note that I'm looking for declarative syntax that allows me to set arbitrary fetch priorities - e.g. upgrade my JSON payload to high priority because I need it to render content on the screen. This is the part that we *need* to solve. rel=preload with the proposal on this thread handles this fine, as far as I can tell. Once we have the low-level declarative+imperative primitives for loading resources, we can build up all other loading and dependency patterns in app-space. That people have to build them in app space is the bug I'm trying to fix here. The loadpolicy/needs attributes are syntax sugar for select resource types -- nice, but (IMO) not strictly necessary and not sufficient for the more general case of content-types not covered by dedicated elements. needs= is actually very little more than syntactic sugar over ES6 module loader primitives, assuming that we can get the ES6 module loader to be augmented to address the needs of non-ES resources: http://esdiscuss.org/topic/es6-loader-proposed-changes -- Ian Hickson U+1047E)\._.,--,'``.fL http://ln.hixie.ch/ U+263A/, _.. \ _\ ;`._ ,. Things that are impossible just take longer. `._.-(,_..'--(,_..'`-.;.'
Re: [whatwg] Preloading and deferred loading of scripts and other resources
On Mon, Sep 8, 2014 at 7:59 PM, Ian Hickson i...@hixie.ch wrote: The platform is missing a lower-level primitive (declarative and imperative) that is able to explain resource loading with the same expressive power as requests initiated by the browser itself. That isn't a problem. I don't follow. To me that *is* the core problem that we should solve first and ship as soon as possible: if we keep the surface area low, we can ship it quickly and let developers experiment and move the platform forward. Adding more layers of higher-level APIs only slows the deployment process. To be clear, I'm not against the core premise of unifying various import mechanisms, but to me that's a secondary goal -- good housekeeping, but not the problem that the actual web developers (not implementers) are actually up against today. And, at least personally, I think we should prioritize developer needs over implementers. That said, I don't think we're actually that far apart... XHR provides arbitrary resource loading, but it lacks the power to express transport-layer options such as relative request priority That is fixed by exposing Request initialisation flags on XHR. I've seen discussions about exposing this on Fetch, but not XHR. Granted, one is not far from the other. and dependencies, That's fixed by using the proposal in this thread. We're talking about different dependencies. I mean transport-layer dependencies - i.e. if possible, ship bytes for resource A before bytes for resource B. Again though, if we can express priorities, we should be able to express (transport) dependencies via the same mechanism, so this is not a big deal. and it also hides requests from the preload scanner, which is a deal-break for performance. That's why the proposal in this thread uses the existing import mechanisms to define how the dependencies. But restricts it to a subset of resource types. Granted, this is not an issue if you give me a generic way to load any resource, ala rel=preload. (2) We also need a declarative, content-type agnostic primitive to express resource loads, such that the preload scanner is able to pickup and processes these fetches on par with all other resources -- hence my rel=preload suggestion. I don't disagree that we need a way to declarative way to import non-browser-native resources (like some text file the script uses for storing game level data or something). But I don't think we need a redundant mechanism to import resource types that already have existing import mechanisms. That's not a primitive, it's just a redundant mechanism. I went into more detail on this very topic, considering a wide array of options, in the big e-mail I sent recently: http://lists.w3.org/Archives/Public/public-whatwg-archive/2014Aug/0177.html It's only redundant insofar as XHR is a redundant mechanism for loading arbitrary resources. There are cases where fetching an image / stylesheet / etc, via XHR is both a reasonable and a required step - {pre,post}processing, and so on. Moving forward, I think the intent is to explain resource loading via Fetch. I'm asking for a declarative Fetch that's preloader friendly and has the same expressive capabilities. We can augment img, script, and other elements, with load-settings and other flags, but that still doesn't cover all the necessary cases. For example, how do I fetch a font file http://dev.w3.org/csswg/css-font-loading/ ...which presumably would have loadSettings exposed. Sadly, even that requires executing JavaScript and fails the preloader use case. or an arbitrary JSON payload with app-data, etc? XHR, or link rel=preload. I assume you're not expecting us to preparse the JSON file. Right, no execution. Just fetch and nothing else: start the request, stick into the appropriate cache(s) if applicable, and keep the payload inert. Note that I'm looking for declarative syntax that allows me to set arbitrary fetch priorities - e.g. upgrade my JSON payload to high priority because I need it to render content on the screen. This is the part that we *need* to solve. rel=preload with the proposal on this thread handles this fine, as far as I can tell. Yes, I think it's close! A few considerations to account for in the processing model, based on real-world use cases and feedback from the webperf group: - https://igrigorik.github.io/resource-hints/#preload - *https://igrigorik.github.io/resource-hints/#processing https://igrigorik.github.io/resource-hints/#processing* All I'm arguing for here is that the MVP for giving web developers the power to start solving these problems is rel=preload. Everything else is a nice to have. As a result, I'd love to uncouple rel=preload from the rest... Once/if the other mechanisms are ready, rel=preload would just inherit them as part of coverage of link. As I said earlier, I don't think we're that far apart. ig
Re: [whatwg] Preloading and deferred loading of scripts and other resources
On Sat, Aug 23, 2014 at 2:44 AM, Ian Hickson i...@hixie.ch wrote: [snip] load-settings=A JSON-encoded dictionary to pass to the Request constructor. I'm not a big fan of JSON attributes for this purpose, for a couple of reasons: * They're likely to add implementation complexity, since these instructions must be read by the preloader, which at least for Blink Gecko is on the parser thread, and cannot do JS AFAIK. It can probably be solved with a thread-safe JSON parser, but it'd add extra complexity. * A non-scientific sample of authors seems to object to them, and I have to admit that they seems weird as part of markup What's the use-case that requires a Request constructor? Is it just for future friendliness? If so, maybe we can expose that only through JS initially, see what people use it for, and if it makes sense add it to markup later on?
Re: [whatwg] Preloading and deferred loading of scripts and other resources
On 9/2/14, 4:34 AM, Yoav Weiss wrote: * They're likely to add implementation complexity, since these instructions must be read by the preloader, which at least for Blink Gecko is on the parser thread, and cannot do JS AFAIK. Fwiw, in Gecko it could, but it would add some overhead to that thread (instantiating a JS runtime on it)... -Boris
Re: [whatwg] Preloading and deferred loading of scripts and other resources
On Tue, Sep 2, 2014 at 3:58 PM, Boris Zbarsky bzbar...@mit.edu wrote: On 9/2/14, 4:34 AM, Yoav Weiss wrote: * They're likely to add implementation complexity, since these instructions must be read by the preloader, which at least for Blink Gecko is on the parser thread, and cannot do JS AFAIK. Fwiw, in Gecko it could, but it would add some overhead to that thread (instantiating a JS runtime on it)... In that case, I may be wrong about Blink as well... I'll make sure if it is in fact an issue there.
Re: [whatwg] Preloading and deferred loading of scripts and other resources
On Tue, 2 Sep 2014, Yoav Weiss wrote: On Sat, Aug 23, 2014 at 2:44 AM, Ian Hickson i...@hixie.ch wrote: [snip] load-settings=A JSON-encoded dictionary to pass to the Request constructor. I'm not a big fan of JSON attributes for this purpose Nobody is, as far as I know. It's just the least bad option suggested so far. Some of the alternatives we've discussed include: - a whole farm of content attributes -- pro: no mixed markup languages (JSON+HTML) -- con: lots of attributes instead -- con: leads to a situation where we have entirely different APIs in different cases (content attribute farm for HTML elements, some other API for non-elements) -- con: hugely increases (potentially in an unbounded fashion) the number of allowed attributes on many elements -- con: would have non-trivial document conformance rules (the attributes are probably interrelated, especially e.g. the ones for setting HTTP headers) -- con: ends up being really ugly and hard to use (how do you set the second HTTP header? It's not intuitive. How do you remove the first while leaving the second?) -- con: ends up even uglier if we ever need two sets on one element (e.g. one for poster= and one for src= on video, or one for each URL in a srcset=) - a new microsyntax, maybe CSS-like -- pro: can be optimised for the use case -- pro: can easily be given a dedicated API -- con: other than skipping the outer braces, it's not clear how much different it would end up being than JSON -- con: still results in mixed markup languages -- con: requires a custom parser -- con: language would have to be non-trivial since it has to include substrings (and escaping in those strings) and nested structures (e.g. for setting headers) - JSON -- pro: some extensibilty (so long as we just want a tree structure of strings and numbers, anyway) -- pro: existing standard syntax with off-the-shelf parsers -- pro: easily placed on other objects -- pro: easily duplicated if an element needs multiple Requests -- pro: can easily be given a dedicated API -- con: verbose -- con: mixed markup languages -- con: requires a non-trivial parser on the preloader thread What's the use-case that requires a Request constructor? Each Fetch has a Request. So assuming we want to explain the Web platform in terms of Fetch, we need a corresponding Request for each Fetch. The Request lets you control HTTP2 priorities and so forth. If so, maybe we can expose that only through JS initially, see what people use it for, and if it makes sense add it to markup later on? Well the Request object is only exposed through JS. But the Request object's construction parameters have to be exposed through markup because for many elements there's no time between the creation of the element and the creation of the Request passed to the Fetch. -- Ian Hickson U+1047E)\._.,--,'``.fL http://ln.hixie.ch/ U+263A/, _.. \ _\ ;`._ ,. Things that are impossible just take longer. `._.-(,_..'--(,_..'`-.;.'
Re: [whatwg] Preloading and deferred loading of scripts and other resources
https://docs.google.com/document/d/1jSpWc6jkrUoYtGWcxev9Blkkv9RhoO1XtqinBvXqhgY/edit Would suffice for priority. Peter On Aug 29, 2014, at 9:59 AM, bizzbys...@gmail.com wrote: We need to bite the bullet and add a priority attribute and an expected-size attribute. Priority: The web server will often have information that allows it to know better than the UA about the priority of objects. Basing this on type is not super useful when we have only a few types and we have lots of objects. The UA can ignore it but a priority field allows the web server to give the UA as much information as it has about how to download the objects to optimize load time. Why not just make it like probability and allow the web server to specify a value between 0.0 and 1.0, which 1.0 being a top priority object? Expected-size: I’ve argued this previously (https://github.com/igrigorik/resource-hints/issues/12) and Ilya agrees its a nice to have. Along with the probability attribute that is in Ilya’s latest draft, this provides a simple way to threshold which objects to prefetch at the UA. Sorry to re-raise expected-size but I think it’s relevant again in the context of priority. A small device or a UA on a bandwidth challenged link could use a simple scheme such as only preload resources above priority X with a smaller than a certain probability*expected-size when expected-size is available. Regardless the details of the logic, the UA needs all three fields (probability, priority, and expected-size) to make a good decision. We know this from 15 years experience doing prefetching in the network for satellite. Thanks, Peter On Aug 28, 2014, at 5:31 PM, Yoav Weiss y...@yoav.ws wrote: On Sat, Aug 23, 2014 at 2:44 AM, Ian Hickson i...@hixie.ch wrote: [snip] On Wed, 4 Sep 2013, William Chan (陈智昌) wrote: * 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. I'm not sure what to do about this exactly. Wouldn't that be something that is best handled as part of HTTP? e.g. sending a flag with the request indicating whether the resource can be progressively decoded or not? * 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. It's hard to come up with a super fine-grained model that works well with multiple competing scripts, but we can do better than what we have now, certainly. It seems we can at least split things into the following categories, in order of highest priority to lowest: 1. resources that are needed and are causing something to block e.g. script src=foo.js/script 2. resources that are needed and are neither blocking anything nor explicitly deferred e.g. img src=foo.png ... 3. resources that are needed but are deferred e.g. script src=foo.js defer/script 4. resources that the browser wants e.g. link rel=icon, html manifest 5. resources that are not yet needed but which the author wants precached when possible, and which have not been marked deferred e.g. link rel=subresource href=... 6. other resources Is that fine-grained enough? Wouldn't the needs attribute enable the browser to create a dependency tree that would allow for finer grained priorities? e.g. 1. Needed resources with no dependencies, that block initial render 2. Needed resources that blocking resources need (e.g.
Re: [whatwg] Preloading and deferred loading of scripts and other resources
We need to bite the bullet and add a priority attribute and an expected-size attribute. Priority: The web server will often have information that allows it to know better than the UA about the priority of objects. Basing this on type is not super useful when we have only a few types and we have lots of objects. The UA can ignore it but a priority field allows the web server to give the UA as much information as it has about how to download the objects to optimize load time. Why not just make it like probability and allow the web server to specify a value between 0.0 and 1.0, which 1.0 being a top priority object? Expected-size: I’ve argued this previously (https://github.com/igrigorik/resource-hints/issues/12) and Ilya agrees its a nice to have. Along with the probability attribute that is in Ilya’s latest draft, this provides a simple way to threshold which objects to prefetch at the UA. Sorry to re-raise expected-size but I think it’s relevant again in the context of priority. A small device or a UA on a bandwidth challenged link could use a simple scheme such as only preload resources above priority X with a smaller than a certain probability*expected-size when expected-size is available. Regardless the details of the logic, the UA needs all three fields (probability, priority, and expected-size) to make a good decision. We know this from 15 years experience doing prefetching in the network for satellite. Thanks, Peter On Aug 28, 2014, at 5:31 PM, Yoav Weiss y...@yoav.ws wrote: On Sat, Aug 23, 2014 at 2:44 AM, Ian Hickson i...@hixie.ch wrote: [snip] On Wed, 4 Sep 2013, William Chan (陈智昌) wrote: * 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. I'm not sure what to do about this exactly. Wouldn't that be something that is best handled as part of HTTP? e.g. sending a flag with the request indicating whether the resource can be progressively decoded or not? * 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. It's hard to come up with a super fine-grained model that works well with multiple competing scripts, but we can do better than what we have now, certainly. It seems we can at least split things into the following categories, in order of highest priority to lowest: 1. resources that are needed and are causing something to block e.g. script src=foo.js/script 2. resources that are needed and are neither blocking anything nor explicitly deferred e.g. img src=foo.png ... 3. resources that are needed but are deferred e.g. script src=foo.js defer/script 4. resources that the browser wants e.g. link rel=icon, html manifest 5. resources that are not yet needed but which the author wants precached when possible, and which have not been marked deferred e.g. link rel=subresource href=... 6. other resources Is that fine-grained enough? Wouldn't the needs attribute enable the browser to create a dependency tree that would allow for finer grained priorities? e.g. 1. Needed resources with no dependencies, that block initial render 2. Needed resources that blocking resources need (e.g. the jquery script in script src=foo.js needs=jquery/script (We can have multiple levels of priorities here, if the dependency tree is high) 3. Needed blocking resources 4. Needed non-blocking resources etc.
Re: [whatwg] Preloading and deferred loading of scripts and other resources
On Sat, Aug 23, 2014 at 2:44 AM, Ian Hickson i...@hixie.ch wrote: [snip] On Wed, 4 Sep 2013, William Chan (陈智昌) wrote: * 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. I'm not sure what to do about this exactly. Wouldn't that be something that is best handled as part of HTTP? e.g. sending a flag with the request indicating whether the resource can be progressively decoded or not? * 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. It's hard to come up with a super fine-grained model that works well with multiple competing scripts, but we can do better than what we have now, certainly. It seems we can at least split things into the following categories, in order of highest priority to lowest: 1. resources that are needed and are causing something to block e.g. script src=foo.js/script 2. resources that are needed and are neither blocking anything nor explicitly deferred e.g. img src=foo.png ... 3. resources that are needed but are deferred e.g. script src=foo.js defer/script 4. resources that the browser wants e.g. link rel=icon, html manifest 5. resources that are not yet needed but which the author wants precached when possible, and which have not been marked deferred e.g. link rel=subresource href=... 6. other resources Is that fine-grained enough? Wouldn't the needs attribute enable the browser to create a dependency tree that would allow for finer grained priorities? e.g. 1. Needed resources with no dependencies, that block initial render 2. Needed resources that blocking resources need (e.g. the jquery script in script src=foo.js needs=jquery/script (We can have multiple levels of priorities here, if the dependency tree is high) 3. Needed blocking resources 4. Needed non-blocking resources etc. If I understand correctly that would provide the fine-grained priorities that Will is after and that will enable the network layer to be smarter about which resource is needed next. [snip] Pulling all of the above together, here's the tentative proposal: These loadable elements: script, link, style, video, img, object, iframe, audio ...get the following new attributes: needs=Gives a list of IDs of other elements that this one needs, known as The Dependencies. Each dependency is added to this element's [[Dependencies]] in the ES6 loader. load-policy= The load policy. Consists of a space-separated set of keywords, of which one may be from the following list: block, async, optimistic, when-needed, late-run, declare. The other allowed keywords are precache, low-priority, and force. (Maybe we disallow block and force since they're for legacy only.) Different elements have different defaults. precache isn't allowed if the keywords block or async are specified, since those always load immediately. Can you perhaps expand on what each of these would mean? [snip] [Use-case P:] download dynamic page components (e.g. maps) only on larger devices. Long
Re: [whatwg] Preloading and deferred loading of scripts and other resources
On 8/28/14, 5:31 PM, Yoav Weiss wrote: Wouldn't that be something that is best handled as part of HTTP? e.g. sending a flag with the request indicating whether the resource can be progressively decoded or not? Can we define progressively decoded? Firefox is moving to a setup where we will progressively parse scripts, and possibly progressively bytecode-compile, and possibly progressively native-code-compile in the cases when we do AOT compilation, but obviously not progressively execute. -Boris
Re: [whatwg] Preloading and deferred loading of scripts and other resources
On Tue, Aug 26, 2014 at 5:45 PM, Ilya Grigorik igrigo...@gmail.com wrote: [[stuck in the mod queue.. attempt #5, apologies for dupes if you get them]] Ian, thanks for writing this up. The first thing that strikes me about this entire topic is its scope, and I'm wondering if we should take a step back and (a) extract some lower level primitives, (b) leave the rest to libraries and web developers to experiment with, and (c) if (b) leads to some good patterns, then codify them at a later date... Instead of trying to tackle all of this at once. In particular, it seems like we might be coupling two topics: (1) a flexible declarative mechanism to fetch arbitrary resources (2) some set of mechanisms to express dependencies, execution order, etc. If we do our job right with (1), I think (2) can (should?) be deferred to developers and library writers. Specifically, for (1): - We need a way to initiate arbitrary downloads that doc + preload parsers will understand and can process - We need a way to communicate type, prioritization, MQ, and other custom fetch information for each download - We need a way to listen on download progress of these resources to build custom processing logic - By default there is no UA processing on the response, this mechanism simply fetches bytes This is the direction I was proposing earlier [1] with rel=preload -- see [2], for a concrete example. I really like your proposal for as=... Concretely it could look something like this: link rel=preload href=/some/asset.css as=stylesheet(used to initialize default priority, headers, etc) load-settings={} (JSON payload with custom headers, priority [2], etc) media= ... (relevant media queries..) probability=([0.0-1.0] used for speculative fetches [3]) The combination of all of the above allows me to fetch any content-type, specify custom priorities and headers (or use a default set via 'as'), apply MQ's, etc. Given all that, assuming I can extract a Promise/Fetch object (or some such) out of it, I can then track the download progress and apply any arbitrary logic for how and when it should be processed. For example: - I can execute a script immediately by waiting for the download to finish and inject the script tag referencing same URL - I can setup a callback that waits for any other arbitrary resource to finish before I execute it... - I can defer execution until a particular action occurs. - I can prefetch arbitrary resources for later use - ... (note: the script example is completely arbitrary.. the entire point is that this mechanism is independent of content-type) In other words, it seems like you could build most (all?) of the doc'ed use cases in client-land... One thing you won't have here is the declaration of a dependency tree to the preloader, so e.g. all of your scripts will be of the same priority, even if some of them depend on others. I can implement needs, loadPolicty, addDependency on my own. Which, in my books, is a much better outcome anyway because it will allow more and much more rapid experimentation. --- [1] http://lists.whatwg.org/pipermail/whatwg-whatwg.org/2014-August/297383.html [2] https://docs.google.com/presentation/d/1Q-7keKXwP2UeZ2zTN9Ue2ASIdIZPqxnEvnDsPSLTwcQ/present#slide=id.g377330538_0345 [3] http://lists.whatwg.org/pipermail/whatwg-whatwg.org/2014-August/297437.html [4] https://docs.google.com/presentation/d/1Q-7keKXwP2UeZ2zTN9Ue2ASIdIZPqxnEvnDsPSLTwcQ/present#slide=id.g120f70e9a_025
Re: [whatwg] Preloading and deferred loading of scripts and other resources
On Thu, Aug 28, 2014 at 11:34 PM, Boris Zbarsky bzbar...@mit.edu wrote: On 8/28/14, 5:31 PM, Yoav Weiss wrote: Wouldn't that be something that is best handled as part of HTTP? e.g. sending a flag with the request indicating whether the resource can be progressively decoded or not? Can we define progressively decoded? Firefox is moving to a setup where we will progressively parse scripts, and possibly progressively bytecode-compile, and possibly progressively native-code-compile in the cases when we do AOT compilation, but obviously not progressively execute. Maybe the flag should indicate a please send this progressively hint to the server. Then the browser is free to send whatever hint to the server that gives it best performance. If receiving multiple resources progressively provides better performance then having the server sending them one after the other, then the hint should be sent.
Re: [whatwg] Preloading and deferred loading of scripts and other resources
Ian Hickson writes: Here's how [the proposal] would handle the use cases listed above. [Use-case G:] A website knows there's a piece of Javascript code that the user might need if they click on a part of the page. The developer would like to have the user download it, but not at the expense of other resources. script src=button-reaction.js id=reaction load-policy=when-needed precache low-priority // button-reaction.js defines react() /script button type=button onclick=document.scripts.reaction.load().then( function() { react(); }) Part of the Page /button What does low-priority add in case G? How does that differ from case H, where when-needed precache is sufficient to avoid delaying other things from loading? [Use-case H:] A website is prefetching photos in a photo album and would like to make sure these images are lower priority than images the user is actually viewing. img src=photo1.jpg alt=... load-policy=when-needed precache img src=photo2.jpg alt=... load-policy=when-needed precache img src=photo3.jpg alt=... load-policy=when-needed precache img src=photo4.jpg alt=... load-policy=when-needed precache img src=photo5.jpg alt=... load-policy=when-needed precache As they come into view, they'll become needed automatically. When they are not needed, they get precached if that wouldn't get in the way of other things getting loaded. Thanks. Smylers -- http://twitter.com/Smylers2
Re: [whatwg] Preloading and deferred loading of scripts and other resources
[[stuck in the mod queue.. attempt #5, apologies for dupes if you get them]] Ian, thanks for writing this up. The first thing that strikes me about this entire topic is its scope, and I'm wondering if we should take a step back and (a) extract some lower level primitives, (b) leave the rest to libraries and web developers to experiment with, and (c) if (b) leads to some good patterns, then codify them at a later date... Instead of trying to tackle all of this at once. In particular, it seems like we might be coupling two topics: (1) a flexible declarative mechanism to fetch arbitrary resources (2) some set of mechanisms to express dependencies, execution order, etc. If we do our job right with (1), I think (2) can (should?) be deferred to developers and library writers. Specifically, for (1): - We need a way to initiate arbitrary downloads that doc + preload parsers will understand and can process - We need a way to communicate type, prioritization, MQ, and other custom fetch information for each download - We need a way to listen on download progress of these resources to build custom processing logic - By default there is no UA processing on the response, this mechanism simply fetches bytes This is the direction I was proposing earlier [1] with rel=preload -- see [2], for a concrete example. I really like your proposal for as=... Concretely it could look something like this: link rel=preload href=/some/asset.css as=stylesheet(used to initialize default priority, headers, etc) load-settings={} (JSON payload with custom headers, priority [2], etc) media= ... (relevant media queries..) probability=([0.0-1.0] used for speculative fetches [3]) The combination of all of the above allows me to fetch any content-type, specify custom priorities and headers (or use a default set via 'as'), apply MQ's, etc. Given all that, assuming I can extract a Promise/Fetch object (or some such) out of it, I can then track the download progress and apply any arbitrary logic for how and when it should be processed. For example: - I can execute a script immediately by waiting for the download to finish and inject the script tag referencing same URL - I can setup a callback that waits for any other arbitrary resource to finish before I execute it... - I can defer execution until a particular action occurs. - I can prefetch arbitrary resources for later use - ... (note: the script example is completely arbitrary.. the entire point is that this mechanism is independent of content-type) In other words, it seems like you could build most (all?) of the doc'ed use cases in client-land... I can implement needs, loadPolicty, addDependency on my own. Which, in my books, is a much better outcome anyway because it will allow more and much more rapid experimentation. --- [1] http://lists.whatwg.org/pipermail/whatwg-whatwg.org/2014-August/297383.html [2] https://docs.google.com/presentation/d/1Q-7keKXwP2UeZ2zTN9Ue2ASIdIZPqxnEvnDsPSLTwcQ/present#slide=id.g377330538_0345 [3] http://lists.whatwg.org/pipermail/whatwg-whatwg.org/2014-August/297437.html [4] https://docs.google.com/presentation/d/1Q-7keKXwP2UeZ2zTN9Ue2ASIdIZPqxnEvnDsPSLTwcQ/present#slide=id.g120f70e9a_025
Re: [whatwg] Preloading and deferred loading of scripts and other resources
On Sat, 23 Aug 2014 02:44:23 +0200, Ian Hickson i...@hixie.ch wrote: On Wed, 12 Mar 2014, Boris Zbarsky wrote: I realize no one would write actual code like this; the real-life use case I'm worried about would be more like this: // img is already loaded sometimes // Would like to observe a new load var promise1 = img.loaded(); // oops! This will be pre-resolved if // we were already loaded, but otherwise // will resolve with the new load we're // about to start. img.src = bar; promise1 would be rejected as soon as you set 'src' if it hadn't loaded yet. The old image doesn't stop loading immediately when setting 'src' if its dimensions are known. In that case it only stops loading if the new image gets known dimensions before the old one finishes loading. If it had loaded, it would resolve straight away. In the latter case, you might observe either the old image or the new one, there's no way to know for sure. This is certainly bug-prone and I'm sure people will get it wrong and it'll usually work but sometimes not, due to the race. However, it's a logic error -- you're always observing the first load, not the second. It will always resolve straight away, either aborting or succeeding based on whether the original load is aborted or had completed. On Wed, 12 Mar 2014, Domenic Denicola wrote: With promises you should only ask for the loaded promise *after* setting `src`; anything you retrieve before that represents a previous load. Except, I suppose, for the base-case of images with no src, transitioning to having an src? Or are they considered to have e.g. loaded `about:blank` already? No, but iframe does (when inserted to the document). I.e. what should this do? var img = document.createElement(img); var promise1 = img.loaded(); img.src = foo.png; var promise2 = img.loaded(); I think we should spec this case to reject promise1, since the image is not .complete. .complete returns true actually. (Thought I don't mind rejecting.) I definitely don't think we should say that promise1 waits for the src to be set. On Tue, 22 Jul 2014, Ben Maurer wrote: On Tue, Jul 22, 2014 at 10:26 AM, Ian Hickson i...@hixie.ch wrote: On Mon, 21 Jul 2014, Ben Maurer wrote: (1) Allowing the user to specify parameters to Fetch. For example, a user could say: script src=/my.js params={'headers':{'myheader':'value'}} id=myscript / This would allow the user to make any type of request customization that they could for a direct call to Fetch. I think this would make a lot of sense. It's similar to earlier suggestions for controlling Referer on a per-link basis, but more generic. The problem I had with the proposals for controlling Referer was that while there's an obvious way to do it for script and link, it quickly starts breaking down don't have a 1:1 mapping of URL to element. For example, how do you get the fetches of URLs in a style sheet? Or of the poster frame of a video element? Or EventSource objects? Should we just have different ways to set the options for each one? I guess the upshot of of doing this through fetch is that once we added the ability to specify fetch metadata it would hopefully reduce the need for future modification of all the different ways one could load an object. http://lists.w3.org/Archives/Public/public-webappsec/2014Jan/0129.html suggests the idea of using fetch for stylesheet subresources in the context of subresource integrity. Yeah. I think it makes sense to expose a Request object once one is underway, and a RequestInit object (probably in the form of a JSON-encoded content attribute?) to configure it, at least for the main resources. I'm not sure how to handle elements with multiple resources, e.g. video poster or the new picture stuff. So currently video and img have an attribute to configure the request, namely crossorigin=. It doesn't apply to poster, but video crossorigin applies to video src, source src *and* track src. (You can't paint the poster on a canvas anyway so it doesn't matter much.) For img crossorigin it applies to the URL that gets loaded, whether that is from src, srcset or source srcset. integrity would need to be able to apply to each individual URL somehow (probably with a new srcset descriptor for img). Is crossorigin's coarseness OK or do we need something per URL? -- Simon Pieters Opera Software
Re: [whatwg] Preloading and deferred loading of scripts and other resources
Thanks for writing this all up. A few questions/thoughts: (1) Dependencies in this model seem to be strict execution dependencies. It's possible some use cases might want to use dependencies to describe loading priority. As an example, imagine a Facebook page with 3 JS files: Feed.js -- Needed to render the user's feed Chat.js -- Displays the user's friends who are online PhotoViewer.js -- When the user clicks a photo, this file creates a photo viewer allowing the user to browse an album. Until the user clicks something, this file isn't needed. Roughly, the behavior we want here is: load Feed, then Chat, then PhotoViewer. But if the user clicks a photo move PhotoViewer to the front of the line. How do I express the relative ordering of Feed vs Chat vs PhotoViewer? I wouldn't want to use dependencies, because if PhotoViewer depended on Chat then if I call .load() on PhotoViewer it will force Chat to be downloaded. (2) Can inline scripts have needs? This seems like something potentially useful (eg, you include a script tag for Google maps then you have an inline script to create a map. You want the inline script to only execute once maps is loaded) (3) How does loading interact with the cache? For example, if I have a link load-policy=declare and the resource is in the browser's cache, would the ready promise be fulfilled? This could be very useful for applications -- sometimes there is functionality you are willing to execute immediately if the resource is in the user's cache. On Fri, Aug 22, 2014 at 5:44 PM, Ian Hickson i...@hixie.ch wrote: When I last looked at preloading scripts, it was pointed out to me that the Web Perf WG had some work ongoing in this space, so I decided to let them take care of it. However, nothing much seems to be happening there, and so I'm looking at this again. It's also been pointed out that limiting this to just scripts preloading maybe taking too narrow a view, and that we should also consider preloading and deferring loading of other resources, such as images, style sheets, and so forth. I will start by looking at use cases again, then go through some of the feedback on the last proposal I'd made in this space, and then make a new proposal intended to address the use cases and feedback. On Fri, 15 Aug 2014, Ben Maurer wrote: [Use-case F:] A website has a page where media is the primary content. It would like to make sure that media is downloaded before JS [e.g. flickr, youtube, facebook photos] [Use-case G:] A website knows there's a piece of Javascript code that the user might need if they click on a part of the page. The developer would like to have the user download it, but not at the expense of other resources. [Use-case H:] A website is prefetching photos in a photo album and would like to make sure these images are lower priority than images the user is actually viewing. On Mon, 28 Jul 2014, Ben Maurer wrote: [Use-case I:] Facebook uses an automated pipeline to decide what CSS/JS files to package together. If we could pass a custom header in the request for a CSS file (for example: what part of the page caused that file to be loaded) we could use this information in our packaging system to make smarter decisions. On Tue, 22 Jul 2014, Ben Maurer wrote: [Use-case J:] The way we render pages at Facebook [is essentially that we] flush sections of HTML with a list of CSS and JS dependencies for each section. The HTML is only rendered once these resources are loaded. [Use-case K:] We have a few other use cases for this type of dependency (for example, we have a method where you can say call this callback once resources X, Y and Z are requested). On Tue, 3 Sep 2013, Ryosuke Niwa wrote: [Use-case L:] A web page wants to load and execute a script widget.js if the script is already cached in the browser. However, it wants to load other essential assets such as images first if it's not already in the cache except as long as the user had not started interacting with the parts of the page that require widget.js. On Tue, 18 Mar 2014, Jonas Sicking wrote: [Use-case M:] Being able to specify that an image/video should only be downloaded on demand (aka lazily), i.e. when it's in view, or about to be in view. Use case is both to lower bandwidth in cases of long pages where the user doesn't always scroll to the bottom, as well as make sure to fill the network pipe with the most important resources first. [Use-case N:] Being able to specify that a stylesheet should not block rendering. Use case is to preload stylesheets that will be used by content that isn't rendered in the initial view, but that might be rendered later. [Use-case O:] Being able to specify some form of prioritization for resources like (non-blocking) stylesheets, (non-blocking) scripts, images, video, iframes etc. Use case is making sure to fill the network pipe with the most important
Re: [whatwg] Preloading and deferred loading of scripts and other resources
Surely our goal should be to make script loaders unnecessary. There's unquestionably a lot of folks on this thread for whom that is their main concern. I think it's a mistake to assume that because they mostly seem to be working as browser developers (which strongly influences their perspective, I believe) that this is a universal goal. In fact, I would say I have the opposite goal. I currently, and have always (for the 3-4 years this discussion has been languishing), wanted to make script loaders better and more capable, not get rid of them. Two primary reasons: 1. A hand-authorable markup only (aka zero script loaders) approach is, and always will be, limited. Limited to what? To the initial page load. A significant portion of the discussion in the long and sordid history of this thread of discussion is indeed centered around browsers wanting to optimize markup loading using their pre-scanner, etc. There's a strong implied assumption that zero-script-loader hand-authored-markup-only page-load-only script loading is the most important, and in fact the only important, concern. I have registered already many times my strong objection to this mindset. Originally, my participation in the thread, and my many proposals and variations along the way, actually didn't really care nearly as much about this initial page-load case. But let me clarify: it's not that I don't care about initial page-load at all, but that I care *more* (much more, in fact) about enabling and making easy-to-use dynamic in-page on-demand loading use-cases. The proposals I made for improving that usage also degrade to letting the same script loader logic handle the initial page-load using the same mechanisms. IOW, my focus is on on-demand loading capabilities, via a script loader, and the initial-page-load script loading (via script loader) is a simple degraded base-case for the same capabilities. The reverse is not true. The hand-authored-markup-only solutions being proposed largely don't care at all about the script loaders use cases, and certainly don't degrade in any reasonable way to improving the outlook for dynamic script loading (see the initial quote above). In fact, they sometimes make those use cases MUCH WORSE. Why? Because the markup-only solutions make lots of assumptions that don't apply to on-demand loading, such as availability of DOM elements, order of parsing, etc. Some of the concerns have analogs in script loading logic, but they're awkward and inefficient from the script loader point of view. -- The majority of markup-focused solutions thus far proposed favor hand-authored-markup-only, and seem unconcerned by the fact that they will make the on-demand script loader use-cases harder. -- For example: var s1 = document.createElement(script); s1.id = some-id-1; s1.src = http://some.url.1;; var s2 = document.createElement(script); s2.id = some-id-2; s2.src = http://some.url.2;; s2.needs = s1.id; var s3 = document.createElement(script); s3.src = http://some.url.3;; s3.needs = s1.id + , + s2.id; document.head.appendChild(s3); // append in reverse order to make sure `needs` is registered early enough document.head.appendChild(s2); document.head.appendChild(s1); This is a super simple distillation of generated script loader logic to load 3 scripts, where 2 needs 1, and 3 needs both 1 and 2. If you author JS code like this by hand, it seems somewhat tractable. But, as the chains get longer (more scripts) and the dependencies get more complex, this becomes increasingly difficult (in fact, approaching impossible/impractical) to actually generate via a generalized script loader. Why? Because the script loader has to know the entire list of scripts (IOW it needs to make its own internal queue/s) in this group, before it can reason about how to generate the ID's and wire up the attributes. By contrast, most good script loaders right now that take advantage of the `async=false` internal browser loading queue can start loading in 1-2-3 order in a streaming fashion, not having to wait for all 3 to start. Why? Because the `async=false` loading queue that the browser provides implicitly handles the ordering. The result? Current script loaders can load 1. Then later 2. Then later 3. And regardless of how long or short later is, or of how quickly things load, or if all 3 are indeed loaded at the same time -- in all these variations, the queue the browser provides just makes the loading/ordering work. The proposals being suggested actively do away with that assistance, in favor of making authors manage their own queues via chains of selectors, in markup. Which leads to… 2. There is, intuitively, some threshold of complexity of markup beyond which most hand-authors will not go. They may author: script src=http://some.url.1; async id=s1 script src=http://some.url.2; async needs=s1 But, most probably would never author: script src=http://some.url.1;