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

Commit

Permalink
Support hot module replacement
Browse files Browse the repository at this point in the history
  • Loading branch information
cletusw committed Mar 10, 2017
1 parent 75cb09e commit 360c155
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 5 deletions.
19 changes: 19 additions & 0 deletions hotModuleReplacement.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
module.exports = function(compilationHash, publicPath, outputFilename) {
if (document) {
var origin = document.location.protocol + '//' + document.location.hostname + (document.location.port ? ':' + document.location.port: '');
var styleSheets = document.getElementsByTagName('link');
for (var i = 0; i < styleSheets.length; i++) {
if (styleSheets[i].href) {
var hrefUrl = styleSheets[i].href.split('?');
var href = hrefUrl[0];
var hash = hrefUrl[1];
if (hash !== compilationHash && href === origin + publicPath + outputFilename) {
var url = href + '?' + compilationHash;
styleSheets[i].href = url;
console.log('[HMR]', 'Reload css: ', url);
break;
}
}
}
}
}
18 changes: 16 additions & 2 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,13 @@ function ExtractTextPluginCompilation() {
}

ExtractTextPlugin.prototype.mergeNonInitialChunks = function(chunk, intoChunk, checkedChunks) {
if (chunk.chunks) {
// Fix error when hot module replacement used with CommonsChunkPlugin
chunk.chunks = chunk.chunks.filter(function(c) {
return typeof c !== 'undefined';
})
}

if(!intoChunk) {
checkedChunks = [];
chunk.chunks.forEach(function(c) {
Expand Down Expand Up @@ -313,7 +320,8 @@ ExtractTextPlugin.prototype.apply = function(compiler) {
callback();
}.bind(this));
}.bind(this));
compilation.plugin("additional-assets", function(callback) {
compilation.plugin("before-chunk-assets", function() {
// 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.
extractedChunks.forEach(function(extractedChunk) {
if(extractedChunk.modules.length) {
extractedChunk.modules.sort(function(a, b) {
Expand All @@ -336,9 +344,15 @@ ExtractTextPlugin.prototype.apply = function(compiler) {

compilation.assets[file] = source;
chunk.files.push(file);

// Hot module replacement
extractedChunk.modules.forEach(function(module){
var originalModule = module.getOriginalModule();
originalModule._source._value = originalModule._source._value.replace('%%extracted-file%%', file);
originalModule._source._value = originalModule._source._value.replace('%%extracted-hash%%', compilation.hash);
});
}
}, this);
callback();
}.bind(this));
}.bind(this));
};
18 changes: 15 additions & 3 deletions loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,13 @@ var LibraryTemplatePlugin = require("webpack/lib/LibraryTemplatePlugin");
var SingleEntryPlugin = require("webpack/lib/SingleEntryPlugin");
var LimitChunkCountPlugin = require("webpack/lib/optimize/LimitChunkCountPlugin");

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

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

module.exports.pitch = function(request) {
Expand Down Expand Up @@ -120,8 +122,18 @@ module.exports.pitch = function(request) {
});
});
this[NS](text, query);
if(text.locals && typeof resultSource !== "undefined") {
resultSource += "\nmodule.exports = " + JSON.stringify(text.locals) + ";";
if(typeof resultSource !== "undefined") {
if (text.locals) {
resultSource += "\nmodule.exports = " + JSON.stringify(text.locals) + ";";
}
// module.hot.data is undefined on initial load, and an object in hot updates
resultSource += `
if (module.hot) {
module.hot.accept();
if (module.hot.data) {
require('${extractTextPluginHmrRuntime}')('%%extracted-hash%%','${publicPath}','%%extracted-file%%');
}
}`;
}
} catch(e) {
return callback(e);
Expand Down

0 comments on commit 360c155

Please sign in to comment.