mirror of https://github.com/webpack/webpack.git
hot module replacement with code splitting #26
This commit is contained in:
parent
8b2301056d
commit
d8fc8472f6
|
@ -1,22 +1,31 @@
|
||||||
if(module.hot) {
|
if(module.hot) {
|
||||||
|
function check() {
|
||||||
|
module.hot.check(function(err, updatedModules) {
|
||||||
|
if(err) {
|
||||||
|
if(module.hot.status() in {abort:1,fail:1})
|
||||||
|
window.location.reload();
|
||||||
|
else
|
||||||
|
console.warn("Update failed: " + err);
|
||||||
|
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) {
|
window.onmessage = function(event) {
|
||||||
if(event.data === "webpackHotUpdate" && module.hot.status() === "idle") {
|
if(event.data === "webpackHotUpdate" && module.hot.status() === "idle") {
|
||||||
module.hot.check(function(err, updatedModules) {
|
check();
|
||||||
if(err) {
|
|
||||||
if(module.hot.status() in {abort:1,fail:1})
|
|
||||||
window.location.reload();
|
|
||||||
else
|
|
||||||
console.warn("Update failed: " + err);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!updatedModules || updatedModules.length === 0)
|
|
||||||
return console.log("Update is empty.");
|
|
||||||
console.log("Updated modules:");
|
|
||||||
updatedModules.forEach(function(moduleId) {
|
|
||||||
console.log(" - " + moduleId);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
|
@ -93,6 +93,12 @@ HotModuleReplacementPlugin.prototype.apply = function(compiler) {
|
||||||
|
|
||||||
var mainTemplate = compilation.mainTemplate;
|
var mainTemplate = compilation.mainTemplate;
|
||||||
compilation.mainTemplate = Object.create(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) {
|
compilation.mainTemplate.renderRequireFunctionForModule = function(hash, chunk, varModuleId) {
|
||||||
return "hotCreateRequire(" + varModuleId + ")";
|
return "hotCreateRequire(" + varModuleId + ")";
|
||||||
};
|
};
|
||||||
|
@ -164,49 +170,53 @@ var hotInitCode = function() {
|
||||||
hotUpdate[moduleId] = false;
|
hotUpdate[moduleId] = false;
|
||||||
}
|
}
|
||||||
hotUpdateNewHash = newHash;
|
hotUpdateNewHash = newHash;
|
||||||
if(--hotWaitingFiles === 0) {
|
if(--hotWaitingFiles === 0 && hotChunksLoading === 0) {
|
||||||
var outdatedDependencies = hotUpdateOutdatedDependencies = {};
|
hotUpdateDownloaded();
|
||||||
var outdatedModules = hotUpdateOutdatedModules = Object.keys(hotUpdate).slice();
|
}
|
||||||
var queue = outdatedModules.slice();
|
}
|
||||||
while(queue.length > 0) {
|
|
||||||
var moduleId = queue.pop();
|
|
||||||
var module = installedModules[moduleId];
|
|
||||||
if(module.hot._selfAccepted)
|
|
||||||
continue;
|
|
||||||
if(module.hot._selfDeclined) {
|
|
||||||
hotSetStatus("abort");
|
|
||||||
return hotCallback(new Error("Aborted because of self decline: " + moduleId));
|
|
||||||
}
|
|
||||||
if(moduleId === 0) {
|
|
||||||
hotSetStatus("abort");
|
|
||||||
return hotCallback(new Error("Aborted because of bubbling"));
|
|
||||||
}
|
|
||||||
for(var i = 0; i < module.parents.length; i++) {
|
|
||||||
var parentId = module.parents[i];
|
|
||||||
var parent = installedModules[parentId];
|
|
||||||
if(parent.hot._declinedDependencies[moduleId]) {
|
|
||||||
hotSetStatus("abort");
|
|
||||||
return hotCallback(new Error("Aborted because of declined dependency: " + moduleId + " in " + parentId));
|
|
||||||
}
|
|
||||||
if(outdatedModules.indexOf(parentId) >= 0) continue;
|
|
||||||
if(parent.hot._acceptedDependencies[moduleId]) {
|
|
||||||
if(!outdatedDependencies[parentId]) outdatedDependencies[parentId] = [];
|
|
||||||
if(outdatedDependencies[parentId].indexOf(moduleId) >= 0) continue;
|
|
||||||
outdatedDependencies[parentId].push(moduleId);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
delete outdatedDependencies[parentId];
|
|
||||||
outdatedModules.push(parentId);
|
|
||||||
queue.push(parentId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
hotSetStatus("ready");
|
function hotUpdateDownloaded() {
|
||||||
if(hotApplyOnUpdate) {
|
var outdatedDependencies = hotUpdateOutdatedDependencies = {};
|
||||||
hotApply(hotCallback);
|
var outdatedModules = hotUpdateOutdatedModules = Object.keys(hotUpdate).slice();
|
||||||
} else {
|
var queue = outdatedModules.slice();
|
||||||
hotCallback(null, outdatedModules);
|
while(queue.length > 0) {
|
||||||
|
var moduleId = queue.pop();
|
||||||
|
var module = installedModules[moduleId];
|
||||||
|
if(module.hot._selfAccepted)
|
||||||
|
continue;
|
||||||
|
if(module.hot._selfDeclined) {
|
||||||
|
hotSetStatus("abort");
|
||||||
|
return hotCallback(new Error("Aborted because of self decline: " + moduleId));
|
||||||
}
|
}
|
||||||
|
if(moduleId === 0) {
|
||||||
|
hotSetStatus("abort");
|
||||||
|
return hotCallback(new Error("Aborted because of bubbling"));
|
||||||
|
}
|
||||||
|
for(var i = 0; i < module.parents.length; i++) {
|
||||||
|
var parentId = module.parents[i];
|
||||||
|
var parent = installedModules[parentId];
|
||||||
|
if(parent.hot._declinedDependencies[moduleId]) {
|
||||||
|
hotSetStatus("abort");
|
||||||
|
return hotCallback(new Error("Aborted because of declined dependency: " + moduleId + " in " + parentId));
|
||||||
|
}
|
||||||
|
if(outdatedModules.indexOf(parentId) >= 0) continue;
|
||||||
|
if(parent.hot._acceptedDependencies[moduleId]) {
|
||||||
|
if(!outdatedDependencies[parentId]) outdatedDependencies[parentId] = [];
|
||||||
|
if(outdatedDependencies[parentId].indexOf(moduleId) >= 0) continue;
|
||||||
|
outdatedDependencies[parentId].push(moduleId);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
delete outdatedDependencies[parentId];
|
||||||
|
outdatedModules.push(parentId);
|
||||||
|
queue.push(parentId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
hotSetStatus("ready");
|
||||||
|
if(hotApplyOnUpdate) {
|
||||||
|
hotApply(hotCallback);
|
||||||
|
} else {
|
||||||
|
hotCallback(null, outdatedModules);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -225,9 +235,19 @@ var hotInitCode = function() {
|
||||||
return $require$(request);
|
return $require$(request);
|
||||||
};
|
};
|
||||||
fn.e = function(chunkId, callback) {
|
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() {
|
$require$.e(chunkId, function() {
|
||||||
callback(fn);
|
callback(fn);
|
||||||
|
hotChunksLoading--;
|
||||||
|
if(hotStatus === "prepare") {
|
||||||
|
if(!hotWaitingFilesMap[chunkId]) {
|
||||||
|
hotDownloadUpdateChunk(chunkId);
|
||||||
|
}
|
||||||
|
if(hotChunksLoading === 0 && hotWaitingFiles === 0) {
|
||||||
|
hotUpdateDownloaded();
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
fn.cache = $require$.cache;
|
fn.cache = $require$.cache;
|
||||||
|
@ -298,6 +318,8 @@ var hotInitCode = function() {
|
||||||
}
|
}
|
||||||
|
|
||||||
var hotWaitingFiles = 0;
|
var hotWaitingFiles = 0;
|
||||||
|
var hotChunksLoading = 0;
|
||||||
|
var hotWaitingFilesMap = {};
|
||||||
var hotCallback;
|
var hotCallback;
|
||||||
function hotCheck(callback) {
|
function hotCheck(callback) {
|
||||||
if(hotStatus !== "idle") throw new Error("check() is only allowed in idle status");
|
if(hotStatus !== "idle") throw new Error("check() is only allowed in idle status");
|
||||||
|
@ -318,27 +340,32 @@ var hotInitCode = function() {
|
||||||
if(request.status !== 200 && request.status !== 304) {
|
if(request.status !== 200 && request.status !== 304) {
|
||||||
|
|
||||||
hotSetStatus("idle");
|
hotSetStatus("idle");
|
||||||
callback(null, []);
|
callback(null, null);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
hotWaitingFilesMap = {};
|
||||||
hotSetStatus("prepare");
|
hotSetStatus("prepare");
|
||||||
hotCallback = callback || function(err) { if(err) throw err };
|
hotCallback = callback || function(err) { if(err) throw err };
|
||||||
hotUpdate = {};
|
hotUpdate = {};
|
||||||
var hash = hotCurrentHash;
|
var hash = hotCurrentHash;
|
||||||
/*foreachInstalledChunks*/ {
|
/*foreachInstalledChunks*/ {
|
||||||
hotWaitingFiles++;
|
hotDownloadUpdateChunk(chunkId);
|
||||||
var head = document.getElementsByTagName('head')[0];
|
|
||||||
var script = document.createElement('script');
|
|
||||||
script.type = 'text/javascript';
|
|
||||||
script.charset = 'utf-8';
|
|
||||||
script.src = modules.c + $hotChunkFilename$;
|
|
||||||
head.appendChild(script);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
function hotDownloadUpdateChunk(chunkId) {
|
||||||
|
hotWaitingFiles++;
|
||||||
|
var head = document.getElementsByTagName('head')[0];
|
||||||
|
var script = document.createElement('script');
|
||||||
|
script.type = 'text/javascript';
|
||||||
|
script.charset = 'utf-8';
|
||||||
|
script.src = modules.c + $hotChunkFilename$;
|
||||||
|
head.appendChild(script);
|
||||||
|
hotWaitingFilesMap[chunkId] = true;
|
||||||
|
}
|
||||||
|
|
||||||
var hotUpdate, hotUpdateOutdatedDependencies, hotUpdateOutdatedModules, hotUpdateNewHash;
|
var hotUpdate, hotUpdateOutdatedDependencies, hotUpdateOutdatedModules, hotUpdateNewHash;
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
};
|
||||||
|
}
|
|
@ -38,6 +38,8 @@ window.onload = function() {
|
||||||
|
|
||||||
require("./style.js");
|
require("./style.js");
|
||||||
|
|
||||||
|
require("bundle!./style2.js");
|
||||||
|
|
||||||
if(module.hot) {
|
if(module.hot) {
|
||||||
|
|
||||||
module.hot.accept("./html.js", function() {
|
module.hot.accept("./html.js", function() {
|
||||||
|
|
|
@ -1,22 +1,11 @@
|
||||||
// This file can update, because it accept itself.
|
// This file can update, because it accept itself.
|
||||||
// A dispose handler removes the old <style> element.
|
// A dispose handler removes the old <style> element.
|
||||||
|
|
||||||
var cssCode = "body { background: green; }";
|
var addStyle = require("./addStyle");
|
||||||
|
|
||||||
var head = document.getElementsByTagName("head")[0];
|
var dispose = addStyle("body { background: green; }");
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
if(module.hot) {
|
if(module.hot) {
|
||||||
module.hot.accept();
|
module.hot.accept();
|
||||||
module.hot.dispose(function() {
|
module.hot.dispose(dispose);
|
||||||
head.removeChild(styleElement);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
Loading…
Reference in New Issue