link rel="preload" without as
A preload with no as has no destination, so the browser fetches nothing and the critical resource loads late, as if the hint were never written.
- Avoid
- Harmful
- Severity
- HarmfulActively breaks something for users.
- Basis
- SpecifiedThe evidence is in a current standard.
- Detectable
- YesMatched exactly. Autofixable when the rule carries a fix.
- Matches
link[rel~="preload" i]:not([as])Element rule, anywhere in the document.- Fix
- None — reports only
- Impacts
- Performance
- Related
link/preload-font-crossorigin
<link rel="preload" href="/fonts/inter.woff2"> looks like it tells the browser to start
downloading a critical resource early. Without as, it tells the browser nothing it can
act on, so the browser does nothing. The resource arrives exactly when it would have with no
hint at all, and the only trace is a warning in the console.
Why avoid
The attribute isn’t optional. The HTML Standard says as “must be specified on link
elements that have a rel attribute that contains the preload keyword”, with a value that
is a preload destination: fetch, font, image, script, style or track. There is
no default. A missing value maps to no state.
Without a destination, there is no preload. The destination is part of how a preloaded
response is matched to the real request later, and the Standard’s processing translates
as into one before fetching. A value that isn’t a preload destination translates to
null, and the preload stops there without making a request. Chromium does the same: it
logs <link rel=preload> must have a valid `as` value as a console warning and
returns before fetching anything.
That makes it harmful rather than merely invalid. A preload marks the one resource that
matters most for this navigation: the hero image that becomes the Largest Contentful Paint,
the font the first paint waits on, the CSS above the fold. With as missing, that resource
is found and fetched at normal priority whenever the parser or style engine gets to it. The
optimisation the markup promises silently doesn’t happen, nothing on the page shows it, and
so it ships.
A correct as does more than turn the preload on. It sets the right Accept header, makes
the right Content-Security-Policy directive apply, and lets the browser reuse the preloaded
response instead of fetching it again.
Use instead
<link rel="preload" href="/css/above-the-fold.css" as="style">
<link rel="preload" href="/img/hero.avif" as="image" fetchpriority="high">
<link rel="preload" href="/fonts/inter.woff2" as="font" type="font/woff2" crossorigin>
Fonts are fetched in CORS mode, so a font preload also needs crossorigin or it won’t be
reused. See link/preload-font-crossorigin.
Detectability
Fully detectable. The selector matches a preload token in rel, which is a token set,
on a <link> with no as attribute at all. An as that is present but empty or not a
destination, like as="stylesheet", has the same outcome but isn’t caught by this rule.
There is no autofix. The fix adds a value, and only the author knows what the resource is.
Resources
- HTML Standard — the as attribute — “must be specified” on
rel=preload, with a preload destination as its value; no missing value default. - HTML Standard — link type “preload” — the preload key includes the destination; a value that isn’t a preload destination translates to null and nothing is fetched.
- Chromium —
third_party/blink/renderer/core/loader/preload_helper.cc— the “must have a validasvalue” console warning, and the return before any fetch. - MDN — rel=preload — what
aslets the browser do: cache reuse, the right CSP, the rightAcceptheader;crossoriginfor fonts.
This page is generated from content/rules/link/preload-as.md, the same file the linter is built from. Think the rule is wrong, or that browsers moved on? Say so — that is the most useful issue you can file.