Closed getify closed 8 years ago
Good question, not sure. Are there mechanisms to test if browser implements particular relation type? E.g. prerender, etc?
I have never considered FT for link rel=prefetch
(or others) before, since its absence wasn't a problem. This feature would absolutely require to know if it's there to decide if it's going to be used (by script loaders, that is).
So, if a technique doesn't exist, I'd say it's a must that we invent something.
I'm open to ideas :) /cc @marcoscaceres @slightlyoff
Here's a thought:
var s = document.create("link");
s.rel = "preload";
var supports = ("preload" in s);
That is, it adds the preload
property to the element (value true
) as soon as you set the rel
to "preload"
.
An alternate is that instead of an onload
event name, the preload
event would be used (only possible on the <link>
element and only used for these preloading purposes). So you could check for:
var supports = ("onpreload" in document.create("link"));
Side note: I like this option better semantically anyway, as "load" on a preloading-only element feels awkward.
The more I think about this, the more I'm wary of trying to invent something in a context of this particular spec... This feels like a larger missing feature in the platform? Specifically, while we have libraries like Modernizr doing all kinds of crazy tricks in the background to feature detect particular features.. perhaps there should be a dedicated API to answer such things.
Yeah, that's been needed for years. I've asked for (soft proposed) it several times in fact. There's a whole slew of things that are currently not feature detectable, that such an API could help with.
Problem is people always say that the scope is too large to tackle it paired with whatever the one feature case is at the moment, so another ad hoc FT is designed, or (worse) FT is skipped (thankfully more rare these days).
If you think you could push a FeatureTests
API through in roughly the same time period as rel=preload
, I'd be all for it. My guess is that won't happen, given history.
Side note: this is somewhat tangential to my other feeling, which is that "client hints" should be extended to be able to send all the same kinds of info that a theoretical FT API would.
The problem with this kind of API is that it's extremely problematic - what "supported" means is nebulous. See, for instance, .hasFeature()
which was a previous attempts to provide this kind of thing:
hasFeature() originally would report whether the user agent claimed to support a given DOM feature, but experience proved it was not nearly as reliable or granular as simply checking whether the desired objects, attributes, or methods existed. As such, it should no longer be used, but continues to exist (and simply returns true) so that old pages don't stop working.
I agree that there should be some means of detecting preload
by explaining it in terms of JS (and related DOM APIs), but I've not given this a lot of thought. It depends on the browser machinery handling the preload.
I understand Blink has announced intent-to-implement for this link..rel=preload
feature. I still feel strongly that it must have a feature-test of some sort to be acceptable as a new feature.
I was asked to add an explicit description to this issue of why I feel this way.
The primary reason is that I maintain the LABjs dynamic script loader. It has various feature tests (and, unfortunately, inferences) in it for exploiting different preloading techniques (of sorts) in browsers, both new and old. If link..rel=preload
lands in browsers, of course I would want to update LABjs to detect and use that new technique.
However, there must be a feature detect for this. I will not be using any new features in LABjs that do not have direct and reliable feature tests (no inferences or UA parsing or any of that junk).
Hopefully that underscores the necessity of a feature-test. :)
+@yoavweiss
@getify, the problem is that there is no guarantee that preload
will actually do the preloading (even if you could feature detect it). It's to the browser's (or possibly user settable) discretion if preload actually preloads and when the preload actually happens (it's low priority). The only way to detect the preload is on the preloaded resource, which will be able to detect that it has been loaded in the background through, IIRC, the page visibility API.
In other words, I don't see what you would gain from feature testing, rather than assuming with certainty that, being a "web standard", you are increasingly likely (over time/on new browsers) to get the desired effect when the browser's environmental conditions are right to perform the a preload.
there is no guarantee that preload will actually do the preloading
That doesn't match up with the semantics from my reading of the spec. If that's true, how is "preload" any different from "prefetch"?
That is, how is there any less guarantee that link..rel=preload
will preload the script than there is that <script src>
will load a resource? If they're roughly the same "guarantee", that's more than sufficient. If they're substantially different, that's a major design flaw with this feature.
it's low priority
AFAICT, priority wouldn't affect the decision to use the feature or not. In fact, that might be a benefit to be able to opt into a system for script loading which is lower priority than document.createElement("script")
implies, if in fact it's different.
The only way to detect the preload is on the preloaded resource
How?
I don't see what you would gain from feature testing
I would absolutely expect that a browser should not make the feature-detect (whatever it is) return true
for this link..rel=preload
feature if it's not actually implemented in some meaningful way. If browsers do that, they're acting counter to the spirit. No, there's nothing I can do about that except complain on twitter.
But the possibility of misbehavior on the part of browser vendors is in no way an argument against features designed and relied upon in good spirit.
@marcoscaceres I am also confused about your "no guarantee" statement here.
My understanding is that Preload
was split as separate specs for the mandatory semantics.
Doesn't that mean that a link preload
with no pr=
and no loadpolicy=
is a must?
In terms of feature detection, one alternative could be exposing some CONSTANTS
at the HTMLLinkElementConstructor
level, similarly to how's we'd detect support for CSSRULES
?
@hexalys oh dear, maybe I'm getting my prefetch, preload, prerenders confused again :/ Ignore me.
@marcoscaceres @hexalys @getify yep, rel=preload
is a MUST fetch.
Re, feature detect: the onpreload
even suggestion sounds feasible, but it does feel a bit odd to me. First, it deviates from regular "fire the load event" pattern, which will undoubtedly create confusion and head-scratching for developers. Second, it's a preload specific thing.
<crazy thought>
But speaking of "MAY" fetch semantics.. Would there be value in exposing an API that allows the site to query whether the UA is willing to invoke a certain type of fetch? For example, the UA may support prerendering, but due to current environment/etc constraints is not willing to perform it: instead of leaving the application guessing, perhaps we should provide a way to the UA before submitting the request?
If we had such an API, it wouldn't be too farfetched to also ask for "is preload supported?"
It could be an API extended to check support for all/any Link Types or associated rel
properties. Which would be new, but useful on the long term for recent and future link
attributes or rel
types.
i.e. A more limited hasFeature()
good for things like: crossorigin
, media type
, sizes
, icon
, prefetch
, prerender
, ping
or even stylesheet
support etc.. All very hard detects requiring expensive tests or tricks.
@hexalys hasFeature()
is different what I was thinking above.. I was pointing out the case where feature was supported, but based on runtime factors is "not active" - e.g. prefetch won't be triggered because the user is roaming and/or on expensive data plan. And, of course, not supported == not active.
For hasFeature
scoped to link
, this kinda smells like a whatwg question...
@igrigorik Understood. But this could be a linkSupport
designed to assume runtime or environment conditions, along the basic capability. With detects like: 'prefetch' in linkSupport.rel
to detect feature support; and linkSupport.rel.prefetch === true|false
for active or inactive; A whatwg question indeed.
@getify open to kicking off a discussion on whatwg on feature testing ? :)
@getify perfect, thank you! Let's see what we can come up with there.
I like where this is going.
Semantically, feature detection and testing is 2 things:
These are requirement of detection/testing seems valuable for hints.
@zcorpan's suggestion on the WHATWG thread makes a ton of sense for preload, and <link>
based features in general.
@zcorpan - that's not something that's currently part of the link element spec, right?
No, it would be a spec change.
For reference, from the whatwg thread:
(@zcorpan) For
<link rel>
, we could solve the feature-testing problem by normalizing the case for supported keywords but not unsupported keywords, so you can check with .rel or .relList:
function preloadSupported() {
var link = document.createElement('link');
link.rel = 'PRELOAD';
return link.rel == 'preload';
}
^ sgtm. @zcorpan should we open a bug for this on whatwg?
Thanks for this thread. I'm trying to research how this might come together in a real implementation. Mind having a look, @igrigorik ? (Moved to an issue over at loadCSS to keep this thread on topic.)
@scottjehl commented on the issue; lgtm.
In related news, opened a bug for the HTML spec: https://www.w3.org/Bugs/Public/show_bug.cgi?id=28616 /cc @zcorpan
We don't have a label for "blocked on other spec", hence marking as 'help wanted'.
Another (possibly better) idea is to make some changes to the DOMTokenList API to enable feature-checking, see https://www.w3.org/Bugs/Public/show_bug.cgi?id=29061
That looks great. I assume we'd add the validation algorithm for <link>
in HTML spec? There'd need to be a hook for other specs to extend the validation mechanism.
First step: https://github.com/whatwg/dom/pull/103
@yoavweiss awesome. thanks for nudging it forward!
Blink intent to implement: https://groups.google.com/a/chromium.org/d/msg/blink-dev/xEoWkGEd_g4/Pkn_o92EAwAJ
Yoav, I'm thinking we can add a note in the spec documenting this mechanism?
Definitely! :) On Nov 19, 2015 19:23, "Ilya Grigorik" notifications@github.com wrote:
Blink intent to implement: https://groups.google.com/a/chromium.org/d/msg/blink-dev/xEoWkGEd_g4/Pkn_o92EAwAJ
Yoav, I'm thinking we can add a note in the spec documenting this mechanism?
— Reply to this email directly or view it on GitHub https://github.com/w3c/preload/issues/7#issuecomment-158126550.
Had @travisleithead from TAG review this and there was no pushback. Nicely done, @yoavweiss !
@yoavweiss kudos on getting https://code.google.com/p/chromium/issues/detail?id=553945 fixed.
Do you have a 'best practice' code snippet I should put in the spec?
I'll PR something in a bit
What did we actually end up with for the feature detection? The snippet indicated here: https://www.smashingmagazine.com/2016/02/preload-what-is-it-good-for/#feature-detection
... that really sucks if that's the required pattern for feature detect, having to wrap in a slowish try..catch
. Please tell me there's a better way than that?
Maybe:
function supportsToken(token) {
return function(relList){
if (relList.supports && token) {
return relList.supports(token);
}
return false;
}
};
var supportsPreload = supportsToken("preload");
var rl = document.createElement("link").relList;
console.log(supportsPreload(rl));
One could make a more generic variant of the above if necessary. Is that what you mean?
No, I meant that in the linked-to code snippet, a try..catch
was wrapped around the supports(..)
call, indicating that it could throw errors. Is the try..catch
required or not?
Ah, I'm concerned about that too. I hope it can't throw. That would be sad.
The try...catch
is required when you're calling supports()
on a DOMTokenList which may not have supported tokens.
If you're calling supports()
on e.g. the result of relList
of an HTMLLinkElement
, try
is not needed.
@yoavweiss are you suggesting that link#relList
always has a list of supported tokens, so supports(..)
would never throw on it? What are some examples of relList
s where it would throw?
@getify yeah, assuming supports()
is implemented according to spec. See https://html.spec.whatwg.org/#the-link-element:concept-supported-tokens
It always throws for e.g. classList
.
on IE relList
is not supported https://caniuse.com/#search=relList so this check only works on modern browsers which already support preload https://caniuse.com/#search=preload therefore using relList
to check feature support is not useful, is there some other way to check this feature on old browsers?
If relList
is not supported, that's an indication that preload
isn't as well (as it was implemented alongside it, as the feature detection mechanism)
@yoavweiss that's a feature inference, not a feature detection. maybe parsing semantics, but I think it's important to be clear on such things.
While I agree that there could be a case of an implementation implementing preload without making sure its feature detection mechanism is shipped as well, I'm not aware of such a case. Therefore, I think the distinction makes very little difference in practice.
In practice? Maybe not much. It makes a bigger semantic difference though. From a documentation and code-readability perspective.
If relList
"was implemented alongside preload
, as the feature detection mechanism", shouldn't the spec mention that relList
must also be implemented if preload
is implemented or something like that?
How do I feature test if a new browser supports
link rel=preload
?