Skip to content
This repository was archived by the owner on May 29, 2019. It is now read-only.

Commit 360c155

Browse files
committed
Support hot module replacement
1 parent 75cb09e commit 360c155

File tree

3 files changed

+50
-5
lines changed

3 files changed

+50
-5
lines changed

hotModuleReplacement.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
module.exports = function(compilationHash, publicPath, outputFilename) {
2+
if (document) {
3+
var origin = document.location.protocol + '//' + document.location.hostname + (document.location.port ? ':' + document.location.port: '');
4+
var styleSheets = document.getElementsByTagName('link');
5+
for (var i = 0; i < styleSheets.length; i++) {
6+
if (styleSheets[i].href) {
7+
var hrefUrl = styleSheets[i].href.split('?');
8+
var href = hrefUrl[0];
9+
var hash = hrefUrl[1];
10+
if (hash !== compilationHash && href === origin + publicPath + outputFilename) {
11+
var url = href + '?' + compilationHash;
12+
styleSheets[i].href = url;
13+
console.log('[HMR]', 'Reload css: ', url);
14+
break;
15+
}
16+
}
17+
}
18+
}
19+
}

index.js

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,13 @@ function ExtractTextPluginCompilation() {
2222
}
2323

2424
ExtractTextPlugin.prototype.mergeNonInitialChunks = function(chunk, intoChunk, checkedChunks) {
25+
if (chunk.chunks) {
26+
// Fix error when hot module replacement used with CommonsChunkPlugin
27+
chunk.chunks = chunk.chunks.filter(function(c) {
28+
return typeof c !== 'undefined';
29+
})
30+
}
31+
2532
if(!intoChunk) {
2633
checkedChunks = [];
2734
chunk.chunks.forEach(function(c) {
@@ -313,7 +320,8 @@ ExtractTextPlugin.prototype.apply = function(compiler) {
313320
callback();
314321
}.bind(this));
315322
}.bind(this));
316-
compilation.plugin("additional-assets", function(callback) {
323+
compilation.plugin("before-chunk-assets", function() {
324+
// This appears to be the latest hook where the %%extracted-file%% and hash replacements work on initial load. Any later and the contents of modules appears to be sealed and changes don't have any effect until the next hot update.
317325
extractedChunks.forEach(function(extractedChunk) {
318326
if(extractedChunk.modules.length) {
319327
extractedChunk.modules.sort(function(a, b) {
@@ -336,9 +344,15 @@ ExtractTextPlugin.prototype.apply = function(compiler) {
336344

337345
compilation.assets[file] = source;
338346
chunk.files.push(file);
347+
348+
// Hot module replacement
349+
extractedChunk.modules.forEach(function(module){
350+
var originalModule = module.getOriginalModule();
351+
originalModule._source._value = originalModule._source._value.replace('%%extracted-file%%', file);
352+
originalModule._source._value = originalModule._source._value.replace('%%extracted-hash%%', compilation.hash);
353+
});
339354
}
340355
}, this);
341-
callback();
342356
}.bind(this));
343357
}.bind(this));
344358
};

loader.js

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,13 @@ var LibraryTemplatePlugin = require("webpack/lib/LibraryTemplatePlugin");
1010
var SingleEntryPlugin = require("webpack/lib/SingleEntryPlugin");
1111
var LimitChunkCountPlugin = require("webpack/lib/optimize/LimitChunkCountPlugin");
1212

13+
var extractTextPluginHmrRuntime = require.resolve("./hotModuleReplacement.js");
1314
var NS = fs.realpathSync(__dirname);
1415

1516
module.exports = function(source) {
1617
if(this.cacheable) this.cacheable();
17-
return source;
18+
// Even though this gets overwritten if extract+remove are true, without it, the runtime doesn't get added to the chunk
19+
return `if (module.hot) { require('${extractTextPluginHmrRuntime}'); }\n${source}`;
1820
};
1921

2022
module.exports.pitch = function(request) {
@@ -120,8 +122,18 @@ module.exports.pitch = function(request) {
120122
});
121123
});
122124
this[NS](text, query);
123-
if(text.locals && typeof resultSource !== "undefined") {
124-
resultSource += "\nmodule.exports = " + JSON.stringify(text.locals) + ";";
125+
if(typeof resultSource !== "undefined") {
126+
if (text.locals) {
127+
resultSource += "\nmodule.exports = " + JSON.stringify(text.locals) + ";";
128+
}
129+
// module.hot.data is undefined on initial load, and an object in hot updates
130+
resultSource += `
131+
if (module.hot) {
132+
module.hot.accept();
133+
if (module.hot.data) {
134+
require('${extractTextPluginHmrRuntime}')('%%extracted-hash%%','${publicPath}','%%extracted-file%%');
135+
}
136+
}`;
125137
}
126138
} catch(e) {
127139
return callback(e);

0 commit comments

Comments
 (0)