mirror of
https://github.com/marko-js/marko.git
synced 2025-12-08 19:26:05 +00:00
Fixes #266 - Hot reloading fails if original template is deleted
This commit is contained in:
parent
3203d630ec
commit
36a3a02f9f
@ -20,7 +20,8 @@ var extend = require('raptor-util/extend');
|
||||
var compiler = require('../compiler');
|
||||
var nodePath = require('path');
|
||||
|
||||
var modifiedFlag = 1;
|
||||
var modifiedId = 1;
|
||||
var nextTemplateId = 0;
|
||||
var runtime;
|
||||
|
||||
/**
|
||||
@ -32,6 +33,14 @@ function _getMarkoRuntime() {
|
||||
return runtime || (runtime = require('../runtime'));
|
||||
}
|
||||
|
||||
function tryReload(path, runtime) {
|
||||
try {
|
||||
return runtime.load(path);
|
||||
} catch(e) {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
exports.enable = function() {
|
||||
var runtime = _getMarkoRuntime();
|
||||
|
||||
@ -60,13 +69,16 @@ exports.enable = function() {
|
||||
if (typeof v === 'function') {
|
||||
var oldMethod = v;
|
||||
Template.prototype[k] = function() {
|
||||
if (this.__hotReloadModifiedFlag !== modifiedFlag) {
|
||||
if (this.__hotReloadModifiedId !== modifiedId) {
|
||||
var path = this.__hotReloadPath;
|
||||
if (path) {
|
||||
// Reload the template
|
||||
var template = runtime.load(path);
|
||||
extend(this, template);
|
||||
var template = tryReload(path, runtime);
|
||||
if (template && template.__hotReloadTemplateId !== this.__hotReloadTemplateId) {
|
||||
extend(this, template);
|
||||
}
|
||||
}
|
||||
this.__hotReloadModifiedId = modifiedId;
|
||||
}
|
||||
|
||||
return oldMethod.apply(this, arguments);
|
||||
@ -95,9 +107,16 @@ exports.enable = function() {
|
||||
var template = oldCreateTemplate.apply(runtime, arguments);
|
||||
|
||||
// Store the current last modified with the template
|
||||
template.__hotReloadModifiedFlag = modifiedFlag;
|
||||
template.__hotReloadModifiedId = modifiedId;
|
||||
|
||||
// Store the path of the loaded template so that we can reload it if
|
||||
// necessary
|
||||
template.__hotReloadPath = templatePath;
|
||||
|
||||
// Assign a unique ID to the loaded template so that we can know if
|
||||
// a new version of the template is loaded
|
||||
template.__hotReloadTemplateId = nextTemplateId++;
|
||||
|
||||
return template;
|
||||
};
|
||||
};
|
||||
@ -110,18 +129,26 @@ exports.handleFileModified = function(path) {
|
||||
path.endsWith('.marko.html') ||
|
||||
path.endsWith('.marko.xml') ||
|
||||
basename === 'marko-tag.json' ||
|
||||
basename === 'marko-taglib.json') {
|
||||
basename === 'marko.json') {
|
||||
|
||||
console.log('[marko/hot-reload] File modified: ' + path);
|
||||
|
||||
if (path.endsWith('.marko') || path.endsWith('.marko.html')) {
|
||||
// Uncache just the modified template
|
||||
delete require.cache[path];
|
||||
delete require.cache[path + '.js'];
|
||||
} else {
|
||||
// If we taglib was modified then uncache *all* templates so that they will
|
||||
// all be reloaded
|
||||
Object.keys(require.cache).forEach((filename) => {
|
||||
if (filename.endsWith('.marko') || filename.endsWith('.marko.js')) {
|
||||
delete require.cache[filename];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
runtime.cache = {};
|
||||
compiler.clearCaches();
|
||||
modifiedFlag++;
|
||||
modifiedId++;
|
||||
}
|
||||
|
||||
};
|
||||
@ -68,6 +68,11 @@ function compile(templatePath, markoCompiler, compilerOptions) {
|
||||
return compiledSrc;
|
||||
}
|
||||
|
||||
function getLoadedTemplate(path) {
|
||||
var cached = require.cache[path];
|
||||
return cached && cached.exports.render ? cached.exports : undefined;
|
||||
}
|
||||
|
||||
exports.install = function(options) {
|
||||
options = options || {};
|
||||
|
||||
@ -85,10 +90,10 @@ exports.install = function(options) {
|
||||
|
||||
require.extensions[extension] = function markoExtension(module, filename) {
|
||||
var targetFile = filename + '.js';
|
||||
var loaded = require.cache[targetFile];
|
||||
if (loaded) {
|
||||
var cachedTemplate = getLoadedTemplate(targetFile) || getLoadedTemplate(filename);
|
||||
if (cachedTemplate) {
|
||||
// The template has already been loaded so use the exports of the already loaded template
|
||||
module.exports = loaded.exports;
|
||||
module.exports = cachedTemplate;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@ -73,24 +73,28 @@ function loadSource(templatePath, compiledSrc) {
|
||||
return templateModule.exports;
|
||||
}
|
||||
|
||||
function getLoadedTemplate(path) {
|
||||
var cached = require.cache[path];
|
||||
return cached && cached.exports.render ? cached.exports : undefined;
|
||||
}
|
||||
|
||||
function loadFile(templatePath, options) {
|
||||
var targetFile = templatePath + '.js';
|
||||
|
||||
// Short-circuit loading if the template has already been cached in the Node.js require cache
|
||||
var cached = require.cache[targetFile];
|
||||
if (cached) {
|
||||
return cached.exports;
|
||||
var cachedTemplate = getLoadedTemplate(targetFile) || getLoadedTemplate(templatePath);
|
||||
if (cachedTemplate) {
|
||||
return cachedTemplate;
|
||||
}
|
||||
|
||||
// Just in case the the path wasn't a fully resolved file system path...
|
||||
templatePath = nodePath.resolve(cwd, templatePath);
|
||||
var targetDir = nodePath.dirname(templatePath);
|
||||
|
||||
targetFile = templatePath + '.js';
|
||||
|
||||
// Check the require cache again after fully resolving the path
|
||||
cached = require.cache[targetFile];
|
||||
if (cached) {
|
||||
return cached.exports;
|
||||
cachedTemplate = getLoadedTemplate(targetFile) || getLoadedTemplate(templatePath);
|
||||
if (cachedTemplate) {
|
||||
return cachedTemplate;
|
||||
}
|
||||
|
||||
options = extend(extend({}, markoCompiler.defaultOptions), options);
|
||||
@ -114,6 +118,7 @@ function loadFile(templatePath, options) {
|
||||
// console.log('Compiled code for "' + templatePath + '":\n' + compiledSrc);
|
||||
|
||||
var filename = nodePath.basename(targetFile);
|
||||
var targetDir = nodePath.dirname(targetFile);
|
||||
var tempFile = nodePath.join(targetDir, '.' + process.pid + '.' + Date.now() + '.' + filename);
|
||||
fs.writeFileSync(tempFile, compiledSrc, fsReadOptions);
|
||||
fs.renameSync(tempFile, targetFile);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user