From 23d32e5f02cb810d1c3884a25ac682f8e30e592b Mon Sep 17 00:00:00 2001 From: Hugo Alliaume Date: Thu, 26 Sep 2024 22:13:31 +0200 Subject: [PATCH] Add support for integrity hashes when asset names contain a query string --- CHANGELOG.md | 2 ++ lib/webpack/entry-points-plugin.js | 9 ++++++--- test/functional.js | 29 +++++++++++++++++++++++++++++ 3 files changed, 37 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f291adf2..2f807d93 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,8 @@ This is a new major version that contains several backwards-compatibility breaks * #1344 Add options configuration callback to `Encore.enableReactPreset()` (@Kocal) +* #1345 Add support for integrity hashes when asset names contain a query string (@Kocal) + ### BC Breaks * #1321 Drop support of Node.js 19 and 21 (@Kocal) diff --git a/lib/webpack/entry-points-plugin.js b/lib/webpack/entry-points-plugin.js index 59a538e0..796ed6eb 100644 --- a/lib/webpack/entry-points-plugin.js +++ b/lib/webpack/entry-points-plugin.js @@ -95,13 +95,16 @@ class EntryPointsPlugin { for (const entryName in manifest.entrypoints) { for (const fileType in manifest.entrypoints[entryName]) { for (const asset of manifest.entrypoints[entryName][fileType]) { - if (asset in manifest.integrity) { + // Drop query string if any + const assetNormalized = asset.includes('?') ? asset.split('?')[0] : asset; + + if (assetNormalized in manifest.integrity) { continue; } const filePath = path.resolve( this.outputPath, - asset.replace(this.publicPath, ''), + assetNormalized.replace(this.publicPath, ''), ); if (fs.existsSync(filePath)) { @@ -115,7 +118,7 @@ class EntryPointsPlugin { fileHashes.push(`${algorithm}-${hash.digest('base64')}`); } - manifest.integrity[asset] = fileHashes.join(' '); + manifest.integrity[assetNormalized] = fileHashes.join(' '); } } } diff --git a/test/functional.js b/test/functional.js index ac600457..7e39eb52 100644 --- a/test/functional.js +++ b/test/functional.js @@ -3123,6 +3123,35 @@ module.exports = { done(); }); }); + + it('With query string versioning', (done) => { + const config = createWebpackConfig('web/build', 'dev'); + config.addEntry('main', './js/no_require'); + config.setPublicPath('/build'); + config.addStyleEntry('styles', './css/h1_style.css'); + config.enableVersioning(true); + config.configureFilenames({ + js: '[name].js?v=[contenthash:16]', + css: '[name].css?v=[contenthash:16]' + }); + config.enableIntegrityHashes(); + + testSetup.runWebpack(config, (webpackAssert) => { + const integrityData = getIntegrityData(config); + const expectedFilesWithHashes = [ + '/build/runtime.js', + '/build/main.js', + '/build/styles.css', + ]; + + expectedFilesWithHashes.forEach((file) => { + expect(integrityData[file]).to.contain('sha384-'); + expect(integrityData[file]).to.have.length(71); + }); + + done(); + }); + }); }); }); });