Skip to content

Commit 192d9af

Browse files
committed
feat: add option to enable/disable HMR (options.hmr)
1 parent ce53bd9 commit 192d9af

File tree

5 files changed

+97
-24
lines changed

5 files changed

+97
-24
lines changed

README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ Styles are not added on `import/require()`, but instead on call to `use`/`ref`.
134134

135135
|Name|Type|Default|Description|
136136
|:--:|:--:|:-----:|:----------|
137+
|**`hmr`**|`{Boolean}`|`true`|Enable/disable Hot Module Replacement (HMR), if disabled no HMR Code will be added (good for non local development/production)|
137138
|**`base`** |`{Number}`|`true`|Set module ID base (DLLPlugin)|
138139
|**`attrs`**|`{Object}`|`{}`|Add custom attrs to `<style></style>`|
139140
|**`transform`** |`{Function}`|`false`|Transform/Conditionally load CSS by passing a transform/condition function|
@@ -142,6 +143,21 @@ Styles are not added on `import/require()`, but instead on call to `use`/`ref`.
142143
|**`sourceMap`**|`{Boolean}`|`false`|Enable/Disable Sourcemaps|
143144
|**`convertToAbsoluteUrls`**|`{Boolean}`|`false`|Converts relative URLs to absolute urls, when source maps are enabled|
144145

146+
### `hmr`
147+
148+
Enable/disable Hot Module Replacement (HMR), if disabled no HMR Code will be added.
149+
This could be used for non local development and production.
150+
151+
**webpack.config.js**
152+
```js
153+
{
154+
loader: 'style-loader'
155+
options: {
156+
hmr: false
157+
}
158+
}
159+
```
160+
145161
### `base`
146162

147163
This setting is primarily used as a workaround for [css clashes](https://github.com/webpack-contrib/style-loader/issues/163) when using one or more [DllPlugin](https://robertknight.github.io/posts/webpack-dll-plugins/)'s. `base` allows you to prevent either the *app*'s css (or *DllPlugin2*'s css) from overwriting *DllPlugin1*'s css by specifying a css module id base which is greater than the range used by *DllPlugin1* e.g.:

index.js

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,22 @@ module.exports.pitch = function (request) {
1717

1818
validateOptions(require('./options.json'), options, 'Style Loader')
1919

20+
var hmr = [
21+
"// Hot Module Replacement",
22+
"if(module.hot) {",
23+
" // When the styles change, update the <style> tags",
24+
" if(!content.locals) {",
25+
" module.hot.accept(" + loaderUtils.stringifyRequest(this, "!!" + request) + ", function() {",
26+
" var newContent = require(" + loaderUtils.stringifyRequest(this, "!!" + request) + ");",
27+
" if(typeof newContent === 'string') newContent = [[module.id, newContent, '']];",
28+
" update(newContent);",
29+
" });",
30+
" }",
31+
" // When the module is disposed, remove the <style> tags",
32+
" module.hot.dispose(function() { update(); });",
33+
"}"
34+
].join("\n");
35+
2036
return [
2137
"// style-loader: Adds some css to the DOM by adding a <style> tag",
2238
"",
@@ -31,18 +47,6 @@ module.exports.pitch = function (request) {
3147
"// add the styles to the DOM",
3248
"var update = require(" + loaderUtils.stringifyRequest(this, "!" + path.join(__dirname, "lib", "addStyles.js")) + ")(content, options);",
3349
"if(content.locals) module.exports = content.locals;",
34-
"// Hot Module Replacement",
35-
"if(module.hot) {",
36-
" // When the styles change, update the <style> tags",
37-
" if(!content.locals) {",
38-
" module.hot.accept(" + loaderUtils.stringifyRequest(this, "!!" + request) + ", function() {",
39-
" var newContent = require(" + loaderUtils.stringifyRequest(this, "!!" + request) + ");",
40-
" if(typeof newContent === 'string') newContent = [[module.id, newContent, '']];",
41-
" update(newContent);",
42-
" });",
43-
" }",
44-
" // When the module is disposed, remove the <style> tags",
45-
" module.hot.dispose(function() { update(); });",
46-
"}"
50+
options.hmr ? hmr : ""
4751
].join("\n");
4852
};

options.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22
{
33
"type": "object",
44
"properties": {
5+
"hmr": {
6+
"type": "boolean",
7+
"default": true
8+
},
59
"base": {
610
"type": "number"
711
},

test/basicTest.js

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ describe("basic tests", function() {
55
var path = require("path");
66

77
var utils = require("./utils"),
8-
runCompilerTest = utils.runCompilerTest;
8+
runCompilerTest = utils.runCompilerTest,
9+
runSourceTest = utils.runSourceTest;
910

1011
var fs;
1112

@@ -60,6 +61,18 @@ describe("basic tests", function() {
6061
}
6162
};
6263

64+
var setupWebpackConfig = function() {
65+
fs = utils.setup(webpackConfig, jsdomHtml);
66+
67+
// Create a tiny file system. rootDir is used because loaders are referring to absolute paths.
68+
fs.mkdirpSync(rootDir);
69+
fs.writeFileSync(rootDir + "main.js", "var css = require('./style.css');");
70+
fs.writeFileSync(rootDir + "style.css", requiredCss);
71+
fs.writeFileSync(rootDir + "styleTwo.css", requiredCssTwo);
72+
fs.writeFileSync(rootDir + "localScoped.css", localScopedCss);
73+
fs.writeFileSync(rootDir + "localComposing.css", localComposingCss);
74+
};
75+
6376
beforeEach(function() {
6477
// Reset all style-loader options
6578
for (var member in styleLoaderOptions) {
@@ -70,15 +83,7 @@ describe("basic tests", function() {
7083
cssRule[member] = defaultCssRule[member];
7184
}
7285

73-
fs = utils.setup(webpackConfig, jsdomHtml);
74-
75-
// Create a tiny file system. rootDir is used because loaders are refering to absolute paths.
76-
fs.mkdirpSync(rootDir);
77-
fs.writeFileSync(rootDir + "main.js", "var css = require('./style.css');");
78-
fs.writeFileSync(rootDir + "style.css", requiredCss);
79-
fs.writeFileSync(rootDir + "styleTwo.css", requiredCssTwo);
80-
fs.writeFileSync(rootDir + "localScoped.css", localScopedCss);
81-
fs.writeFileSync(rootDir + "localComposing.css", localComposingCss);
86+
setupWebpackConfig();
8287
}); // before each
8388

8489
it("insert at bottom", function(done) {
@@ -385,6 +390,25 @@ describe("basic tests", function() {
385390

386391
runCompilerTest(expected, done);
387392
});
393+
});
394+
395+
describe("hmr option", function() {
396+
397+
it("should output HMR code block by default", function(done) {
398+
runSourceTest(/Hot Module Replacement/g, null, done);
399+
});
400+
401+
it("should output HMR code block when options.hmr is true", function(done) {
402+
styleLoaderOptions.hmr = true;
403+
setupWebpackConfig();
404+
runSourceTest(/Hot Module Replacement/g, null, done);
405+
});
406+
407+
it("should not output HMR code block when options.hmr is false", function(done) {
408+
styleLoaderOptions.hmr = false;
409+
setupWebpackConfig();
410+
runSourceTest(null, /Hot Module Replacement/g, done);
411+
});
388412

389413
});
390414

test/utils.js

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ module.exports = {
7272
virtualConsole: jsdom.createVirtualConsole().sendTo(console),
7373
done: function(err, window) {
7474
if (typeof actual === 'function') {
75-
assert.equal(actual.apply(window), expected);
75+
assert.equal(actual.apply(window), expected);
7676
} else {
7777
assert.equal(window.document.querySelector(selector).innerHTML.trim(), expected);
7878
}
@@ -83,5 +83,30 @@ module.exports = {
8383
}
8484
});
8585
});
86+
},
87+
88+
/*
89+
* Runs the test against Webpack compiled source code.
90+
* @param {regex} regexToMatch - regex to match the source code
91+
* @param {regex} regexToNotMatch - regex to NOT match the source code
92+
* @param {function} done - Async callback from Mocha.
93+
*/
94+
runSourceTest: function(regexToMatch, regexToNotMatch, done) {
95+
compiler.run(function(err, stats) {
96+
if (stats.compilation.errors.length) {
97+
throw new Error(stats.compilation.errors);
98+
}
99+
100+
const bundleJs = stats.compilation.assets["bundle.js"].source();
101+
if (regexToMatch) {
102+
assert.equal(regexToMatch.test(bundleJs), true);
103+
}
104+
105+
if (regexToNotMatch) {
106+
assert.equal(regexToNotMatch.test(bundleJs), false);
107+
}
108+
109+
done();
110+
});
86111
}
87112
};

0 commit comments

Comments
 (0)