From beb28f72c1eebce98d555d49ec0bbfd6b1966d00 Mon Sep 17 00:00:00 2001 From: biodiscus Date: Mon, 11 Mar 2024 20:46:17 +0100 Subject: [PATCH] fix: avoid recompiling all entry templates after changes of a non-entry partial file --- CHANGELOG.md | 4 ++ package-lock.json | 4 +- package.json | 2 +- src/Loader/Dependency.js | 33 ++++++++---- .../watch-non-entry-partial-ejs/README.md | 20 ++++++++ .../watch-non-entry-partial-ejs/package.json | 10 ++++ .../src/components/slider/slider.html | 5 ++ .../pages/about-product/includes/header.html | 1 + .../src/views/pages/about-product/index.html | 11 ++++ .../views/pages/about/includes/header.html | 1 + .../src/views/pages/about/index.html | 11 ++++ .../src/views/pages/home/includes/header.html | 1 + .../src/views/pages/home/index.html | 11 ++++ .../webpack.config.js | 50 +++++++++++++++++++ .../watch-non-entry-partial-pug/README.md | 20 ++++++++ .../watch-non-entry-partial-pug/package.json | 10 ++++ .../src/components/slider/slider.pug | 4 ++ .../src/views/layouts/default.pug | 6 +++ .../pages/about-product/includes/header.pug | 1 + .../src/views/pages/about-product/index.pug | 9 ++++ .../src/views/pages/about/includes/header.pug | 1 + .../src/views/pages/about/index.pug | 9 ++++ .../src/views/pages/home/includes/header.pug | 1 + .../src/views/pages/home/index.pug | 9 ++++ .../webpack.config.js | 49 ++++++++++++++++++ 25 files changed, 269 insertions(+), 14 deletions(-) create mode 100644 test/manual/watch-non-entry-partial-ejs/README.md create mode 100644 test/manual/watch-non-entry-partial-ejs/package.json create mode 100644 test/manual/watch-non-entry-partial-ejs/src/components/slider/slider.html create mode 100644 test/manual/watch-non-entry-partial-ejs/src/views/pages/about-product/includes/header.html create mode 100644 test/manual/watch-non-entry-partial-ejs/src/views/pages/about-product/index.html create mode 100644 test/manual/watch-non-entry-partial-ejs/src/views/pages/about/includes/header.html create mode 100644 test/manual/watch-non-entry-partial-ejs/src/views/pages/about/index.html create mode 100644 test/manual/watch-non-entry-partial-ejs/src/views/pages/home/includes/header.html create mode 100644 test/manual/watch-non-entry-partial-ejs/src/views/pages/home/index.html create mode 100644 test/manual/watch-non-entry-partial-ejs/webpack.config.js create mode 100644 test/manual/watch-non-entry-partial-pug/README.md create mode 100644 test/manual/watch-non-entry-partial-pug/package.json create mode 100644 test/manual/watch-non-entry-partial-pug/src/components/slider/slider.pug create mode 100644 test/manual/watch-non-entry-partial-pug/src/views/layouts/default.pug create mode 100644 test/manual/watch-non-entry-partial-pug/src/views/pages/about-product/includes/header.pug create mode 100644 test/manual/watch-non-entry-partial-pug/src/views/pages/about-product/index.pug create mode 100644 test/manual/watch-non-entry-partial-pug/src/views/pages/about/includes/header.pug create mode 100644 test/manual/watch-non-entry-partial-pug/src/views/pages/about/index.pug create mode 100644 test/manual/watch-non-entry-partial-pug/src/views/pages/home/includes/header.pug create mode 100644 test/manual/watch-non-entry-partial-pug/src/views/pages/home/index.pug create mode 100644 test/manual/watch-non-entry-partial-pug/webpack.config.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 2373a7f7..943f4c0e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Change log +## 3.6.2 (2024-03-11) + +- fix: avoid recompiling all entry templates after changes of a non-entry partial file, [pug-plugin issue](https://github.com/webdiscus/pug-plugin/issues/66) + ## 3.6.1 (2024-03-08) - fix: cannot find module 'nunjucks/src/object', introduced in v3.6.0 diff --git a/package-lock.json b/package-lock.json index 477d3d91..d276ee29 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "html-bundler-webpack-plugin", - "version": "3.5.3", + "version": "3.6.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "html-bundler-webpack-plugin", - "version": "3.5.3", + "version": "3.6.1", "license": "ISC", "dependencies": { "@types/html-minifier-terser": "^7.0.2", diff --git a/package.json b/package.json index 742fe4a5..8df208c6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "html-bundler-webpack-plugin", - "version": "3.6.1", + "version": "3.6.2", "description": "HTML bundler plugin for webpack handles a template as an entry point, extracts CSS and JS from their sources referenced in HTML, supports template engines like Eta, EJS, Handlebars, Nunjucks.", "keywords": [ "html", diff --git a/src/Loader/Dependency.js b/src/Loader/Dependency.js index dd581ebc..7f753263 100644 --- a/src/Loader/Dependency.js +++ b/src/Loader/Dependency.js @@ -1,3 +1,4 @@ +const path = require('path'); const { readDirRecursiveSync } = require('../Common/FileUtils'); const PluginService = require('../Plugin/PluginService'); const AssetEntry = require('../Plugin/AssetEntry'); @@ -11,18 +12,28 @@ class Dependency { static fileSystem = null; static files = new Set(); static directories = new Set(); - static loaderContext = null; static watchFiles = {}; - static #entryFiles = new Set(); + static entryFiles = new Set(); + static excludeDirs = []; + static loaderContext = null; static init(loaderContext) { if (!PluginService.isWatchMode()) return; + let watchFile = loaderContext.resourcePath; + PluginService.setDependencyInstance(this); this.loaderContext = loaderContext; this.fileSystem = loaderContext.fs.fileSystem; this.watchFiles = Option.getWatchFiles(); - this.#entryFiles = AssetEntry.getEntryFiles(); + this.entryFiles = AssetEntry.getEntryFiles(); + + this.excludeDirs = []; + this.entryFiles.forEach((entryFile) => { + let entryDir = path.dirname(entryFile) + path.sep; + if (!watchFile.startsWith(entryDir)) this.excludeDirs.push(entryDir); + }); + this.addFile = this.addFile.bind(this); const fs = this.fileSystem; @@ -69,18 +80,18 @@ class Dependency { static watch() { if (!PluginService.isWatchMode()) return; - const { loaderContext } = this; + const { loaderContext, excludeDirs } = this; - for (let dir of this.directories) { - loaderContext.addContextDependency(dir); - } + this.directories.forEach(loaderContext.addContextDependency); for (let file of this.files) { - if (!this.#entryFiles.has(file)) { - // the dependency already contains the current resource file, - // add for watching only files not defined in the entry to avoid unnecessary rebuilding of all templates - loaderContext.addDependency(file); + let isExcluded = excludeDirs.findIndex((dirname) => file.startsWith(dirname)) > -1; + + if (isExcluded || this.entryFiles.has(file)) { + // ignore all files from other entry directory or the current entry file, because it is already in the list + continue; } + loaderContext.addDependency(file); } } diff --git a/test/manual/watch-non-entry-partial-ejs/README.md b/test/manual/watch-non-entry-partial-ejs/README.md new file mode 100644 index 00000000..f181b66f --- /dev/null +++ b/test/manual/watch-non-entry-partial-ejs/README.md @@ -0,0 +1,20 @@ +## Problem `FIXED` in v3.6.2 + +Compiling all entrypoint files after changes of a non-entry file. + +**Project files** + +``` +pages/home/index.html <= entrypoint +pages/home/includes/header.html <= non entry partial + +pages/about/index.html <= entrypoint +pages/about/includes/header.html <= non entry partial +``` + +### Reproduce + +- change `pages/home/index.html` => will be rendered only this file. OK +- change `pages/home/includes/header.html` => will be recompiled pages: + - pages/home/index.html (with all dependencies), OK + - pages/about/index.html (with all dependencies), NOT OK, should not be recompiled (`FIXED`) diff --git a/test/manual/watch-non-entry-partial-ejs/package.json b/test/manual/watch-non-entry-partial-ejs/package.json new file mode 100644 index 00000000..56cf2560 --- /dev/null +++ b/test/manual/watch-non-entry-partial-ejs/package.json @@ -0,0 +1,10 @@ +{ + "scripts": { + "start": "webpack serve --mode development", + "watch": "webpack watch --mode development", + "build": "webpack --mode=production --progress" + }, + "devDependencies": { + "html-bundler-webpack-plugin": "file:../../.." + } +} diff --git a/test/manual/watch-non-entry-partial-ejs/src/components/slider/slider.html b/test/manual/watch-non-entry-partial-ejs/src/components/slider/slider.html new file mode 100644 index 00000000..493c85da --- /dev/null +++ b/test/manual/watch-non-entry-partial-ejs/src/components/slider/slider.html @@ -0,0 +1,5 @@ +
+
Slide 1
+
Slide 2
+
Slide 3
+
\ No newline at end of file diff --git a/test/manual/watch-non-entry-partial-ejs/src/views/pages/about-product/includes/header.html b/test/manual/watch-non-entry-partial-ejs/src/views/pages/about-product/includes/header.html new file mode 100644 index 00000000..e6b86f77 --- /dev/null +++ b/test/manual/watch-non-entry-partial-ejs/src/views/pages/about-product/includes/header.html @@ -0,0 +1 @@ +

About product 123456789

\ No newline at end of file diff --git a/test/manual/watch-non-entry-partial-ejs/src/views/pages/about-product/index.html b/test/manual/watch-non-entry-partial-ejs/src/views/pages/about-product/index.html new file mode 100644 index 00000000..ac289759 --- /dev/null +++ b/test/manual/watch-non-entry-partial-ejs/src/views/pages/about-product/index.html @@ -0,0 +1,11 @@ + + + + About product + + + <%- include('./includes/header.html') %> +

Test body: 123 45678

+ <%- include('../../../components/slider/slider.html') %> + + \ No newline at end of file diff --git a/test/manual/watch-non-entry-partial-ejs/src/views/pages/about/includes/header.html b/test/manual/watch-non-entry-partial-ejs/src/views/pages/about/includes/header.html new file mode 100644 index 00000000..926a7d6a --- /dev/null +++ b/test/manual/watch-non-entry-partial-ejs/src/views/pages/about/includes/header.html @@ -0,0 +1 @@ +

About 123

\ No newline at end of file diff --git a/test/manual/watch-non-entry-partial-ejs/src/views/pages/about/index.html b/test/manual/watch-non-entry-partial-ejs/src/views/pages/about/index.html new file mode 100644 index 00000000..e5c7816e --- /dev/null +++ b/test/manual/watch-non-entry-partial-ejs/src/views/pages/about/index.html @@ -0,0 +1,11 @@ + + + + About + + + <%- include('./includes/header.html') %> +

Test body: 123 4567

+ <%- include('../../../components/slider/slider.html') %> + + \ No newline at end of file diff --git a/test/manual/watch-non-entry-partial-ejs/src/views/pages/home/includes/header.html b/test/manual/watch-non-entry-partial-ejs/src/views/pages/home/includes/header.html new file mode 100644 index 00000000..9b586a88 --- /dev/null +++ b/test/manual/watch-non-entry-partial-ejs/src/views/pages/home/includes/header.html @@ -0,0 +1 @@ +

Home 123

\ No newline at end of file diff --git a/test/manual/watch-non-entry-partial-ejs/src/views/pages/home/index.html b/test/manual/watch-non-entry-partial-ejs/src/views/pages/home/index.html new file mode 100644 index 00000000..f35c6be5 --- /dev/null +++ b/test/manual/watch-non-entry-partial-ejs/src/views/pages/home/index.html @@ -0,0 +1,11 @@ + + + + Home + + + <%- include('./includes/header.html') %> +

Test body: 123

+ <%- include('../../../components/slider/slider.html') %> + + \ No newline at end of file diff --git a/test/manual/watch-non-entry-partial-ejs/webpack.config.js b/test/manual/watch-non-entry-partial-ejs/webpack.config.js new file mode 100644 index 00000000..e12d31ba --- /dev/null +++ b/test/manual/watch-non-entry-partial-ejs/webpack.config.js @@ -0,0 +1,50 @@ +const path = require('path'); +const HtmlBundlerPlugin = require('html-bundler-webpack-plugin'); + +module.exports = { + mode: 'development', + stats: 'minimal', + + output: { + path: path.join(__dirname, 'dist/'), + }, + + plugins: [ + new HtmlBundlerPlugin({ + entry: { + index: './src/views/pages/home/index.html', + about: './src/views/pages/about/index.html', + }, + preprocessor: 'ejs', + //preprocessor: false, + //hotUpdate: true, + //verbose: true, + }), + ], + + // module: { + // rules: [ + // { + // test: /\.(css)$/, + // use: ['css-loader'], + // }, + // ], + // }, + + // devServer: { + // static: { + // directory: path.join(__dirname, 'dist'), + // }, + // watchFiles: { + // paths: ['src/**/*.*'], + // options: { + // usePolling: true, + // }, + // }, + // }, + + watchOptions: { + // fix twice recompilation the same file + aggregateTimeout: 600, + }, +}; diff --git a/test/manual/watch-non-entry-partial-pug/README.md b/test/manual/watch-non-entry-partial-pug/README.md new file mode 100644 index 00000000..397276f9 --- /dev/null +++ b/test/manual/watch-non-entry-partial-pug/README.md @@ -0,0 +1,20 @@ +## Problem `FIXED` in v3.6.2 + +Compiling all entrypoint files after changes of a non-entry file. + +**Project files** + +``` +pages/home/index.pug <= entrypoint +pages/home/includes/header.pug <= non entry partial + +pages/about/index.pug <= entrypoint +pages/about/includes/header.pug <= non entry partial +``` + +### Reproduce + +- change `pages/home/index.pug` => will be rendered only this file. OK +- change `pages/home/includes/header.pug` => will be recompiled pages: + - pages/home/index.pug (with all dependencies), OK + - pages/about/index.pug (with all dependencies), NOT OK, should not be recompiled (`FIXED`) diff --git a/test/manual/watch-non-entry-partial-pug/package.json b/test/manual/watch-non-entry-partial-pug/package.json new file mode 100644 index 00000000..56cf2560 --- /dev/null +++ b/test/manual/watch-non-entry-partial-pug/package.json @@ -0,0 +1,10 @@ +{ + "scripts": { + "start": "webpack serve --mode development", + "watch": "webpack watch --mode development", + "build": "webpack --mode=production --progress" + }, + "devDependencies": { + "html-bundler-webpack-plugin": "file:../../.." + } +} diff --git a/test/manual/watch-non-entry-partial-pug/src/components/slider/slider.pug b/test/manual/watch-non-entry-partial-pug/src/components/slider/slider.pug new file mode 100644 index 00000000..bcd8c609 --- /dev/null +++ b/test/manual/watch-non-entry-partial-pug/src/components/slider/slider.pug @@ -0,0 +1,4 @@ +.slider + div Slide 1: 123 + div Slide 2 + div Slide 3 diff --git a/test/manual/watch-non-entry-partial-pug/src/views/layouts/default.pug b/test/manual/watch-non-entry-partial-pug/src/views/layouts/default.pug new file mode 100644 index 00000000..4b93bd38 --- /dev/null +++ b/test/manual/watch-non-entry-partial-pug/src/views/layouts/default.pug @@ -0,0 +1,6 @@ +html + head + block head + body + .nav Menu: 123 + block body diff --git a/test/manual/watch-non-entry-partial-pug/src/views/pages/about-product/includes/header.pug b/test/manual/watch-non-entry-partial-pug/src/views/pages/about-product/includes/header.pug new file mode 100644 index 00000000..f064e4fa --- /dev/null +++ b/test/manual/watch-non-entry-partial-pug/src/views/pages/about-product/includes/header.pug @@ -0,0 +1 @@ +h1 About product diff --git a/test/manual/watch-non-entry-partial-pug/src/views/pages/about-product/index.pug b/test/manual/watch-non-entry-partial-pug/src/views/pages/about-product/index.pug new file mode 100644 index 00000000..b34f2bd0 --- /dev/null +++ b/test/manual/watch-non-entry-partial-pug/src/views/pages/about-product/index.pug @@ -0,0 +1,9 @@ +extends ../../layouts/default + +block head + title About product + +block body + include includes/header + p Test body: 123 + include ../../../components/slider/slider diff --git a/test/manual/watch-non-entry-partial-pug/src/views/pages/about/includes/header.pug b/test/manual/watch-non-entry-partial-pug/src/views/pages/about/includes/header.pug new file mode 100644 index 00000000..b75b30f1 --- /dev/null +++ b/test/manual/watch-non-entry-partial-pug/src/views/pages/about/includes/header.pug @@ -0,0 +1 @@ +h1 About 123 diff --git a/test/manual/watch-non-entry-partial-pug/src/views/pages/about/index.pug b/test/manual/watch-non-entry-partial-pug/src/views/pages/about/index.pug new file mode 100644 index 00000000..7cf6994f --- /dev/null +++ b/test/manual/watch-non-entry-partial-pug/src/views/pages/about/index.pug @@ -0,0 +1,9 @@ +extends ../../layouts/default + +block head + title About + +block body + include includes/header + p Test body: 123 + include ../../../components/slider/slider diff --git a/test/manual/watch-non-entry-partial-pug/src/views/pages/home/includes/header.pug b/test/manual/watch-non-entry-partial-pug/src/views/pages/home/includes/header.pug new file mode 100644 index 00000000..5863bc87 --- /dev/null +++ b/test/manual/watch-non-entry-partial-pug/src/views/pages/home/includes/header.pug @@ -0,0 +1 @@ +h1 Home diff --git a/test/manual/watch-non-entry-partial-pug/src/views/pages/home/index.pug b/test/manual/watch-non-entry-partial-pug/src/views/pages/home/index.pug new file mode 100644 index 00000000..d0cf54d3 --- /dev/null +++ b/test/manual/watch-non-entry-partial-pug/src/views/pages/home/index.pug @@ -0,0 +1,9 @@ +extends ../../layouts/default + +block head + title Home + +block body + include includes/header + p Test body: 123 + include ../../../components/slider/slider diff --git a/test/manual/watch-non-entry-partial-pug/webpack.config.js b/test/manual/watch-non-entry-partial-pug/webpack.config.js new file mode 100644 index 00000000..5de4fbcf --- /dev/null +++ b/test/manual/watch-non-entry-partial-pug/webpack.config.js @@ -0,0 +1,49 @@ +const path = require('path'); +const HtmlBundlerPlugin = require('html-bundler-webpack-plugin'); + +module.exports = { + mode: 'production', + stats: 'minimal', + + output: { + path: path.join(__dirname, 'dist/'), + }, + + plugins: [ + new HtmlBundlerPlugin({ + entry: { + index: './src/views/pages/home/index.pug', + about: './src/views/pages/about/index.pug', + }, + preprocessor: 'pug', + hotUpdate: true, + //verbose: true, + }), + ], + + module: { + rules: [ + { + test: /\.(css)$/, + use: ['css-loader'], + }, + ], + }, + + devServer: { + static: { + directory: path.join(__dirname, 'dist'), + }, + watchFiles: { + paths: ['src/**/*.*'], + options: { + usePolling: true, + }, + }, + }, + + watchOptions: { + // fix twice recompilation the same file + aggregateTimeout: 600, + }, +};