Skip to content

Commit 9a30989

Browse files
committed
fix(styled-components): fix race condition
1 parent 2820a1c commit 9a30989

File tree

4 files changed

+37
-9
lines changed

4 files changed

+37
-9
lines changed

packages/smooth-plugin-styled-components/src/smooth-node.js

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,20 +19,34 @@ export function onCreateBabelConfig({ actions }, pluginOptions) {
1919
})
2020
}
2121

22-
const sheetByPathname = new Map()
22+
const sheetConfigByRequestId = new Map()
2323

2424
// eslint-disable-next-line react/prop-types,react/display-name
25-
export function wrapRootElement({ element, pathname }) {
25+
export function wrapRootElement({ element, requestId }) {
2626
const sheet = new ServerStyleSheet()
27-
sheetByPathname.set(pathname, sheet)
27+
28+
// Sheet is automatically disposed after 2min to prevent memory leaks
29+
const disposeTimeout = setTimeout(() => {
30+
// eslint-disable-next-line no-use-before-define
31+
dispose()
32+
}, 120000)
33+
34+
function dispose() {
35+
sheetConfigByRequestId.delete(requestId)
36+
clearTimeout(disposeTimeout)
37+
}
38+
39+
const sheetConfig = { sheet, dispose }
40+
sheetConfigByRequestId.set(requestId, sheetConfig)
2841
return <StyleSheetManager sheet={sheet.instance}>{element}</StyleSheetManager>
2942
}
3043

31-
export function onRenderBody({ setHeadComponents, pathname }) {
32-
const sheet = sheetByPathname.get(pathname)
33-
if (sheet) {
44+
export function onRenderBody({ setHeadComponents, requestId }) {
45+
const sheetConfig = sheetConfigByRequestId.get(requestId)
46+
if (sheetConfig) {
47+
const { sheet, dispose } = sheetConfig
3448
setHeadComponents([sheet.getStyleElement()])
35-
sheetByPathname.delete(pathname)
49+
dispose()
3650

3751
// Prevent cache bugs
3852
if (process.env.NODE_ENV !== 'production') {

packages/smooth/src/plugin/nodeHooks/onRenderBody.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ export const onRenderBody = config => ({
88
postBodyComponents = [],
99
bodyProps = {},
1010
pathname,
11+
requestId,
1112
}) => {
1213
function setHeadComponents(components) {
1314
headComponents = [...headComponents, ...components]
@@ -35,6 +36,7 @@ export const onRenderBody = config => ({
3536

3637
applyHook(config, 'onRenderBody', {
3738
pathname,
39+
requestId,
3840
setHeadComponents,
3941
setHtmlAttributes,
4042
setBodyAttributes,
Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
11
import { applyHook } from '../node'
22

3-
export const wrapRootElement = config => ({ element, pathname }) =>
4-
applyHook(config, 'wrapRootElement', { element, pathname }, 'element')
3+
export const wrapRootElement = config => ({ element, pathname, requestId }) =>
4+
applyHook(
5+
config,
6+
'wrapRootElement',
7+
{ element, pathname, requestId },
8+
'element',
9+
)

packages/smooth/src/server/ssr.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,15 @@ export default function ssrMiddleware({
5757
</ErrorContextProvider>
5858
)
5959

60+
// Generate unique request id
61+
const requestId = Math.random()
62+
.toString(36)
63+
.substring(7)
64+
6065
const rootElement = wrapRootElement(config)({
6166
element: jsx,
6267
pathname: req.url,
68+
requestId,
6369
})
6470

6571
// Loadable components
@@ -95,6 +101,7 @@ export default function ssrMiddleware({
95101
headComponents,
96102
postBodyComponents,
97103
pathname: req.url,
104+
requestId,
98105
})
99106

100107
const html = renderToString(<Html {...pluginProps} body={appHtml} />)

0 commit comments

Comments
 (0)