From bff1a98cda1179a309d5bc448e78c9998ac6489c Mon Sep 17 00:00:00 2001 From: yiminghe Date: Wed, 20 Mar 2024 17:53:07 +0800 Subject: [PATCH] fix: avoid reload all css when hot load --- src/loader.js | 25 +++++++++++++------ test/cases/hmr-locals/index.css | 3 +++ test/cases/hmr-locals/webpack.config.js | 33 +++++++++++++++++++++++++ test/cases/hmr/expected/main.js | 19 +++++++++++--- 4 files changed, 69 insertions(+), 11 deletions(-) create mode 100644 test/cases/hmr-locals/index.css create mode 100644 test/cases/hmr-locals/webpack.config.js diff --git a/src/loader.js b/src/loader.js index 35d8a9ba..49c7a34c 100644 --- a/src/loader.js +++ b/src/loader.js @@ -44,22 +44,31 @@ const MiniCssExtractPlugin = require("./index"); * @returns {string} */ function hotLoader(content, context) { - const accept = context.locals - ? "" - : "module.hot.accept(undefined, cssReload);"; - + const localsJsonString = JSON.stringify(JSON.stringify(context.locals)); return `${content} if(module.hot) { + const localsJsonString = ${localsJsonString}; // ${Date.now()} - var cssReload = require(${stringifyRequest( + const cssReload = require(${stringifyRequest( context.loaderContext, path.join(__dirname, "hmr/hotModuleReplacement.js") )})(module.id, ${JSON.stringify({ ...context.options, - locals: !!context.locals, })}); - module.hot.dispose(cssReload); - ${accept} + // only invalidate when locals change + if ( + module.hot.data && + module.hot.data.value && + module.hot.data.value !== localsJsonString + ) { + module.hot.invalidate(); + } else { + module.hot.accept(); + } + module.hot.dispose(function(data) { + data.value = localsJsonString; + cssReload(); + }); } `; } diff --git a/test/cases/hmr-locals/index.css b/test/cases/hmr-locals/index.css new file mode 100644 index 00000000..739f1581 --- /dev/null +++ b/test/cases/hmr-locals/index.css @@ -0,0 +1,3 @@ +.x { + color: red; +} diff --git a/test/cases/hmr-locals/webpack.config.js b/test/cases/hmr-locals/webpack.config.js new file mode 100644 index 00000000..639b6511 --- /dev/null +++ b/test/cases/hmr-locals/webpack.config.js @@ -0,0 +1,33 @@ +import { HotModuleReplacementPlugin } from "webpack"; + +import Self from "../../../src"; + +module.exports = { + entry: "./index.css", + mode: "development", + devtool: false, + module: { + rules: [ + { + test: /\.css$/, + use: [ + { + loader: Self.loader, + }, + { + loader: "css-loader", + options: { + modules: true, + }, + }, + ], + }, + ], + }, + plugins: [ + new HotModuleReplacementPlugin(), + new Self({ + filename: "[name].css", + }), + ], +}; diff --git a/test/cases/hmr/expected/main.js b/test/cases/hmr/expected/main.js index 39fc3d64..94f27eb5 100644 --- a/test/cases/hmr/expected/main.js +++ b/test/cases/hmr/expected/main.js @@ -363,10 +363,23 @@ __webpack_require__.r(__webpack_exports__); // extracted by mini-css-extract-plugin if(true) { + const localsJsonString = undefined; // - var cssReload = __webpack_require__(/*! ../../../src/hmr/hotModuleReplacement.js */ "../../../src/hmr/hotModuleReplacement.js")(module.id, {"locals":false}); - module.hot.dispose(cssReload); - module.hot.accept(undefined, cssReload); + const cssReload = __webpack_require__(/*! ../../../src/hmr/hotModuleReplacement.js */ "../../../src/hmr/hotModuleReplacement.js")(module.id, {}); + // only invalidate when locals change + if ( + module.hot.data && + module.hot.data.value && + module.hot.data.value !== localsJsonString + ) { + module.hot.invalidate(); + } else { + module.hot.accept(); + } + module.hot.dispose(function(data) { + data.value = localsJsonString; + cssReload(); + }); }