Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Iterate on crossorigin language in Link preload header comments #186

Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 21 additions & 18 deletions server/lib/set-headers-to-preload-assets.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ function setHeadersToPreloadAssets(res, pageOptions) {

const { styles, preloadScripts } = getDependenciesForEntryPointName(pageOptions.entryPoint);

// Note: Any docs for the `<link>` element apply to the `Link` header. "The `Link`
// header contains parameters [that] are equivalent to attributes of the `<link>`
// element."
// (https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Link#parameters)

// XXX: Should we add `nopush` to the `Link` headers here? Many servers initiate an
// HTTP/2 Server Push when they encounter a preload link in HTTP header form
// otherwise. Do we want/care about that (or maybe we don't)? (mentioned in
Expand All @@ -29,32 +34,30 @@ function setHeadersToPreloadAssets(res, pageOptions) {

// TODO: We should preload fonts as well.
//
// We use `cors` because fonts are fetched with "CORS mode 'cors'" (see
// https://drafts.csswg.org/css-fonts/#font-fetching-requirements)
//
// TODO: Should this be `cors` or `crossorigin`?
// https://www.smashingmagazine.com/2016/02/preload-what-is-it-good-for/#headers shows
// `crossorigin` but
// https://html.spec.whatwg.org/multipage/links.html#link-type-preload (the spec) says
// `cors` so I'm not sure.
// We use `crossorigin` because fonts are fetched with anonymous mode "cors" and
// "same-origin" credentials mode (see
// https://drafts.csswg.org/css-fonts/#font-fetching-requirements). `crossorigin` is
// just short-hand for `crossorigin=anonymous` (see
// https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/crossorigin and
// https://html.spec.whatwg.org/multipage/infrastructure.html#cors-settings-attribute).
//
// `Link: <font_to_load.woff2>; rel=preload; as=font; cors`
// `Link: <font_to_load.woff2>; rel=preload; as=font; crossorigin`

// We use `rel=modulepreload` instead of `rel=preload` for the JavaScript modules
// because it's a nice dedicated thing to handle ESM modules that not only downloads
// and puts it in the cache like a normal `rel=preload` but the browser also knows
// it's a JavaScript module now and can parse/compile it so it's ready to go.
//
// Also as a note: `<script type="module">` with no `crossorigin` attribute indicates
// a credentials mode of `omit` so you will run into CORS issues with a naive `Link:
// <thing_to_load.js>; rel=preload; as=script;` because it defaults to `same-origin` and there
// is a mismatch (see
// https://html.spec.whatwg.org/multipage/links.html#link-type-preload ->
// https://fetch.spec.whatwg.org/#concept-request-credentials-mode). We could set the
// credentials mode to match using `rel=preload; as=script; omit` but then we lose the
// extra parse/compile step that `rel=modulepreload` gives.
// Also as a note: `<script type="module">` with no `crossorigin` attribute
// indicates a credentials mode of `omit` so you will run into CORS issues with a
// naive `Link: <thing_to_load.js>; rel=preload; as=script;` because it defaults to
// `same-origin` and there is a mismatch. (see
// https://developer.chrome.com/blog/modulepreload/#ok-so-why-doesnt-link-relpreload-work-for-modules)
// (and spec: https://html.spec.whatwg.org/multipage/links.html#link-type-preload ->
// https://fetch.spec.whatwg.org/#concept-request-credentials-mode). There isn't a way
// to make the link match `omit`. You could update both the link and `<script
// type="module">` to one of the other `crossorigin` values though.
//
// See https://developer.chrome.com/blog/modulepreload/#ok-so-why-doesnt-link-relpreload-work-for-modules
// Spec: https://html.spec.whatwg.org/multipage/links.html#link-type-modulepreload
const scriptLinks = preloadScripts.map((scriptUrl) => {
return `<${scriptUrl}>; rel=modulepreload`;
Expand Down