From 2da54ab6b61e7e13624d2cfe4fc613f09a3222af Mon Sep 17 00:00:00 2001 From: rvlb Date: Wed, 29 Oct 2025 10:21:50 -0300 Subject: [PATCH 1/7] Fix tests --- .github/workflows/config.yml | 20 ------------ lib/index.js | 60 ++++++++++++++++++++---------------- package.json | 3 ++ 3 files changed, 37 insertions(+), 46 deletions(-) diff --git a/.github/workflows/config.yml b/.github/workflows/config.yml index 4abcce4..59c5f4f 100644 --- a/.github/workflows/config.yml +++ b/.github/workflows/config.yml @@ -7,26 +7,6 @@ on: branches: [ master ] jobs: - # Oldest maintenance LTS, End-of-Life 2025-04-30 - test-node-18: - runs-on: ubuntu-latest - container: - image: node:18.19 - env: - NODE_OPTIONS: --openssl-legacy-provider - steps: - - name: Checkout - uses: actions/checkout@v4 - - name: Set up Node.js - run: | - echo "Node version: $(node --version)" - echo "NPM version: $(npm --version)" - npm install - npm run ci - - name: Unset NODE_OPTIONS - run: | - unset NODE_OPTIONS - test: runs-on: ubuntu-latest strategy: diff --git a/lib/index.js b/lib/index.js index e98c5cd..ccf351d 100644 --- a/lib/index.js +++ b/lib/index.js @@ -56,6 +56,7 @@ class BundleTrackerPlugin { }; this.name = 'BundleTrackerPlugin'; + this.output = {}; this.outputChunkDir = ''; this.outputTrackerFile = ''; this.outputTrackerDir = ''; @@ -145,29 +146,8 @@ class BundleTrackerPlugin { _handleCompile(compiler) { this._writeOutput(compiler, { status: 'compile' }); } - /** - * Handle compile hook - * @param {Compiler} compiler - * @param {Stats} stats - */ - _handleDone(compiler, stats) { - if (stats.hasErrors()) { - const findError = compilation => { - if (compilation.errors.length > 0) { - return compilation.errors[0]; - } - return compilation.children.find(child => findError(child)); - }; - const error = findError(stats.compilation); - this._writeOutput(compiler, { - status: 'error', - error: error?.name ?? 'unknown-error', - message: stripAnsi(error['message']), - }); - - return; - } + _handleAssetEmitted(_compiler, _, stats) { /** @type {Contents} */ const output = { status: 'done', assets: {}, chunks: {} }; Object.entries(stats.compilation.assets).map(([assetName, _]) => { @@ -200,19 +180,46 @@ class BundleTrackerPlugin { output.assets[assetName] = fileInfo; }); + this.output = output; + } + + /** + * Handle compile hook + * @param {Compiler} compiler + * @param {Stats} stats + */ + _handleDone(compiler, stats) { + if (stats.hasErrors()) { + const findError = compilation => { + if (compilation.errors.length > 0) { + return compilation.errors[0]; + } + return compilation.children.find(child => findError(child)); + }; + const error = findError(stats.compilation); + this._writeOutput(compiler, { + status: 'error', + error: error?.name ?? 'unknown-error', + message: stripAnsi(error['message']), + }); + + return; + } + stats.compilation.chunkGroups.forEach(chunkGroup => { if (!chunkGroup.isInitial()) return; - output.chunks[chunkGroup.name] = chunkGroup.getFiles(); + this.output.chunks[chunkGroup.name] = chunkGroup.getFiles(); }); if (this.options.logTime === true) { - output.startTime = stats.startTime; - output.endTime = stats.endTime; + this.output.startTime = stats.startTime; + this.output.endTime = stats.endTime; } - this._writeOutput(compiler, output); + this._writeOutput(compiler, this.output); } + /** * Method called by webpack to apply plugin hook * @param {Compiler} compiler @@ -221,6 +228,7 @@ class BundleTrackerPlugin { this._setParamsFromCompiler(compiler); compiler.hooks.compile.tap(this.name, this._handleCompile.bind(this, compiler)); + compiler.hooks.assetEmitted.tap(this.name, this._handleAssetEmitted.bind(this, compiler)); compiler.hooks.done.tap(this.name, this._handleDone.bind(this, compiler)); } } diff --git a/package.json b/package.json index 7c8cf63..2c72a31 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,9 @@ ], "homepage": "https://github.com/django-webpack/webpack-bundle-tracker", "bugs": "https://github.com/django-webpack/webpack-bundle-tracker/issues", + "engines": { + "node": ">=22.0.0" + }, "repository": { "type": "git", "url": "git+https://github.com/django-webpack/webpack-bundle-tracker.git" From c3eae8b63f78c790afa8c1216c532ca22b97b6f4 Mon Sep 17 00:00:00 2001 From: rvlb Date: Wed, 29 Oct 2025 14:52:59 -0300 Subject: [PATCH 2/7] Fix flow for webpack5 --- lib/index.js | 83 +++++++++++++++++++++++++--------------------------- package.json | 2 +- 2 files changed, 41 insertions(+), 44 deletions(-) diff --git a/lib/index.js b/lib/index.js index ccf351d..a2da5cf 100644 --- a/lib/index.js +++ b/lib/index.js @@ -56,7 +56,11 @@ class BundleTrackerPlugin { }; this.name = 'BundleTrackerPlugin'; - this.output = {}; + this.output = { + status: 'compile', + assets: {}, + chunks: {}, + }; this.outputChunkDir = ''; this.outputTrackerFile = ''; this.outputTrackerDir = ''; @@ -104,11 +108,9 @@ class BundleTrackerPlugin { } /** * Write bundle tracker stats file - * - * @param {Compiler} _compiler - * @param {Partial} contents */ - _writeOutput(_compiler, contents) { + _writeOutput() { + const contents = this.output; Object.assign(this.contents, contents, { assets: mergeObjectsAndSortKeys(this.contents.assets, contents.assets), chunks: mergeObjectsAndSortKeys(this.contents.chunks, contents.chunks), @@ -141,54 +143,50 @@ class BundleTrackerPlugin { } /** * Handle compile hook - * @param {Compiler} compiler + * @param {Compiler} _compiler */ - _handleCompile(compiler) { - this._writeOutput(compiler, { status: 'compile' }); + _handleCompile(_compiler) { + this.output = { status: 'compile', assets: {}, chunks: {} }; + this._writeOutput(); } - _handleAssetEmitted(_compiler, _, stats) { - /** @type {Contents} */ - const output = { status: 'done', assets: {}, chunks: {} }; - Object.entries(stats.compilation.assets).map(([assetName, _]) => { - const fileInfo = { - name: assetName, - path: getAssetPath(stats.compilation, assetName), - }; + _handleAssetEmitted(_compiler, assetName, stats) { + const fileInfo = { + name: assetName, + path: getAssetPath(stats.compilation, assetName), + }; - if (this.options.integrity === true) { - fileInfo.integrity = this._computeIntegrity(getSource(stats.compilation, assetName)); - } + if (this.options.integrity === true) { + fileInfo.integrity = this._computeIntegrity(getSource(stats.compilation, assetName)); + } - if (this.options.publicPath) { - if (this.options.publicPath === 'auto') { - fileInfo.publicPath = 'auto'; - } else { - fileInfo.publicPath = this.options.publicPath + assetName; - } + if (this.options.publicPath) { + if (this.options.publicPath === 'auto') { + fileInfo.publicPath = 'auto'; + } else { + fileInfo.publicPath = this.options.publicPath + assetName; } + } - if (this.options.relativePath === true) { - fileInfo.path = path.relative(this.outputChunkDir, fileInfo.path); - } + if (this.options.relativePath === true) { + fileInfo.path = path.relative(this.outputChunkDir, fileInfo.path); + } + // @ts-ignore: TS2339: Property 'assetsInfo' does not exist on type 'Compilation'. + if (stats.compilation.assetsInfo) { // @ts-ignore: TS2339: Property 'assetsInfo' does not exist on type 'Compilation'. - if (stats.compilation.assetsInfo) { - // @ts-ignore: TS2339: Property 'assetsInfo' does not exist on type 'Compilation'. - fileInfo.sourceFilename = stats.compilation.assetsInfo.get(assetName).sourceFilename; - } + fileInfo.sourceFilename = stats.compilation.assetsInfo.get(assetName).sourceFilename; + } - output.assets[assetName] = fileInfo; - }); - this.output = output; + this.output.assets[assetName] = fileInfo; } /** * Handle compile hook - * @param {Compiler} compiler + * @param {Compiler} _compiler * @param {Stats} stats */ - _handleDone(compiler, stats) { + _handleDone(_compiler, stats) { if (stats.hasErrors()) { const findError = compilation => { if (compilation.errors.length > 0) { @@ -197,18 +195,18 @@ class BundleTrackerPlugin { return compilation.children.find(child => findError(child)); }; const error = findError(stats.compilation); - this._writeOutput(compiler, { + this.output = { status: 'error', error: error?.name ?? 'unknown-error', message: stripAnsi(error['message']), - }); + }; + this._writeOutput(); return; } stats.compilation.chunkGroups.forEach(chunkGroup => { if (!chunkGroup.isInitial()) return; - this.output.chunks[chunkGroup.name] = chunkGroup.getFiles(); }); @@ -216,8 +214,8 @@ class BundleTrackerPlugin { this.output.startTime = stats.startTime; this.output.endTime = stats.endTime; } - - this._writeOutput(compiler, this.output); + this.output.status = 'done'; + this._writeOutput(); } /** @@ -226,7 +224,6 @@ class BundleTrackerPlugin { */ apply(compiler) { this._setParamsFromCompiler(compiler); - compiler.hooks.compile.tap(this.name, this._handleCompile.bind(this, compiler)); compiler.hooks.assetEmitted.tap(this.name, this._handleAssetEmitted.bind(this, compiler)); compiler.hooks.done.tap(this.name, this._handleDone.bind(this, compiler)); diff --git a/package.json b/package.json index 2c72a31..8427a42 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "homepage": "https://github.com/django-webpack/webpack-bundle-tracker", "bugs": "https://github.com/django-webpack/webpack-bundle-tracker/issues", "engines": { - "node": ">=22.0.0" + "node": ">=20.0.0" }, "repository": { "type": "git", From 4a38afb382ab5e2ae047856b1c3d211908435902 Mon Sep 17 00:00:00 2001 From: rvlb Date: Wed, 29 Oct 2025 15:18:01 -0300 Subject: [PATCH 3/7] Refactor compilation logic and fix webpack4 flow --- lib/index.js | 39 ++++++++++++++++++++++++++------------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/lib/index.js b/lib/index.js index a2da5cf..8e6297f 100644 --- a/lib/index.js +++ b/lib/index.js @@ -143,21 +143,31 @@ class BundleTrackerPlugin { } /** * Handle compile hook - * @param {Compiler} _compiler */ - _handleCompile(_compiler) { + _handleCompile() { this.output = { status: 'compile', assets: {}, chunks: {} }; this._writeOutput(); } - _handleAssetEmitted(_compiler, assetName, stats) { + /** + * Hook to inject the webpack compilation object + */ + _handleThisCompilation(compilation) { + this._compilation = compilation; + } + + /** + * Hook to handle each compiled asset and set their + * info into the output object + */ + _handleAssetEmitted(assetName) { const fileInfo = { name: assetName, - path: getAssetPath(stats.compilation, assetName), + path: getAssetPath(this._compilation, assetName), }; if (this.options.integrity === true) { - fileInfo.integrity = this._computeIntegrity(getSource(stats.compilation, assetName)); + fileInfo.integrity = this._computeIntegrity(getSource(this._compilation, assetName)); } if (this.options.publicPath) { @@ -173,20 +183,19 @@ class BundleTrackerPlugin { } // @ts-ignore: TS2339: Property 'assetsInfo' does not exist on type 'Compilation'. - if (stats.compilation.assetsInfo) { + if (this._compilation.assetsInfo) { // @ts-ignore: TS2339: Property 'assetsInfo' does not exist on type 'Compilation'. - fileInfo.sourceFilename = stats.compilation.assetsInfo.get(assetName).sourceFilename; + fileInfo.sourceFilename = this._compilation.assetsInfo.get(assetName).sourceFilename; } this.output.assets[assetName] = fileInfo; } /** - * Handle compile hook - * @param {Compiler} _compiler + * Handle done hook and write output file * @param {Stats} stats */ - _handleDone(_compiler, stats) { + _handleDone(stats) { if (stats.hasErrors()) { const findError = compilation => { if (compilation.errors.length > 0) { @@ -195,6 +204,7 @@ class BundleTrackerPlugin { return compilation.children.find(child => findError(child)); }; const error = findError(stats.compilation); + // @ts-ignore: TS2739 this.output = { status: 'error', error: error?.name ?? 'unknown-error', @@ -224,9 +234,12 @@ class BundleTrackerPlugin { */ apply(compiler) { this._setParamsFromCompiler(compiler); - compiler.hooks.compile.tap(this.name, this._handleCompile.bind(this, compiler)); - compiler.hooks.assetEmitted.tap(this.name, this._handleAssetEmitted.bind(this, compiler)); - compiler.hooks.done.tap(this.name, this._handleDone.bind(this, compiler)); + compiler.hooks.compile.tap(this.name, this._handleCompile.bind(this)); + // The thisCompilation hook is required here because webpack4 does not properly + // inject the stats object with the compilation data into the assetEmitted hook + compiler.hooks.thisCompilation.tap(this.name, this._handleThisCompilation.bind(this)); + compiler.hooks.assetEmitted.tap(this.name, this._handleAssetEmitted.bind(this)); + compiler.hooks.done.tap(this.name, this._handleDone.bind(this)); } } From 7aed240c60c6f1204bd05450aff95ef01e8537f0 Mon Sep 17 00:00:00 2001 From: rvlb Date: Wed, 29 Oct 2025 15:28:52 -0300 Subject: [PATCH 4/7] Refactors output handling --- lib/index.js | 44 ++++++++++++++++++-------------------------- 1 file changed, 18 insertions(+), 26 deletions(-) diff --git a/lib/index.js b/lib/index.js index 8e6297f..e972ce4 100644 --- a/lib/index.js +++ b/lib/index.js @@ -49,18 +49,14 @@ class BundleTrackerPlugin { /** @type {Options} */ this.options = options; /** @type {Contents} */ - this.contents = { + this.output = { status: 'initialization', assets: {}, chunks: {}, }; this.name = 'BundleTrackerPlugin'; - this.output = { - status: 'compile', - assets: {}, - chunks: {}, - }; + this.assets = {}; this.outputChunkDir = ''; this.outputTrackerFile = ''; this.outputTrackerDir = ''; @@ -109,19 +105,18 @@ class BundleTrackerPlugin { /** * Write bundle tracker stats file */ - _writeOutput() { - const contents = this.output; - Object.assign(this.contents, contents, { - assets: mergeObjectsAndSortKeys(this.contents.assets, contents.assets), - chunks: mergeObjectsAndSortKeys(this.contents.chunks, contents.chunks), + _writeOutput(contents) { + Object.assign(this.output, contents, { + assets: mergeObjectsAndSortKeys(this.output.assets, contents.assets), + chunks: mergeObjectsAndSortKeys(this.output.chunks, contents.chunks), }); if (this.options.publicPath) { - this.contents.publicPath = this.options.publicPath; + this.output.publicPath = this.options.publicPath; } fs.mkdirSync(this.outputTrackerDir, { recursive: true, mode: 0o755 }); - fs.writeFileSync(this.outputTrackerFile, JSON.stringify(this.contents, null, this.options.indent)); + fs.writeFileSync(this.outputTrackerFile, JSON.stringify(this.output, null, this.options.indent)); } /** * Compute hash for a content @@ -145,8 +140,7 @@ class BundleTrackerPlugin { * Handle compile hook */ _handleCompile() { - this.output = { status: 'compile', assets: {}, chunks: {} }; - this._writeOutput(); + this._writeOutput({ status: 'compile' }); } /** @@ -188,7 +182,7 @@ class BundleTrackerPlugin { fileInfo.sourceFilename = this._compilation.assetsInfo.get(assetName).sourceFilename; } - this.output.assets[assetName] = fileInfo; + this.assets[assetName] = fileInfo; } /** @@ -204,28 +198,26 @@ class BundleTrackerPlugin { return compilation.children.find(child => findError(child)); }; const error = findError(stats.compilation); - // @ts-ignore: TS2739 - this.output = { + this._writeOutput({ status: 'error', error: error?.name ?? 'unknown-error', message: stripAnsi(error['message']), - }; - this._writeOutput(); - + }); return; } + const chunks = {}; stats.compilation.chunkGroups.forEach(chunkGroup => { if (!chunkGroup.isInitial()) return; - this.output.chunks[chunkGroup.name] = chunkGroup.getFiles(); + chunks[chunkGroup.name] = chunkGroup.getFiles(); }); + const output = { status: 'done', chunks, assets: this.assets }; if (this.options.logTime === true) { - this.output.startTime = stats.startTime; - this.output.endTime = stats.endTime; + output.startTime = stats.startTime; + output.endTime = stats.endTime; } - this.output.status = 'done'; - this._writeOutput(); + this._writeOutput(output); } /** From 278cc182d7e147c56022d47e2b60d009960371dd Mon Sep 17 00:00:00 2001 From: rvlb Date: Thu, 30 Oct 2025 09:24:16 -0300 Subject: [PATCH 5/7] Set release version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8427a42..6bf658e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "webpack-bundle-tracker", - "version": "3.2.1", + "version": "3.2.2", "description": "Spits out some stats about webpack compilation process to a file", "keywords": [ "bundle", From 9d56786d6a8ea3c31a1b2edc79b0c8b6a73a150d Mon Sep 17 00:00:00 2001 From: rvlb Date: Thu, 30 Oct 2025 19:26:15 -0300 Subject: [PATCH 6/7] Fix how assets are obtained in the pipeline --- lib/index.js | 68 ++++++++++++++++------------------- tests/base.test.js | 81 ++++++++++++++++++++++++++++++++++++++++++ tests/webpack5.test.js | 81 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 192 insertions(+), 38 deletions(-) diff --git a/lib/index.js b/lib/index.js index e972ce4..f5e74b2 100644 --- a/lib/index.js +++ b/lib/index.js @@ -17,9 +17,8 @@ function getAssetPath(compilation, name) { return path.join(compilation.getPath(compilation.compiler.outputPath), name.split('?')[0]); } -function getSource(compilation, name) { - const path = getAssetPath(compilation, name); - return fs.readFileSync(path, { encoding: 'utf-8' }); +function getSource(asset) { + return asset.source.source(); } /** @@ -144,45 +143,41 @@ class BundleTrackerPlugin { } /** - * Hook to inject the webpack compilation object + * Hook to handle the assets when they are ready to be emitted + * @param {Compilation} compilation */ - _handleThisCompilation(compilation) { - this._compilation = compilation; - } - - /** - * Hook to handle each compiled asset and set their - * info into the output object - */ - _handleAssetEmitted(assetName) { - const fileInfo = { - name: assetName, - path: getAssetPath(this._compilation, assetName), - }; + _handleEmit(compilation) { + Object.keys(compilation.assets).forEach(assetName => { + const fileInfo = { + name: assetName, + path: getAssetPath(compilation, assetName), + }; - if (this.options.integrity === true) { - fileInfo.integrity = this._computeIntegrity(getSource(this._compilation, assetName)); - } + if (this.options.integrity === true) { + const asset = compilation.getAsset(assetName); + fileInfo.integrity = this._computeIntegrity(getSource(asset)); + } - if (this.options.publicPath) { - if (this.options.publicPath === 'auto') { - fileInfo.publicPath = 'auto'; - } else { - fileInfo.publicPath = this.options.publicPath + assetName; + if (this.options.publicPath) { + if (this.options.publicPath === 'auto') { + fileInfo.publicPath = 'auto'; + } else { + fileInfo.publicPath = this.options.publicPath + assetName; + } } - } - if (this.options.relativePath === true) { - fileInfo.path = path.relative(this.outputChunkDir, fileInfo.path); - } + if (this.options.relativePath === true) { + fileInfo.path = path.relative(this.outputChunkDir, fileInfo.path); + } - // @ts-ignore: TS2339: Property 'assetsInfo' does not exist on type 'Compilation'. - if (this._compilation.assetsInfo) { // @ts-ignore: TS2339: Property 'assetsInfo' does not exist on type 'Compilation'. - fileInfo.sourceFilename = this._compilation.assetsInfo.get(assetName).sourceFilename; - } + if (compilation.assetsInfo) { + // @ts-ignore: TS2339: Property 'assetsInfo' does not exist on type 'Compilation'. + fileInfo.sourceFilename = compilation.assetsInfo.get(assetName).sourceFilename; + } - this.assets[assetName] = fileInfo; + this.assets[assetName] = fileInfo; + }); } /** @@ -227,10 +222,7 @@ class BundleTrackerPlugin { apply(compiler) { this._setParamsFromCompiler(compiler); compiler.hooks.compile.tap(this.name, this._handleCompile.bind(this)); - // The thisCompilation hook is required here because webpack4 does not properly - // inject the stats object with the compilation data into the assetEmitted hook - compiler.hooks.thisCompilation.tap(this.name, this._handleThisCompilation.bind(this)); - compiler.hooks.assetEmitted.tap(this.name, this._handleAssetEmitted.bind(this)); + compiler.hooks.emit.tap(this.name, this._handleEmit.bind(this)); compiler.hooks.done.tap(this.name, this._handleDone.bind(this)); } } diff --git a/tests/base.test.js b/tests/base.test.js index 0ed9c4b..4fffc61 100644 --- a/tests/base.test.js +++ b/tests/base.test.js @@ -64,6 +64,87 @@ describe('BundleTrackerPlugin bases tests', () => { ); }); + it('It should generate the stats file when the plugin runs twice and the output assets already exist', done => { + const expectErrors = null; + const expectWarnings = getWebpack4WarningMessage(); + + // 1st run + testPlugin( + webpack, + { + context: __dirname, + entry: path.resolve(__dirname, 'fixtures', 'index.js'), + output: { + path: OUTPUT_DIR, + filename: 'js/[name].js', + publicPath: 'http://localhost:3000/assets/', + }, + plugins: [ + new BundleTrackerPlugin({ + path: OUTPUT_DIR, + filename: 'webpack-stats.json', + }), + ], + }, + { + status: 'done', + publicPath: 'http://localhost:3000/assets/', + chunks: { + main: ['js/main.js'], + }, + assets: { + 'js/main.js': { + name: 'js/main.js', + path: OUTPUT_DIR + '/js/main.js', + publicPath: 'http://localhost:3000/assets/js/main.js', + }, + }, + }, + 'webpack-stats.json', + jest.fn(), + expectErrors, + expectWarnings, + ); + + // 2nd run + testPlugin( + webpack, + { + context: __dirname, + entry: path.resolve(__dirname, 'fixtures', 'index.js'), + output: { + path: OUTPUT_DIR, + filename: 'js/[name].js', + publicPath: 'http://localhost:3000/assets/', + }, + plugins: [ + new BundleTrackerPlugin({ + path: OUTPUT_DIR, + filename: 'webpack-stats.json', + }), + ], + }, + { + status: 'done', + publicPath: 'http://localhost:3000/assets/', + chunks: { + main: ['js/main.js'], + }, + assets: { + 'js/main.js': { + name: 'js/main.js', + path: OUTPUT_DIR + '/js/main.js', + publicPath: 'http://localhost:3000/assets/js/main.js', + }, + }, + }, + 'webpack-stats.json', + done, + expectErrors, + expectWarnings, + ); + }); + it('It should add log time when option is set', done => { const expectErrors = null; const expectWarnings = getWebpack4WarningMessage(); diff --git a/tests/webpack5.test.js b/tests/webpack5.test.js index 3c1fe3b..9d7e735 100644 --- a/tests/webpack5.test.js +++ b/tests/webpack5.test.js @@ -64,6 +64,87 @@ describe('BundleTrackerPlugin bases tests', () => { ); }); + it('It should generate the stats file when the plugin runs twice and the output assets already exist', done => { + const expectErrors = null; + const expectWarnings = getWebpack5WarningMessage(); + + // 1st run + testPlugin( + webpack5, + { + context: __dirname, + entry: path.resolve(__dirname, 'fixtures', 'index.js'), + output: { + path: OUTPUT_DIR, + filename: 'js/[name].js', + publicPath: 'http://localhost:3000/assets/', + }, + plugins: [ + new BundleTrackerPlugin({ + path: OUTPUT_DIR, + filename: 'webpack-stats.json', + }), + ], + }, + { + status: 'done', + publicPath: 'http://localhost:3000/assets/', + chunks: { + main: ['js/main.js'], + }, + assets: { + 'js/main.js': { + name: 'js/main.js', + path: OUTPUT_DIR + '/js/main.js', + publicPath: 'http://localhost:3000/assets/js/main.js', + }, + }, + }, + 'webpack-stats.json', + jest.fn(), + expectErrors, + expectWarnings, + ); + + // 2nd run + testPlugin( + webpack5, + { + context: __dirname, + entry: path.resolve(__dirname, 'fixtures', 'index.js'), + output: { + path: OUTPUT_DIR, + filename: 'js/[name].js', + publicPath: 'http://localhost:3000/assets/', + }, + plugins: [ + new BundleTrackerPlugin({ + path: OUTPUT_DIR, + filename: 'webpack-stats.json', + }), + ], + }, + { + status: 'done', + publicPath: 'http://localhost:3000/assets/', + chunks: { + main: ['js/main.js'], + }, + assets: { + 'js/main.js': { + name: 'js/main.js', + path: OUTPUT_DIR + '/js/main.js', + publicPath: 'http://localhost:3000/assets/js/main.js', + }, + }, + }, + 'webpack-stats.json', + done, + expectErrors, + expectWarnings, + ); + }); + it('It should add log time when option is set', done => { const expectErrors = null; const expectWarnings = getWebpack5WarningMessage(); From 31eaa9245fb0a96a2c3e268ed1c95f8bc7f17c0b Mon Sep 17 00:00:00 2001 From: rvlb Date: Tue, 4 Nov 2025 16:08:22 -0300 Subject: [PATCH 7/7] Rename this.output as this.contents --- lib/index.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/index.js b/lib/index.js index f5e74b2..9373e14 100644 --- a/lib/index.js +++ b/lib/index.js @@ -48,7 +48,7 @@ class BundleTrackerPlugin { /** @type {Options} */ this.options = options; /** @type {Contents} */ - this.output = { + this.contents = { status: 'initialization', assets: {}, chunks: {}, @@ -105,17 +105,17 @@ class BundleTrackerPlugin { * Write bundle tracker stats file */ _writeOutput(contents) { - Object.assign(this.output, contents, { - assets: mergeObjectsAndSortKeys(this.output.assets, contents.assets), - chunks: mergeObjectsAndSortKeys(this.output.chunks, contents.chunks), + Object.assign(this.contents, contents, { + assets: mergeObjectsAndSortKeys(this.contents.assets, contents.assets), + chunks: mergeObjectsAndSortKeys(this.contents.chunks, contents.chunks), }); if (this.options.publicPath) { - this.output.publicPath = this.options.publicPath; + this.contents.publicPath = this.options.publicPath; } fs.mkdirSync(this.outputTrackerDir, { recursive: true, mode: 0o755 }); - fs.writeFileSync(this.outputTrackerFile, JSON.stringify(this.output, null, this.options.indent)); + fs.writeFileSync(this.outputTrackerFile, JSON.stringify(this.contents, null, this.options.indent)); } /** * Compute hash for a content