Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 28 additions & 12 deletions src/loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,22 +17,32 @@ import schema from './loader-options.json';
const pluginName = 'mini-css-extract-plugin';

function hotLoader(content, context) {
const accept = context.locals
? ''
: 'module.hot.accept(undefined, cssReload);';

return `${content}
if(module.hot) {
// ${Date.now()}
var cssReload = require(${loaderUtils.stringifyRequest(
var varifyLocal = function(a, b) {
var key, idx = 0;
for(key in a) {
if(!b || a[key] !== b[key]) return false;
idx++;
}
for(key in b) idx--;
return idx === 0;
};
var update = require(${loaderUtils.stringifyRequest(
context.context,
path.join(__dirname, 'hmr/hotModuleReplacement.js')
)})(module.id, ${JSON.stringify({
...context.options,
locals: !!context.locals,
})});
module.hot.dispose(cssReload);
${accept}
var cssReload = function () {
var newContent = require(${context.localsPath});
var localMatch = varifyLocal(content.locals, newContent.locals);
if (!localMatch) throw new Error('Aborting CSS HMR due to changed css-modules locals.');
update();
};
module.hot.accept(${context.localsPath}, function () { cssReload(); });
module.hot.dispose(function () { update(); });
}
`;
}
Expand Down Expand Up @@ -203,18 +213,24 @@ export function pitch(request) {
return callback(e);
}

const localsPath = loaderUtils.stringifyRequest(this, `!!${request}`);
const esModule =
typeof options.esModule !== 'undefined' ? options.esModule : false;
const result = locals
? `\n${esModule ? 'export default' : 'module.exports ='} ${JSON.stringify(
locals
)};`
? `\nvar content = require(${localsPath});\n${
esModule ? 'export default' : 'module.exports ='
} content.locals || {};`
: '';

let resultSource = `// extracted by ${pluginName}`;

resultSource += options.hmr
? hotLoader(result, { context: this.context, options, locals })
? hotLoader(result, {
context: this.context,
options,
locals,
localsPath,
})
: result;

return callback(null, resultSource);
Expand Down
2 changes: 1 addition & 1 deletion test/cases/hmr/expected/webpack-4/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@
/***/ (function(module, exports, __webpack_require__) {

// extracted by mini-css-extract-plugin
if(false) { var cssReload; }
if(false) { var cssReload, update, varifyLocal; }


/***/ })
Expand Down
4 changes: 4 additions & 0 deletions test/manual/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@
<p>CrossOriginLoading Option: Must be red.</p>
<p><button>Pressing this button</button> loads chunks with crossorigin attribute and should turn green.</p>
</div>
<div class="test hmr">
<div class="hmr-a">With CSS Module, if locals didn't change, we can hmr update style</div>
<div class="hmr-b">If locals changed, it will trigger a full reload of the page.</div>
</div>
<div class="errors"></div>
<script async defer src="/dist/main.js"></script>
</body>
Expand Down
9 changes: 9 additions & 0 deletions test/manual/src/hmr-module.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/* eslint-env browser */
import style from './hmr-module.module.css';

export default function hmrBootstrap() {
// should not log again if only css changed
// eslint-disable-next-line
console.log('load');
document.querySelector('.hmr-a').classList.add(style.a);
}
16 changes: 16 additions & 0 deletions test/manual/src/hmr-module.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
:local(.a) {
/* change inner style can update with hmr */
background-color: pink;
height: 20px;
}

:global(.hmr-b) {
/* global className works fine in a css-module */
background-color: skyblue;
height: 20px;
}

/* remove or add new local module would cause full reload */
/* :local(.c) {
background-color: khaki;
} */
3 changes: 3 additions & 0 deletions test/manual/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import './initial.css';
import './simple.css';
import classes from './simple.module.css';
import hmrBootstrap from './hmr-module';

console.log('___CLASSES__');
console.log(classes);
Expand Down Expand Up @@ -69,3 +70,5 @@ makeButton('.crossorigin', () => {
__webpack_public_path__ = originalPublicPath;
return promise;
});

hmrBootstrap();