System Info
rspack main (also reproduces on the feat/hmr-precise-css-updates branch, PR #14682)
Details
When a compilation contains no native CSS module at all, CssPlugin does not inject CssLoadingRuntimeModule (and with it the __webpack_require__.hmrC.css download handler): the injection is gated on HAS_CSS_MODULES | CSS_INJECT_STYLE | CSS_STYLE_SHEET (crates/rspack_plugin_css/src/plugin/impl_plugin_for_css_plugin.rs).
If a hot update then adds the first native CSS import, the new compilation emits the stylesheet asset (and, with #14682, lists the chunk in the manifest's css.c), but hotCheck enumerates the hmrC handlers of the old runtime — updated runtime modules only take effect in the apply phase. Since the old runtime never registered hmrC.css, nobody requests the stylesheet: the JS part of the update applies fine while the styles silently never show up until a full reload.
Note the asymmetry: CssExtractRspackPlugin injects its css loading runtime whenever HMR_DOWNLOAD_UPDATE_HANDLERS (or ENSURE_CHUNK_HANDLERS) is required (crates/rspack_plugin_extract_css/src/plugin.rs), i.e. always under HMR, so the same "first stylesheet ever" scenario works for extracted CSS. The native CSS runtime should follow the same rule: when HMR is enabled, register the css HMR handler even if the current compilation has no CSS modules yet.
Reproduce
rspack.config.js:
const { rspack } = require('@rspack/core');
module.exports = {
context: __dirname,
mode: 'development',
entry: { main: './src/index.js' },
plugins: [new rspack.HtmlRspackPlugin({ template: './src/index.html' })],
module: {
rules: [{ test: /\.css$/, type: 'css' }],
},
};
src/index.js (no css import yet):
document.getElementById('root').textContent = 'no css yet';
import.meta.webpackHot.accept();
src/blue.css:
body {
background-color: rgb(163, 255, 255);
}
rspack dev, open the page — no stylesheet, as expected.
- Add the first css import to
src/index.js:
+import './blue.css';
document.getElementById('root').textContent = 'no css yet';
Expected: the hot update loads main.css and the background turns blue (this is what happens with CssExtractRspackPlugin in the same scenario).
Actual: the JS update applies, no CSS request is made, the page stays unstyled until a manual reload.
A playwright assertion against this setup fails with the background stuck at rgba(0, 0, 0, 0) while the same test shape passes for CssExtractRspackPlugin (see tests/e2e/cases/css/hmr-css-added on #14682).
System Info
rspack
main(also reproduces on thefeat/hmr-precise-css-updatesbranch, PR #14682)Details
When a compilation contains no native CSS module at all,
CssPlugindoes not injectCssLoadingRuntimeModule(and with it the__webpack_require__.hmrC.cssdownload handler): the injection is gated onHAS_CSS_MODULES | CSS_INJECT_STYLE | CSS_STYLE_SHEET(crates/rspack_plugin_css/src/plugin/impl_plugin_for_css_plugin.rs).If a hot update then adds the first native CSS import, the new compilation emits the stylesheet asset (and, with #14682, lists the chunk in the manifest's
css.c), buthotCheckenumerates thehmrChandlers of the old runtime — updated runtime modules only take effect in the apply phase. Since the old runtime never registeredhmrC.css, nobody requests the stylesheet: the JS part of the update applies fine while the styles silently never show up until a full reload.Note the asymmetry:
CssExtractRspackPlugininjects its css loading runtime wheneverHMR_DOWNLOAD_UPDATE_HANDLERS(orENSURE_CHUNK_HANDLERS) is required (crates/rspack_plugin_extract_css/src/plugin.rs), i.e. always under HMR, so the same "first stylesheet ever" scenario works for extracted CSS. The native CSS runtime should follow the same rule: when HMR is enabled, register the css HMR handler even if the current compilation has no CSS modules yet.Reproduce
rspack.config.js:src/index.js(no css import yet):src/blue.css:rspack dev, open the page — no stylesheet, as expected.src/index.js:+import './blue.css'; document.getElementById('root').textContent = 'no css yet';Expected: the hot update loads
main.cssand the background turns blue (this is what happens withCssExtractRspackPluginin the same scenario).Actual: the JS update applies, no CSS request is made, the page stays unstyled until a manual reload.
A playwright assertion against this setup fails with the background stuck at
rgba(0, 0, 0, 0)while the same test shape passes forCssExtractRspackPlugin(seetests/e2e/cases/css/hmr-css-addedon #14682).