Files

173 lines
5.4 KiB
JavaScript

const hmrPrefix = 'HMR:';
const log = {
info: (message) => console.info(`${hmrPrefix} ${message}`),
warn: (message) => console.warn(`${hmrPrefix} ${message}`),
error: (message) => console.error(`${hmrPrefix} ${message}`),
};
const refresh = 'Application needs to be restarted in order to apply the changes.';
const hotOptions = {
ignoreUnaccepted: false,
ignoreDeclined: false,
ignoreErrored: false,
onUnaccepted(data) {
const chain = [].concat(data.chain);
const last = chain[chain.length - 1];
if (last === 0) {
chain.pop();
}
log.warn(`Ignored an update to unaccepted module: `);
chain.forEach(mod => log.warn(`${mod}`));
},
onDeclined(data) {
log.warn(`Ignored an update to declined module:`);
data.chain.forEach(mod => log.warn(`${mod}`));
},
onErrored(data) {
log.warn(
`Ignored an error while updating module ${data.moduleId} <${data.type}>`
);
log.warn(data.error);
},
};
let nextHash;
let currentHash;
function upToDate() {
return nextHash.indexOf(__webpack_hash__) >= 0;
}
function result(modules, appliedModules) {
const unaccepted = modules.filter(
(moduleId) => appliedModules && appliedModules.indexOf(moduleId) < 0
);
if (unaccepted.length > 0) {
log.warn('The following modules could not be updated:');
for (const moduleId of unaccepted) {
log.warn(`${moduleId}`);
}
}
if (!(appliedModules || []).length) {
log.info('No Modules Updated.');
} else {
log.info('The following modules were updated:');
for (const moduleId of appliedModules) {
log.info(`${moduleId}`);
}
const numberIds = appliedModules.every(
(moduleId) => typeof moduleId === 'number'
);
if (numberIds) {
log.info(
'Please consider using the NamedModulesPlugin for module names.'
);
}
}
}
function check(options) {
return module.hot
.check()
.then((modules) => {
if (!modules) {
log.warn(
`Cannot find update. ${refresh}`
);
return null;
}
return module.hot
.apply(hotOptions)
.then((appliedModules) => {
let nextCheck;
if (!upToDate()) {
nextCheck = check(options);
}
result(modules, appliedModules);
if (upToDate()) {
// Do not modify message - CLI depends on this exact content to determine hmr operation status.
log.info(`Successfully applied update with hmr hash ${currentHash}. App is up to date.`);
}
return nextCheck || null;
})
.catch((err) => {
const status = module.hot.status();
if (['abort', 'fail'].indexOf(status) >= 0) {
// Do not modify message - CLI depends on this exact content to determine hmr operation status.
log.error(`Cannot apply update with hmr hash ${currentHash}.`);
log.error(err.message || err.stack);
} else {
log.error(`Update failed: ${err.message || err.stack}`);
}
});
})
.catch((err) => {
const status = module.hot.status();
if (['abort', 'fail'].indexOf(status) >= 0) {
log.error(`Cannot check for update. ${refresh}`);
log.error(err.message || err.stack);
} else {
log.error(`Update check failed: ${err.message || err.stack}`);
}
});
}
if (module.hot) {
log.info('Hot Module Replacement Enabled. Waiting for signal.');
} else {
log.error('Hot Module Replacement is disabled.');
}
function update(latestHash, options) {
nextHash = latestHash;
if (!upToDate()) {
const status = module.hot.status();
if (status === 'idle') {
//Do not modify message - CLI depends on this exact content to determine hmr operation status.
log.info(`Checking for updates to the bundle with hmr hash ${currentHash}.`);
return check(options);
} else if (['abort', 'fail'].indexOf(status) >= 0) {
log.warn(
`Cannot apply update. A previous update ${status}ed. ${refresh}`
);
}
}
};
function getNextHash(hash, getFileContent) {
const file = getFileContent(`${hash}.hot-update.json`);
if (!file) {
return Promise.resolve(hash);
}
return file.readText().then(hotUpdateContent => {
if (hotUpdateContent) {
const manifest = JSON.parse(hotUpdateContent);
const newHash = manifest.h;
return getNextHash(newHash, getFileContent);
} else {
return Promise.resolve(hash);
}
}).catch(error => Promise.reject(error));
}
module.exports = function checkState(initialHash, getFileContent) {
currentHash = initialHash;
return getNextHash(initialHash, getFileContent).then(nextHash => {
if (nextHash != initialHash) {
return update(nextHash, {});
}
})
}