Skip to content

Instantly share code, notes, and snippets.

@thomaswilburn
Last active February 20, 2024 21:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save thomaswilburn/fab35b632b73b9e0aaf95d2f0fbda91e to your computer and use it in GitHub Desktop.
Save thomaswilburn/fab35b632b73b9e0aaf95d2f0fbda91e to your computer and use it in GitHub Desktop.
Async imports for CSS files
var links = document.querySelectorAll(`link[rel="stylesheet"][media="async"], link[rel="async-styles"]`);
for (var link of links) {
var resolved = new URL(link.href, window.location);
var processed = await getSheet(resolved.toString());
var style = document.createElement("style");
var constructed = new CSSStyleSheet();
var output = serializeCSS(processed);
constructed.replaceSync(output);
// console.log(output);
document.adoptedStyleSheets.push(constructed);
}
function serializeCSS(sheet) {
var output = "";
for (var rule of Array.from(sheet.cssRules)) {
output += rule.cssText + "\n";
}
return output;
}
async function getSheet(url, cache = new Set()) {
if (cache.has(url)) {
console.log(`Skipping import for ${url}, already loaded elsewhere`);
return { cssRules: [], url }
}
cache.add(url);
var response = await fetch(url);
var text = await response.text();
var sheet = parseSheet(text);
sheet.url = url;
var processed = await processSheet(sheet, cache);
return processed;
}
function parseSheet(text) {
var parser = new DOMParser();
var html = parser.parseFromString(`<style>${text}</style>`, "text/html");
var style = html.querySelector("style");
return style.sheet;
}
async function processSheet(stylesheet, cache) {
for (var i = 0; i < stylesheet.cssRules.length; i++) {
var rule = stylesheet.cssRules[i];
if (rule instanceof CSSImportRule) {
stylesheet.deleteRule(i);
var resolved = new URL(rule.href, stylesheet.url).toString();
var imported = await getSheet(resolved, cache);
for (var j = imported.cssRules.length - 1; j >= 0; j--) {
var insert = imported.cssRules[j];
stylesheet.insertRule(insert.cssText, i);
}
i += imported.cssRules.length;
}
}
return stylesheet;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment