Preload fonts and images (#187)
Part of https://github.com/matrix-org/matrix-public-archive/issues/132
This commit is contained in:
parent
f0a11139cb
commit
e20a67d2ba
|
@ -30,6 +30,7 @@ function getEntryPoints() {
|
|||
return _entryPoints;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line max-statements
|
||||
function recurseManifestEntryName(entryName) {
|
||||
const manifest = getManifest();
|
||||
const entry = manifest[entryName];
|
||||
|
@ -38,6 +39,9 @@ function recurseManifestEntryName(entryName) {
|
|||
|
||||
// css
|
||||
const styles = [];
|
||||
// assets
|
||||
const fonts = [];
|
||||
const images = [];
|
||||
// imports
|
||||
const scripts = [entryFilePath];
|
||||
// imports, dynamicImports
|
||||
|
@ -50,11 +54,15 @@ function recurseManifestEntryName(entryName) {
|
|||
|
||||
const {
|
||||
styles: moreStyles,
|
||||
fonts: moreFonts,
|
||||
images: moreImages,
|
||||
scripts: moreScripts,
|
||||
preloadScripts: morePreloadScripts,
|
||||
} = recurseManifestEntryName(importName);
|
||||
|
||||
styles.push(...moreStyles);
|
||||
fonts.push(...moreFonts);
|
||||
images.push(...moreImages);
|
||||
scripts.push(...moreScripts);
|
||||
preloadScripts.push(...morePreloadScripts);
|
||||
}
|
||||
|
@ -65,11 +73,15 @@ function recurseManifestEntryName(entryName) {
|
|||
|
||||
const {
|
||||
styles: moreStyles,
|
||||
fonts: moreFonts,
|
||||
images: moreImages,
|
||||
scripts: moreScripts,
|
||||
preloadScripts: morePreloadScripts,
|
||||
} = recurseManifestEntryName(dynamicImportName);
|
||||
|
||||
styles.push(...moreStyles);
|
||||
fonts.push(...moreFonts);
|
||||
images.push(...moreImages);
|
||||
scripts.push(...moreScripts);
|
||||
preloadScripts.push(...morePreloadScripts);
|
||||
}
|
||||
|
@ -78,9 +90,36 @@ function recurseManifestEntryName(entryName) {
|
|||
styles.push(path.join('/', cssName));
|
||||
}
|
||||
|
||||
for (const assetName of entry.assets || []) {
|
||||
const assetFileExtension = path.extname(assetName);
|
||||
const assetFilePath = path.join('/', assetName);
|
||||
|
||||
if (
|
||||
// We only care about preloading `.woff2` fonts since that is all of the major
|
||||
// browsers support them.
|
||||
['.woff2'].includes(assetFileExtension) &&
|
||||
// We only care about a few variants that we will actually likely use on the page
|
||||
// (this may need to change over time).
|
||||
['-Regular-', '-Bold-', '-SemiBold-'].some((variant) => assetName.includes(variant))
|
||||
) {
|
||||
fonts.push(path.join('/', assetFilePath));
|
||||
} else if (
|
||||
// Preload a specific file we use on the room directory homepage
|
||||
assetName.includes('matrix-lines-hero')
|
||||
// We don't care about preloading *all* images at the moment because there are a
|
||||
// lot that we just don't use even though they are bundled because they are
|
||||
// referened in the CSS.
|
||||
//['.jpg', '.png', '.svg'].includes(assetFileExtension)
|
||||
) {
|
||||
images.push(path.join('/', assetFilePath));
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
// css
|
||||
styles,
|
||||
fonts,
|
||||
images,
|
||||
// imports
|
||||
scripts,
|
||||
// dynamicImports
|
||||
|
@ -103,11 +142,14 @@ function getDependenciesForEntryPointName(entryPointName) {
|
|||
)}`
|
||||
);
|
||||
|
||||
const { styles, scripts, preloadScripts } = recurseManifestEntryName(entryPointName);
|
||||
const { styles, fonts, images, scripts, preloadScripts } =
|
||||
recurseManifestEntryName(entryPointName);
|
||||
|
||||
return {
|
||||
// De-duplicate assets
|
||||
styles: Array.from(new Set(styles)),
|
||||
fonts: Array.from(new Set(fonts)),
|
||||
images: Array.from(new Set(images)),
|
||||
scripts: Array.from(new Set(scripts)),
|
||||
preloadScripts: Array.from(new Set(preloadScripts)),
|
||||
};
|
||||
|
|
|
@ -16,13 +16,17 @@ function setHeadersToPreloadAssets(res, pageOptions) {
|
|||
assert(pageOptions);
|
||||
assert(pageOptions.entryPoint);
|
||||
|
||||
const { styles, preloadScripts } = getDependenciesForEntryPointName(pageOptions.entryPoint);
|
||||
const { styles, fonts, images, preloadScripts } = getDependenciesForEntryPointName(
|
||||
pageOptions.entryPoint
|
||||
);
|
||||
|
||||
// Work on assembling the `Link` headers
|
||||
//
|
||||
// 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
|
||||
|
@ -32,16 +36,19 @@ function setHeadersToPreloadAssets(res, pageOptions) {
|
|||
return `<${styleUrl}>; rel=preload; as=style`;
|
||||
});
|
||||
|
||||
// TODO: We should preload fonts as well.
|
||||
//
|
||||
// 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; crossorigin`
|
||||
const fontLinks = fonts.map((fontUrl) => {
|
||||
return `<${fontUrl}>; rel=preload; as=font; crossorigin`;
|
||||
});
|
||||
|
||||
const imageLinks = images.map((imageUrl) => {
|
||||
return `<${imageUrl}>; rel=preload; as=image`;
|
||||
});
|
||||
|
||||
// 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
|
||||
|
@ -63,7 +70,7 @@ function setHeadersToPreloadAssets(res, pageOptions) {
|
|||
return `<${scriptUrl}>; rel=modulepreload`;
|
||||
});
|
||||
|
||||
res.append('Link', [].concat(styleLinks, scriptLinks).join(', '));
|
||||
res.append('Link', [].concat(styleLinks, fontLinks, imageLinks, scriptLinks).join(', '));
|
||||
}
|
||||
|
||||
module.exports = setHeadersToPreloadAssets;
|
||||
|
|
Loading…
Reference in New Issue