hot module replacement with code splitting #26

This commit is contained in:
Tobias Koppers 2013-06-19 16:09:46 +02:00
parent 8b2301056d
commit d8fc8472f6
6 changed files with 136 additions and 80 deletions

View File

@ -1,6 +1,5 @@
if(module.hot) {
window.onmessage = function(event) {
if(event.data === "webpackHotUpdate" && module.hot.status() === "idle") {
function check() {
module.hot.check(function(err, updatedModules) {
if(err) {
if(module.hot.status() in {abort:1,fail:1})
@ -10,13 +9,23 @@ if(module.hot) {
return;
}
if(!updatedModules)
return console.log("No Update found.");
check();
if(!updatedModules || updatedModules.length === 0)
return console.log("Update is empty.");
console.log("Updated modules:");
updatedModules.forEach(function(moduleId) {
console.log(" - " + moduleId);
});
});
}
window.onmessage = function(event) {
if(event.data === "webpackHotUpdate" && module.hot.status() === "idle") {
check();
}
};
}

View File

@ -93,6 +93,12 @@ HotModuleReplacementPlugin.prototype.apply = function(compiler) {
var mainTemplate = compilation.mainTemplate;
compilation.mainTemplate = Object.create(mainTemplate);
compilation.mainTemplate.updateHash = function(hash) {
hash.update(compilation.records.hash + "");
mainTemplate.updateHash(hash);
};
compilation.mainTemplate.renderRequireFunctionForModule = function(hash, chunk, varModuleId) {
return "hotCreateRequire(" + varModuleId + ")";
};
@ -164,7 +170,12 @@ var hotInitCode = function() {
hotUpdate[moduleId] = false;
}
hotUpdateNewHash = newHash;
if(--hotWaitingFiles === 0) {
if(--hotWaitingFiles === 0 && hotChunksLoading === 0) {
hotUpdateDownloaded();
}
}
function hotUpdateDownloaded() {
var outdatedDependencies = hotUpdateOutdatedDependencies = {};
var outdatedModules = hotUpdateOutdatedModules = Object.keys(hotUpdate).slice();
var queue = outdatedModules.slice();
@ -208,7 +219,6 @@ var hotInitCode = function() {
hotCallback(null, outdatedModules);
}
}
}
var hotApplyOnUpdate = true;
var hotCurrentHash = $hash$;
@ -225,9 +235,19 @@ var hotInitCode = function() {
return $require$(request);
};
fn.e = function(chunkId, callback) {
if(hotStatus !== "idle") throw new Error("TODO: chunk loading while updating");
if(hotStatus === "ready") throw new Error("Cannot load chunks when update is ready");
hotChunksLoading++;
$require$.e(chunkId, function() {
callback(fn);
hotChunksLoading--;
if(hotStatus === "prepare") {
if(!hotWaitingFilesMap[chunkId]) {
hotDownloadUpdateChunk(chunkId);
}
if(hotChunksLoading === 0 && hotWaitingFiles === 0) {
hotUpdateDownloaded();
}
}
});
}
fn.cache = $require$.cache;
@ -298,6 +318,8 @@ var hotInitCode = function() {
}
var hotWaitingFiles = 0;
var hotChunksLoading = 0;
var hotWaitingFilesMap = {};
var hotCallback;
function hotCheck(callback) {
if(hotStatus !== "idle") throw new Error("check() is only allowed in idle status");
@ -318,15 +340,23 @@ var hotInitCode = function() {
if(request.status !== 200 && request.status !== 304) {
hotSetStatus("idle");
callback(null, []);
callback(null, null);
} else {
hotWaitingFilesMap = {};
hotSetStatus("prepare");
hotCallback = callback || function(err) { if(err) throw err };
hotUpdate = {};
var hash = hotCurrentHash;
/*foreachInstalledChunks*/ {
hotDownloadUpdateChunk(chunkId);
}
}
};
}
function hotDownloadUpdateChunk(chunkId) {
hotWaitingFiles++;
var head = document.getElementsByTagName('head')[0];
var script = document.createElement('script');
@ -334,10 +364,7 @@ var hotInitCode = function() {
script.charset = 'utf-8';
script.src = modules.c + $hotChunkFilename$;
head.appendChild(script);
}
}
};
hotWaitingFilesMap[chunkId] = true;
}
var hotUpdate, hotUpdateOutdatedDependencies, hotUpdateOutdatedModules, hotUpdateNewHash;

View File

@ -0,0 +1,18 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
module.exports = function(cssCode) {
var styleElement = document.createElement("style");
styleElement.type = "text/css";
if (styleElement.styleSheet) {
styleElement.styleSheet.cssText = cssCode;
} else {
styleElement.appendChild(document.createTextNode(cssCode));
}
var head = document.getElementsByTagName("head")[0];
head.appendChild(styleElement);
return function() {
head.removeChild(styleElement);
};
}

View File

@ -38,6 +38,8 @@ window.onload = function() {
require("./style.js");
require("bundle!./style2.js");
if(module.hot) {
module.hot.accept("./html.js", function() {

View File

@ -1,22 +1,11 @@
// This file can update, because it accept itself.
// A dispose handler removes the old <style> element.
var cssCode = "body { background: green; }";
var addStyle = require("./addStyle");
var head = document.getElementsByTagName("head")[0];
var styleElement = document.createElement("style");
styleElement.type = "text/css";
if (styleElement.styleSheet) {
styleElement.styleSheet.cssText = cssCode;
} else {
styleElement.appendChild(document.createTextNode(cssCode));
}
head.appendChild(styleElement);
var dispose = addStyle("body { background: green; }");
if(module.hot) {
module.hot.accept();
module.hot.dispose(function() {
head.removeChild(styleElement);
});
module.hot.dispose(dispose);
}

View File

@ -0,0 +1,11 @@
// This file can update, because it accept itself.
// A dispose handler removes the old <style> element.
var addStyle = require("./addStyle");
var dispose = addStyle("body { color: blue; }");
if(module.hot) {
module.hot.accept();
module.hot.dispose(dispose);
}