-
-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
I have these changes sitting locally for a very long time, and it's time to offload them. The idea behind the styles rehydration is very simple: we collect all existing styles from `<style data-adeira-sx />` (once) and use this information later for deciding whether the styles should be injected or not (this is what I call rehydration). The difference from the current solution is that we do it only once and we don't have to go through all the styles everytime there is something to inject. Motivation for this change is performance: this should significantly improve the runtime style perf + be much easier to deal with (for example, we are basically brute-forcing @at rules and pseudo rules now). Note: this is just a partial solution, there are other changes coming (custom styles printer and @at nodes/pseudo nodes optimization).
- Loading branch information
Showing
7 changed files
with
258 additions
and
73 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
/** | ||
* @flow | ||
* @jest-environment jsdom | ||
*/ | ||
|
||
/* global document */ | ||
|
||
import { invariant } from '@adeira/js'; | ||
|
||
import rehydrateStyles from '../rehydrateStyles'; | ||
|
||
it('correctly rehydrates styles from a style element', () => { | ||
// First, we need to create a `CSSStyleSheet` by actually creating a style element: | ||
const styleElement = document.createElement('style'); | ||
document.head?.appendChild(styleElement); | ||
const styleSheet = styleElement.sheet; | ||
|
||
invariant(styleSheet != null, 'Unable to create test StyleSheet.'); | ||
|
||
// Insert some simple CSS rules: | ||
styleSheet.insertRule('._2tPCgL { font-size: 10px; }', 0); | ||
styleSheet.insertRule('._1Kmfck:hover { color: rgba(var(--sx-foreground), 0.5); }', 1); | ||
|
||
// Insert some @at rules: | ||
styleSheet.insertRule( | ||
`@media (prefers-reduced-motion: reduce) { .VdrO3.VdrO3 { animation-duration: 1s; } }`, | ||
2, | ||
); | ||
styleSheet.insertRule( | ||
`@media (prefers-reduced-motion: reduce) { ._2tPCgL._2tPCgL { font-size: 10px; } }`, | ||
3, | ||
); | ||
styleSheet.insertRule( | ||
`@keyframes oxCh9 { 33% { transform: translateY(-10px); } 66% { transform: translateY(10px); } } | ||
`, | ||
4, | ||
); | ||
|
||
// We should be able to decide whether the style needs to be injected later based on the | ||
// following information: | ||
expect(rehydrateStyles(styleSheet)).toMatchInlineSnapshot(` | ||
Object { | ||
"rehydratedKeyframeRules": Set { | ||
"oxCh9", | ||
}, | ||
"rehydratedMediaRules": Map { | ||
"(prefers-reduced-motion: reduce)" => Set { | ||
".VdrO3.VdrO3", | ||
"._2tPCgL._2tPCgL", | ||
}, | ||
}, | ||
"rehydratedStyleRules": Set { | ||
"._2tPCgL", | ||
"._1Kmfck:hover", | ||
}, | ||
} | ||
`); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
// @flow | ||
|
||
/* global document */ | ||
|
||
import { invariant } from '@adeira/js'; | ||
|
||
// <style data-adeira-sx /> | ||
opaque type StyleElementType = HTMLStyleElement | null; | ||
let styleAdeiraSXTag: StyleElementType = null; | ||
|
||
/** | ||
* This function will try to get already existing `<style data-adeira-sx />` HTML tag or it will | ||
* create a new virtual one in case it doesn't exist yet. | ||
*/ | ||
export default function getStyleSheetFromStyleTag(): CSSStyleSheet { | ||
if (styleAdeiraSXTag === null) { | ||
styleAdeiraSXTag = ((document.querySelector('style[data-adeira-sx]'): any): StyleElementType); | ||
if (styleAdeiraSXTag === null) { | ||
// Still `null` so let's create the style element: | ||
const htmlHead = document.head; | ||
styleAdeiraSXTag = document.createElement('style'); | ||
styleAdeiraSXTag.type = 'text/css'; | ||
styleAdeiraSXTag.setAttribute('data-adeira-sx', ''); | ||
/* $FlowFixMe[incompatible-call] This comment suppresses an error when | ||
* upgrading Flow. To see the error delete this comment and run Flow. */ | ||
htmlHead?.appendChild(styleAdeiraSXTag); | ||
} | ||
} | ||
|
||
/* $FlowFixMe[incompatible-use] This comment suppresses an error when | ||
* upgrading Flow. To see the error delete this comment and run Flow. */ | ||
const styleSheet = styleAdeiraSXTag.sheet; | ||
|
||
invariant( | ||
styleSheet != null, | ||
'SX cannot apply runtime styles because HTMLStyleElement.sheet does not exist.', | ||
); | ||
|
||
return styleSheet; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.