Skip to content

Commit

Permalink
Add missing module.hot.accept call to server CSS modules (#47913)
Browse files Browse the repository at this point in the history
Since we compile global server CSS imports into a special module with a
checksum of the original content, it should always accept HMR updates.
This fixes `Fast Refresh had to perform a full reload` errors.
  • Loading branch information
shuding authored Apr 4, 2023
1 parent a3acbf4 commit 2eeb0c7
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 4 deletions.
16 changes: 12 additions & 4 deletions packages/next/src/build/webpack/loaders/next-flight-css-loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,20 @@ const NextServerCSSLoader = function (this: any, content: string) {
.substring(0, 12)

if (isCSSModule) {
return (
content + '\nmodule.exports.__checksum = ' + JSON.stringify(checksum)
)
return `\
${content}
module.exports.__checksum = ${JSON.stringify(checksum)}
`
}

return `export default ${JSON.stringify(checksum)}`
// Server CSS imports are always available for HMR, so we attach
// `module.hot.accept()` to the generated module.
const hmrCode = 'if (module.hot) { module.hot.accept() }'

return `\
export default ${JSON.stringify(checksum)}
${hmrCode}
`
}

return content
Expand Down
3 changes: 3 additions & 0 deletions test/e2e/app-dir/app-css/app/hmr/global.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
body {
background: gray;
}
5 changes: 5 additions & 0 deletions test/e2e/app-dir/app-css/app/hmr/page.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import './global.css'

export default function Page() {
return <div>hello!</div>
}
20 changes: 20 additions & 0 deletions test/e2e/app-dir/app-css/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -496,6 +496,26 @@ createNextDescribe(
await next.patchFile(filePath, origContent)
}
})

it('should not break HMR when CSS is imported in a server component', async () => {
const filePath = 'app/hmr/page.js'
const origContent = await next.readFile(filePath)

const browser = await next.browser('/hmr')
await browser.eval(`window.__v = 1`)
try {
await next.patchFile(
filePath,
origContent.replace('hello!', 'hmr!')
)
await check(() => browser.elementByCss('body').text(), 'hmr!')

// Make sure it doesn't reload the page
expect(await browser.eval(`window.__v`)).toBe(1)
} finally {
await next.patchFile(filePath, origContent)
}
})
}
})

Expand Down

0 comments on commit 2eeb0c7

Please sign in to comment.