systemjs-hot-reloader-ex
Advanced tools
Comparing version
@@ -39,2 +39,6 @@ 'use strict'; | ||
this.logger = this.createLogger('HMR'); | ||
if (!this.loader.trace) { | ||
this.logger.info('Set "SystemJS.trace = true" to be able to auto unload not used modules'); | ||
} | ||
} | ||
@@ -118,2 +122,3 @@ | ||
this.logger.info('Nothing to update'); | ||
return Promise.resolve(); | ||
@@ -241,2 +246,4 @@ } | ||
var oldDeps = []; | ||
if (reload) { | ||
@@ -258,5 +265,10 @@ return Promise.resolve().then(function () { | ||
}).then(function () { | ||
oldDeps = _this3.getModuleDepNames(name); | ||
}).then(function () { | ||
return backup ? _this3.restoreModuleBackup(backup) : _this3.deleteModule(name); | ||
}).then(function () { | ||
return _this3.importModule(name); | ||
}).then(function () { | ||
var newDeps = _this3.getModuleDepNames(name); | ||
_this3.deleteOldDeps(oldDeps, newDeps); | ||
}); | ||
@@ -266,2 +278,48 @@ } | ||
/** | ||
* Delete modules from oldDeps if they do not exist in newDeps. | ||
*/ | ||
}, { | ||
key: 'deleteOldDeps', | ||
value: function deleteOldDeps(oldDeps, newDeps) { | ||
var _this4 = this; | ||
var depDiff = oldDeps.filter(function (depName) { | ||
return newDeps.indexOf(depName) === -1; | ||
}); | ||
depDiff.forEach(function (depName) { | ||
return _this4.deleteModule(depName); | ||
}); | ||
} | ||
/** | ||
* Get normalized list of module dependency names based on trace information | ||
* or based on module records. | ||
*/ | ||
}, { | ||
key: 'getModuleDepNames', | ||
value: function getModuleDepNames(name) { | ||
var load = this.loader.loads[name]; | ||
if (load) { | ||
return load.deps.map(function (address) { | ||
return load.depMap[address]; | ||
}); | ||
} | ||
var moduleRecord = this.loader._loader.moduleRecords[name]; | ||
if (moduleRecord) { | ||
return moduleRecord.dependencies.map(function (record) { | ||
return record ? record.name : false; | ||
}).filter(function (depName) { | ||
return !!depName; | ||
}); | ||
} | ||
return []; | ||
} | ||
/** | ||
* Fix module dependencies before hooked reload. | ||
@@ -273,3 +331,3 @@ */ | ||
value: function fixModuleDeps(name) { | ||
var _this4 = this; | ||
var _this5 = this; | ||
@@ -292,3 +350,3 @@ var moduleRecords = this.loader._loader.moduleRecords; | ||
if (newDepModuleRecord !== depModuleRecord) { | ||
_this4.logger.debug('Fixing dependency ' + _this4.cleanName(depModuleRecord.name) + ' for module ' + _this4.cleanName(moduleRecord.name)); | ||
_this5.logger.debug('Fixing dependency ' + _this5.cleanName(depModuleRecord.name) + ' for module ' + _this5.cleanName(moduleRecord.name)); | ||
@@ -329,3 +387,3 @@ moduleRecord.setters[index](newDepModuleRecord.exports); | ||
value: function deleteModule(name) { | ||
var _this5 = this; | ||
var _this6 = this; | ||
@@ -341,3 +399,3 @@ var moduleRecord = this.loader._loader.moduleRecords[name]; | ||
if (impModuleRecord && moduleRecord.name === impModuleRecord.name) { | ||
_this5.logger.debug('Removing importer ' + _this5.cleanName(impModuleRecord.name) + ' from module ' + _this5.cleanName(depModuleRecord.name)); | ||
_this6.logger.debug('Removing importer ' + _this6.cleanName(impModuleRecord.name) + ' from module ' + _this6.cleanName(depModuleRecord.name)); | ||
depModuleRecord.importers.splice(index, 1); | ||
@@ -351,5 +409,45 @@ } | ||
this.loader.delete(name); | ||
this.clearModuleResources(name); | ||
} | ||
/** | ||
* Clear module resources located in DOM. | ||
* | ||
* Usefull for CSS/LESS/SASS/SCSS/Stylus plugins who keep CSS as style or link tags. | ||
*/ | ||
}, { | ||
key: 'clearModuleResources', | ||
value: function clearModuleResources(name) { | ||
var address = this.getModuleAddress(name); | ||
// for example, plugin-sass | ||
Array.from(document.querySelectorAll('[data-url="' + address + '"]')).forEach(function (node) { | ||
return node.remove(); | ||
}); | ||
// for example, plugin-css | ||
Array.from(document.querySelectorAll('[data-systemjs-css]')).filter(function (node) { | ||
return node.href === address; | ||
}).forEach(function (node) { | ||
return node.remove(); | ||
}); | ||
} | ||
/** | ||
* Get module address by name. | ||
* | ||
* Try to use trace information if availabe, if not then try to guess it. | ||
* Address guessing should work well for plugins without custom translation hook. | ||
*/ | ||
}, { | ||
key: 'getModuleAddress', | ||
value: function getModuleAddress(name) { | ||
var load = this.loader.loads[name]; | ||
return load ? load.address : name.replace(/!.*$/, ''); | ||
} | ||
/** | ||
* Get module backup which could be used to restore module state. | ||
@@ -384,3 +482,3 @@ */ | ||
value: function getModuleDistanceToRoot(name, record, cache) { | ||
var _this6 = this; | ||
var _this7 = this; | ||
@@ -395,3 +493,3 @@ var distance = void 0; | ||
distance = record.importers.reduce(function (result, impRecord) { | ||
var impDistance = 1 + _this6.getModuleDistanceToRoot(impRecord.name, impRecord, cache); | ||
var impDistance = 1 + _this7.getModuleDistanceToRoot(impRecord.name, impRecord, cache); | ||
return result === null ? impDistance : Math.min(result, impDistance); | ||
@@ -411,3 +509,3 @@ }, null); | ||
value: function getReloadChain(modules, cache) { | ||
var _this7 = this; | ||
var _this8 = this; | ||
@@ -426,3 +524,3 @@ if (modules.length === 0) { | ||
var record = records[name] ? records[name] : undefined; | ||
var distance = _this7.getModuleDistanceToRoot(name, record, cache); | ||
var distance = _this8.getModuleDistanceToRoot(name, record, cache); | ||
var importers = !record ? [] : record.importers.map(function (item) { | ||
@@ -429,0 +527,0 @@ return item.name; |
{ | ||
"name": "systemjs-hot-reloader-ex", | ||
"version": "2.0.5", | ||
"version": "2.0.6", | ||
"description": "SystemJS / JSPM hot reloader with support of CSS, SCSS, SASS, LESS, Stylus, React and JavaScript", | ||
@@ -46,2 +46,3 @@ "main": "dist/index.js", | ||
"lint": "eslint .", | ||
"prepublish": "npm run start", | ||
"start": "npm run lint && npm run clean && npm run build" | ||
@@ -48,0 +49,0 @@ }, |
@@ -21,2 +21,4 @@ # SystemJS Hot Reloader # | ||
* Custom __reload() / __unload() hooks | ||
* Unload unused modules (mostly usefull for css modules). | ||
`SystemJS.trace = true` is required to track modules without exports. | ||
* Optimize reload strategy based on full dependency graph | ||
@@ -36,3 +38,3 @@ * Works with/without enabled `SystemJS.trace` | ||
* Babel plugin to strip __unload() / __reload() for production builds | ||
* Module unload if it was removed (for example, removed css module) | ||
* Show list of unloaded modules | ||
* Get rid of react hot loader babel plugin | ||
@@ -90,2 +92,5 @@ * Reload assets (fonts, images, cursors etc) | ||
Please note that unused modules without exports can't be unloaded without extra | ||
debug information which could be enable with `SystemJS.trace = true`. | ||
### CSS Hot Reloader ### | ||
@@ -99,2 +104,7 @@ | ||
If you would like to be able to remove CSS modules on the fly after they were | ||
initially loaded then you need to enable `SystemJS.trace = true`. Module to DOM | ||
relations are tracked with selectors: `[data-url={address}]` and | ||
`[data-systemjs-css, href={address}]`. | ||
Avoid using of loaders via `!` because in that case there is no 100% way to | ||
@@ -101,0 +111,0 @@ convert file name into module name so reloader will have to iterate over all |
@@ -27,2 +27,6 @@ import 'core-js/shim'; | ||
this.logger = this.createLogger('HMR'); | ||
if (!this.loader.trace) { | ||
this.logger.info('Set "SystemJS.trace = true" to be able to auto unload not used modules'); | ||
} | ||
} | ||
@@ -94,2 +98,3 @@ | ||
this.logger.info('Nothing to update'); | ||
return Promise.resolve(); | ||
@@ -208,2 +213,4 @@ } | ||
let oldDeps = []; | ||
if (reload) { | ||
@@ -226,7 +233,46 @@ return Promise.resolve() | ||
}) | ||
.then(() => { | ||
oldDeps = this.getModuleDepNames(name); | ||
}) | ||
.then(() => (backup ? this.restoreModuleBackup(backup) : this.deleteModule(name))) | ||
.then(() => this.importModule(name)); | ||
.then(() => this.importModule(name)) | ||
.then(() => { | ||
const newDeps = this.getModuleDepNames(name); | ||
this.deleteOldDeps(oldDeps, newDeps); | ||
}); | ||
} | ||
/** | ||
* Delete modules from oldDeps if they do not exist in newDeps. | ||
*/ | ||
deleteOldDeps(oldDeps, newDeps) { | ||
const depDiff = oldDeps.filter(depName => newDeps.indexOf(depName) === -1); | ||
depDiff.forEach(depName => this.deleteModule(depName)); | ||
} | ||
/** | ||
* Get normalized list of module dependency names based on trace information | ||
* or based on module records. | ||
*/ | ||
getModuleDepNames(name) { | ||
const load = this.loader.loads[name]; | ||
if (load) { | ||
return load.deps.map((address) => { | ||
return load.depMap[address]; | ||
}); | ||
} | ||
const moduleRecord = this.loader._loader.moduleRecords[name]; | ||
if (moduleRecord) { | ||
return moduleRecord.dependencies | ||
.map(record => (record ? record.name : false)) | ||
.filter(depName => !!depName); | ||
} | ||
return []; | ||
} | ||
/** | ||
* Fix module dependencies before hooked reload. | ||
@@ -301,5 +347,36 @@ */ | ||
this.loader.delete(name); | ||
this.clearModuleResources(name); | ||
} | ||
/** | ||
* Clear module resources located in DOM. | ||
* | ||
* Usefull for CSS/LESS/SASS/SCSS/Stylus plugins who keep CSS as style or link tags. | ||
*/ | ||
clearModuleResources(name) { | ||
const address = this.getModuleAddress(name); | ||
// for example, plugin-sass | ||
Array.from(document.querySelectorAll(`[data-url="${address}"]`)) | ||
.forEach(node => node.remove()); | ||
// for example, plugin-css | ||
Array.from(document.querySelectorAll('[data-systemjs-css]')) | ||
.filter(node => node.href === address) | ||
.forEach(node => node.remove()); | ||
} | ||
/** | ||
* Get module address by name. | ||
* | ||
* Try to use trace information if availabe, if not then try to guess it. | ||
* Address guessing should work well for plugins without custom translation hook. | ||
*/ | ||
getModuleAddress(name) { | ||
const load = this.loader.loads[name]; | ||
return load ? load.address : name.replace(/!.*$/, ''); | ||
} | ||
/** | ||
* Get module backup which could be used to restore module state. | ||
@@ -306,0 +383,0 @@ */ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
66294
16.57%837
20.43%278
3.73%