emotion version: 8.0.12react version: 16.1.1Relevant code.
EmotionServer.extractCritical(ReactDOM.renderToString(...))
What you did:
I'm following the instructions to implement emotion with SSR.
What happened:
Everything works perfectly on the first request. On the 2nd request though, I still get emotion ids that were generated in the previous request.
Reproduction:
Will try to provide this if necessary.
Problem description:
From initial investigation, it looks like the issue is that { sheet, inserted, registered } from emotion are never cleaned up.
Suggested solution:
I'm still investigating. Any help would be greatly appreciated!
Calling EmotionServer.flush() seems to fix the issue. Here's what I tried:
import express from 'express'
import ReactDOM from 'react-dom/server'
import * as EmotionServer from 'emotion-server'
const app = express()
// ...
app.get('*', async (req, res, next) => {
try {
// ...
const { html, ids, css } = EmotionServer.extractCritical(ReactDOM.renderToString(<App />))
// ...
} catch(err) {
next(err)
} finally {
EmotionServer.flush()
}
})
Should we add a section about this to the docs? I personally would prefer if emotion-server handled this automatically, but I'm not sure if that's possible.
Cleaning up the caches between the requests would break most people's apps since if you use injectGlobal, css or keyframes out of a render path those styles won't be regenerated on each render and therefore won't be in the critical css. The only styles that should stay from request to request are global styles and keyframes, are styles from css or styled staying?
I only have a single file using emotion:
import React from 'react'
import PropTypes from 'prop-types'
import styled from 'react-emotion'
import { MAX_CONTENT_WIDTH } from 'components/constants'
const Root = styled.div`
padding-left: 20px;
padding-right: 20px;
`
const Container = styled.div`
margin: 0 auto;
padding: 0 0 40px;
max-width: ${MAX_CONTENT_WIDTH}px;
`
const NewsItem = styled.article`
margin: 0 0 2rem;
`
const NewsTitle = styled.h1`
font-size: 1.5rem;
`
const NewsDesc = styled.div`
h1,
h2,
h3,
h4,
h5,
h6 {
font-size: 1.125rem;
}
pre {
white-space: pre-wrap;
font-size: 0.875rem;
}
img {
max-width: 100%;
}
`
class Home extends React.Component {
// ...
}
I'm only using styled, no global styles or keyframes.
Could you provide a reproduction as a repo?
By looking at the source code, I see the objects inserted and registered are growing unbounded. There's no part of the code that clears values from there except flush. And flush is never called, unless I do that manually after each request.
We only return global styles and styles that are actually used in the html so we don't need to clear it.
@mitchellhamilton I agree. We do exactly that for styles. But for ids, we return everything:
https://github.com/emotion-js/emotion/blob/v8.0.12/packages/emotion-server/src/index.js#L26-L28
I'll try to provide a quick repro soon.
The filter call that's there should remove the unused ids.
Here's a simple repro based on react-starter-kit: https://github.com/mdebbar/react-starter-kit/tree/emotion (the last commit is the only relevant commit).
To reproduce the issue:
emotion branch.yarnyarn startview-source:http://localhost:3000/aboutemotionIds and see an empty array.view-source:http://localhost:3000/emotionIds and see an array of 5 items.view-source:http://localhost:3000/aboutemotionIds array has 5 items too.This is because of autoLabel and the keys that were used on the caches in Emotion 8. It's fixed in Emotion 9.
@mitchellhamilton Ahhh I think you're right. I disabled autoLabel and I don't see the bug anymore. Is emotion 9 ready for prime time? I think it's not even published yet.
It's on the next tag on npm. As long as you lock your version because there may be breaking changes between versions while it's in beta and read the CHANGELOG when updating, Emotion 9 is ready to use.
yarn add emotion@next react-emotion@next babel-plugin-emotion@next emotion-server@next
Thanks @mitchellhamilton! I'll close the issue and update the title to mention autoLabel being the cause.
Most helpful comment
Thanks @mitchellhamilton! I'll close the issue and update the title to mention
autoLabelbeing the cause.