Skip to content

Commit

Permalink
Fixed an issue with multiple Emotion caches moving SSRed styles to he…
Browse files Browse the repository at this point in the history
…ad at their initialization times
  • Loading branch information
Andarist committed Oct 2, 2020
1 parent 5d094b5 commit 7719cf3
Show file tree
Hide file tree
Showing 14 changed files with 157 additions and 5 deletions.
5 changes: 5 additions & 0 deletions .changeset/gentle-owls-chew.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@emotion/sheet': patch
---

Generated style elements got `data-s="1"` attribute so `@emotion/cache` can recognize them as being already owned by another Emotion copy to avoid messing up existing style elements when initializing a new copy.
5 changes: 5 additions & 0 deletions .changeset/proud-bats-cheer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@emotion/cache': patch
---

Fixed an issue with Emotion messing up style elements already processed by previously initialized Emotion copy.
2 changes: 2 additions & 0 deletions packages/cache/__tests__/__snapshots__/hydration.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ exports[`it works 1`] = `
<head>
<style
data-emotion="css 1lrxbo5"
data-s=""
>
.css-1lrxbo5{color:hotpink;}
</style>
Expand All @@ -18,6 +19,7 @@ exports[`rehydrated styles to head can be flushed 1`] = `
<head>
<style
data-emotion="emo 1lrxbo5"
data-s=""
>
.emo-1lrxbo5{color:hotpink;}
</style>
Expand Down
10 changes: 5 additions & 5 deletions packages/cache/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ let getServerStylisCache = isBrowser
)

const defaultStylisPlugins = [prefixer]
let movedStyles = false

let createCache = (options: Options): EmotionCache => {
let key = options.key
Expand All @@ -53,14 +52,15 @@ let createCache = (options: Options): EmotionCache => {
)
}

if (isBrowser && !movedStyles && key === 'css') {
movedStyles = true

const ssrStyles = document.querySelectorAll(`style[data-emotion]`)
if (isBrowser && key === 'css') {
const ssrStyles = document.querySelectorAll(
`style[data-emotion]:not([data-s])`
)
// get SSRed styles out of the way of React's hydration
// document.head is a safe place to move them to
Array.prototype.forEach.call(ssrStyles, (node: HTMLStyleElement) => {
;((document.head: any): HTMLHeadElement).appendChild(node)
node.setAttribute('data-s', '')
})
}

Expand Down
1 change: 1 addition & 0 deletions packages/css/test/__snapshots__/sheet.dom.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ exports[`sheet tags 1`] = `
Array [
<style
data-emotion="css"
data-s=""
>
</style>,
Expand Down
3 changes: 3 additions & 0 deletions packages/react/__tests__/__snapshots__/at-import.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ exports[`basic 1`] = `
<head>
<style
data-emotion="css-global"
data-s=""
>
</style>
<style
data-emotion="css"
data-s=""
>
</style>
Expand All @@ -31,6 +33,7 @@ exports[`basic 4`] = `
<head>
<style
data-emotion="css"
data-s=""
>
</style>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@ exports[`array 1`] = `
<head>
<style
data-emotion="css-global"
data-s=""
>
html{background-color:green;}
</style>
<style
data-emotion="css-global"
data-s=""
>
html{font-size:16px;}
Expand Down Expand Up @@ -40,6 +42,7 @@ exports[`basic 1`] = `
<head>
<style
data-emotion="css-global"
data-s=""
>
html{background-color:green;}
Expand Down
14 changes: 14 additions & 0 deletions packages/react/__tests__/__snapshots__/global.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -4,42 +4,49 @@ exports[`basic 1`] = `
<head>
<style
data-emotion="css"
data-s=""
>
.css-animation-ocj8pk{}
</style>
<style
data-emotion="css"
data-s=""
>
@-webkit-keyframes animation-ocj8pk{from,to{color:green;}50%{color:hotpink;}}
</style>
<style
data-emotion="css"
data-s=""
>
@keyframes animation-ocj8pk{from,to{color:green;}50%{color:hotpink;}}
</style>
<style
data-emotion="css-global"
data-s=""
>
@import url('something.com/file.css');
</style>
<style
data-emotion="css-global"
data-s=""
>
html{background-color:hotpink;}
</style>
<style
data-emotion="css-global"
data-s=""
>
h1{-webkit-animation:animation-ocj8pk 1s;animation:animation-ocj8pk 1s;}
</style>
<style
data-emotion="css-global"
data-s=""
>
@font-face{font-family:some-name;}
Expand All @@ -59,18 +66,21 @@ exports[`basic 3`] = `
<head>
<style
data-emotion="css"
data-s=""
>
.css-animation-ocj8pk{}
</style>
<style
data-emotion="css"
data-s=""
>
@-webkit-keyframes animation-ocj8pk{from,to{color:green;}50%{color:hotpink;}}
</style>
<style
data-emotion="css"
data-s=""
>
@keyframes animation-ocj8pk{from,to{color:green;}50%{color:hotpink;}}
Expand All @@ -90,12 +100,14 @@ exports[`updating more than 1 global rule 1`] = `
<head>
<style
data-emotion="global-multiple-rules-global"
data-s=""
>
body{background:white;}
</style>
<style
data-emotion="global-multiple-rules-global"
data-s=""
>
div{color:black;}
Expand All @@ -107,12 +119,14 @@ exports[`updating more than 1 global rule 2`] = `
<head>
<style
data-emotion="global-multiple-rules-global"
data-s=""
>
body{background:gray;}
</style>
<style
data-emotion="global-multiple-rules-global"
data-s=""
>
div{color:white;}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@ exports[`specificity with globals 1`] = `
<head>
<style
data-emotion="css-global"
data-s=""
>
.some-class{color:green;}
</style>
<style
data-emotion="css"
data-s=""
>
.css-1ndtvd6{color:hotpink;}
Expand Down Expand Up @@ -40,12 +42,14 @@ exports[`specificity with globals 2`] = `
<head>
<style
data-emotion="css-global"
data-s=""
>
.some-class{color:yellow;}
</style>
<style
data-emotion="css"
data-s=""
>
.css-1ndtvd6{color:hotpink;}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ exports[`composition works from old emotion css calls 1`] = `
<head>
<style
data-emotion="css"
data-s=""
>
.css-ulmpz9{color:green;}
Expand Down
103 changes: 103 additions & 0 deletions packages/react/__tests__/rehydration.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,106 @@ test("cache created in render doesn't cause a hydration mismatch", () => {
expect((console.error: any).mock.calls).toMatchInlineSnapshot(`Array []`)
expect((console.warn: any).mock.calls).toMatchInlineSnapshot(`Array []`)
})

test('initializing another Emotion instance should not move already moved styles elements', () => {
safeQuerySelector('head').innerHTML = '<div id="style-container"></div>'
safeQuerySelector('body').innerHTML = [
'<div id="root">',
'<style data-emotion="stl 1pdkrhd">.stl-1pdkrhd-App {color: hotpink;}</style>',
'<div class="stl-1pdkrhd-App">Hello world!</div>',
'</div>'
].join('')

resetAllModules()

const cache = createCache({
key: 'stl',
container: safeQuerySelector('#style-container')
})

function App() {
return (
<CacheProvider value={cache}>
<div
css={css`
color: hotpink;
`}
>
{'Hello world!'}
</div>
</CacheProvider>
)
}

ReactDOM.hydrate(<App />, safeQuerySelector('#root'))

resetAllModules()

expect(safeQuerySelector('head')).toMatchInlineSnapshot(`
<head>
<div
id="style-container"
>
<style
data-emotion="stl 1pdkrhd"
data-s=""
>
.stl-1pdkrhd-App {color: hotpink;}
</style>
<style
data-emotion="stl"
data-s=""
>
.stl-1pdkrhd-App{color:hotpink;}
</style>
</div>
</head>
`)
})

test('initializing another Emotion instance should not move already moved styles elements', () => {
safeQuerySelector('head').innerHTML = '<div id="style-container"></div>'
safeQuerySelector('body').innerHTML = '<div id="root"></div>'

resetAllModules()

const cache = createCache({
key: 'stl',
container: safeQuerySelector('#style-container')
})

function App() {
return (
<CacheProvider value={cache}>
<div
css={css`
color: hotpink;
`}
>
{'Hello world!'}
</div>
</CacheProvider>
)
}

ReactDOM.render(<App />, safeQuerySelector('#root'))

resetAllModules()

expect(safeQuerySelector('head')).toMatchInlineSnapshot(`
<head>
<div
id="style-container"
>
<style
data-emotion="stl"
data-s=""
>
.stl-1pdkrhd-App{color:hotpink;}
</style>
</div>
</head>
`)
})
Loading

0 comments on commit 7719cf3

Please sign in to comment.