diff --git a/index.js b/index.js index b8fa563e..193fbc9a 100644 --- a/index.js +++ b/index.js @@ -97,12 +97,22 @@ class HtmlWebpackPlugin { // Clear the cache once a new HtmlWebpackPlugin is added childCompiler.clearCache(compiler); - // Clear the cache if the child compiler is outdated + // Register all HtmlWebpackPlugins instances at the child compiler compiler.hooks.thisCompilation.tap('HtmlWebpackPlugin', (compilation) => { + // Clear the cache if the child compiler is outdated if (childCompiler.hasOutDatedTemplateCache(compilation)) { childCompiler.clearCache(compiler); } + // Add this instances template to the child compiler childCompiler.addTemplateToCompiler(compiler, this.options.template); + // Add file dependencies of child compiler to parent compiler + // to keep them watched even if we get the result from the cache + compilation.hooks.additionalChunkAssets.tap('HtmlWebpackPlugin', () => { + const childCompilerDependencies = childCompiler.getFileDependencies(compiler); + childCompilerDependencies.forEach(fileDependency => { + compilation.compilationDependencies.add(fileDependency); + }); + }); }); // setup hooks for third party plugins diff --git a/lib/compiler.js b/lib/compiler.js index 7e431a73..fa099bb2 100644 --- a/lib/compiler.js +++ b/lib/compiler.js @@ -36,6 +36,10 @@ class HtmlWebpackChildCompiler { * @type {number} */ this.compilationStartedTimestamp; + /** + * @type {number} + */ + this.compilationEndedTimestamp; /** * All file dependencies of the child compiler * @type {string[]} @@ -52,23 +56,38 @@ class HtmlWebpackChildCompiler { * Add a templatePath to the child compiler * The given template will be compiled by `compileTemplates` * @param {string} template - The webpack path to the template e.g. `'!!html-loader!index.html'` + * @returns {boolean} true if the template is new */ addTemplate (template) { const templateId = this.templates.indexOf(template); // Don't add the template to the compiler if a similar template was already added if (templateId !== -1) { - return templateId; + return false; } // A child compiler can compile only once // throw an error if a new template is added after the compilation started - if (this.compilationPromise) { + if (this.isCompiling()) { throw new Error('New templates can only be added before `compileTemplates` was called.'); } // Add the template to the childCompiler - const newTemplateId = this.templates.length; this.templates.push(template); // Mark the cache invalid - return newTemplateId; + return true; + } + + /** + * Returns true if the childCompiler is currently compiling + * @retuns {boolean} + */ + isCompiling () { + return !this.didCompile() && this.compilationStartedTimestamp !== undefined; + } + + /** + * Returns true if the childCOmpiler is done compiling + */ + didCompile () { + return this.compilationEndedTimestamp !== undefined; } /** @@ -158,6 +177,7 @@ class HtmlWebpackChildCompiler { entry: entries[entryIndex] }; }); + this.compilationEndedTimestamp = new Date().getTime(); resolve(result); }); }); @@ -266,7 +286,12 @@ function getChildCompiler (mainCompiler) { * @param {WebpackCompiler} mainCompiler */ function clearCache (mainCompiler) { - childCompilerCache.delete(mainCompiler); + const childCompiler = getChildCompiler(mainCompiler); + // If this childCompiler was already used + // remove the entire childCompiler from the cache + if (childCompiler.isCompiling() || childCompiler.didCompile()) { + childCompilerCache.delete(mainCompiler); + } } /** @@ -275,7 +300,11 @@ function clearCache (mainCompiler) { * @param {string} templatePath */ function addTemplateToCompiler (mainCompiler, templatePath) { - getChildCompiler(mainCompiler).addTemplate(templatePath); + const childCompiler = getChildCompiler(mainCompiler); + const isNew = childCompiler.addTemplate(templatePath); + if (isNew) { + clearCache(mainCompiler); + } } /** @@ -321,9 +350,21 @@ function hasOutDatedTemplateCache (compilation) { return childCompiler ? childCompiler.hasOutDatedTemplateCache(compilation) : false; } +/** + * Return all file dependencies of the last child compilation + * + * @param {WebpackCompiler} compiler + * @returns {Array} + */ +function getFileDependencies (compiler) { + const childCompiler = getChildCompiler(compiler); + return childCompiler.fileDependencies; +} + module.exports = { addTemplateToCompiler, compileTemplate, hasOutDatedTemplateCache, - clearCache + clearCache, + getFileDependencies };