Skip to content

Commit

Permalink
fix: don't inline link stylesheets for more predictable behaviour
Browse files Browse the repository at this point in the history
Inlining link stylesheets has unexpected side effects as browsers serialize the styles. This can cause styles to become invalid in certain circumstanecs, such as those outline in #454.

This fix removes inlining of link styles, which may come at a performance cost. However, inlining was implemented before further performance optimisations were made, so the impact may be negliable. We should publish a canary to assess the impact.
  • Loading branch information
chrisvxd committed Apr 20, 2024
1 parent 202611e commit 1e3d1e7
Showing 1 changed file with 16 additions and 17 deletions.
33 changes: 16 additions & 17 deletions packages/core/components/AutoFrame/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React, { ReactNode, useEffect } from "react";
import Frame, { FrameComponentProps, useFrame } from "react-frame-component";
import hash from "object-hash";

const styleSelector = 'style, link[as="style"], link[rel="stylesheet"]';
const styleSelector = 'style, link[rel="stylesheet"]';

const collectStyles = (doc: Document) => {
const collected: HTMLElement[] = [];
Expand Down Expand Up @@ -61,10 +61,10 @@ const CopyHostStyles = ({
const lookupEl = (el: HTMLElement) =>
elements.findIndex((elementMap) => elementMap.original === el);

const mirrorEl = async (el: HTMLElement, onLoad: () => void = () => {}) => {
const mirrorEl = async (el: HTMLElement, inlineStyles = false) => {
let mirror: HTMLStyleElement;

if (el.nodeName === "LINK") {
if (el.nodeName === "LINK" && inlineStyles) {
mirror = document.createElement("style") as HTMLStyleElement;
mirror.type = "text/css";

Expand Down Expand Up @@ -101,12 +101,10 @@ const CopyHostStyles = ({
mirror = el.cloneNode(true) as HTMLStyleElement;
}

mirror.onload = onLoad;

return mirror;
};

const addEl = async (el: HTMLElement, onLoad: () => void = () => {}) => {
const addEl = async (el: HTMLElement) => {
const index = lookupEl(el);
if (index > -1) {
if (debug)
Expand All @@ -116,16 +114,12 @@ const CopyHostStyles = ({

elements[index].mirror.innerText = el.innerText;

onLoad();

return;
}

const mirror = await mirrorEl(el, onLoad);
const mirror = await mirrorEl(el);

if (!mirror) {
onLoad();

return;
}

Expand All @@ -137,15 +131,11 @@ const CopyHostStyles = ({
`iframe already contains element that is being mirrored. Skipping...`
);

onLoad();

return;
}

hashes[elHash] = true;

mirror.onload = onLoad;

doc.head.append(mirror as HTMLElement);
elements.push({ original: el, mirror: mirror });

Expand Down Expand Up @@ -213,6 +203,7 @@ const CopyHostStyles = ({

const collectedStyles = collectStyles(parentDocument);
const hrefs: string[] = [];
let stylesLoaded = 0;

Promise.all(
collectedStyles.map(async (styleNode, i) => {
Expand Down Expand Up @@ -240,6 +231,16 @@ const CopyHostStyles = ({
(el) => typeof el !== "undefined"
) as HTMLStyleElement[];

filtered.forEach((mirror) => {
mirror.onload = () => {
stylesLoaded = stylesLoaded + 1;

if (stylesLoaded >= elements.length) {
onStylesLoaded();
}
};
});

// Reset HTML (inside the promise) so in case running twice (i.e. for React Strict mode)
doc.head.innerHTML = "";

Expand All @@ -253,8 +254,6 @@ const CopyHostStyles = ({

hashes[elHash] = true;
});

onStylesLoaded();
});

return () => {
Expand Down

0 comments on commit 1e3d1e7

Please sign in to comment.