diff --git a/lib/node/NodeTargetPlugin.js b/lib/node/NodeTargetPlugin.js index 33f785babff..adea6ab7801 100644 --- a/lib/node/NodeTargetPlugin.js +++ b/lib/node/NodeTargetPlugin.js @@ -11,6 +11,7 @@ const ExternalsPlugin = require("../ExternalsPlugin"); const builtins = [ "assert", + "assert/strict", "async_hooks", "buffer", "child_process", diff --git a/lib/optimize/RealContentHashPlugin.js b/lib/optimize/RealContentHashPlugin.js index ba058b753a2..9ceb157781d 100644 --- a/lib/optimize/RealContentHashPlugin.js +++ b/lib/optimize/RealContentHashPlugin.js @@ -178,43 +178,10 @@ class RealContentHashPlugin { } } if (hashToAssets.size === 0) return; - const hashRegExps = Array.from(hashToAssets.keys(), quoteMeta).map( - hash => new RegExp(hash, "g") + const hashRegExp = new RegExp( + Array.from(hashToAssets.keys(), quoteMeta).join("|"), + "g" ); - - /** - * @param {string} str string to be matched against all hashRegExps - * @returns {string[] | null} matches found - */ - const hashMatch = str => { - /** @type {string[]} */ - const results = []; - for (const hashRegExp of hashRegExps) { - const matches = str.match(hashRegExp); - if (matches) { - matches.forEach(match => results.push(match)); - } - } - if (results.length) { - return results; - } else { - return null; - } - }; - - /** - * @param {string} str string to be replaced with all hashRegExps - * @param {function(string): string} fn replacement function to use when a hash is found - * @returns {string} replaced content - */ - const hashReplace = (str, fn) => { - let result = str; - for (const hashRegExp of hashRegExps) { - result = result.replace(hashRegExp, fn); - } - return result; - }; - await Promise.all( assetsWithInfo.map(async asset => { const { name, source, content, hashes } = asset; @@ -231,7 +198,7 @@ class RealContentHashPlugin { await cacheAnalyse.providePromise(name, etag, () => { const referencedHashes = new Set(); let ownHashes = new Set(); - const inContent = hashMatch(content); + const inContent = content.match(hashRegExp); if (inContent) { for (const hash of inContent) { if (hashes.has(hash)) { @@ -331,7 +298,7 @@ ${referencingAssets identifier, etag, () => { - const newContent = hashReplace(asset.content, hash => + const newContent = asset.content.replace(hashRegExp, hash => hashToNewHash.get(hash) ); return new RawSource(newContent); @@ -356,12 +323,15 @@ ${referencingAssets identifier, etag, () => { - const newContent = hashReplace(asset.content, hash => { - if (asset.ownHashes.has(hash)) { - return ""; + const newContent = asset.content.replace( + hashRegExp, + hash => { + if (asset.ownHashes.has(hash)) { + return ""; + } + return hashToNewHash.get(hash); } - return hashToNewHash.get(hash); - }); + ); return new RawSource(newContent); } ); @@ -393,6 +363,9 @@ ${referencingAssets let newHash = hooks.updateHash.call(assetsContent, oldHash); if (!newHash) { const hash = createHash(this._hashFunction); + if (compilation.outputOptions.hashSalt) { + hash.update(compilation.outputOptions.hashSalt); + } for (const content of assetsContent) { hash.update(content); } @@ -404,7 +377,7 @@ ${referencingAssets await Promise.all( assetsWithInfo.map(async asset => { await computeNewContent(asset); - const newName = hashReplace(asset.name, hash => + const newName = asset.name.replace(hashRegExp, hash => hashToNewHash.get(hash) ); diff --git a/package.json b/package.json index 2a604bfd149..5e3ff54f9ac 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "webpack", - "version": "5.75.0", + "version": "5.76.1", "author": "Tobias Koppers @sokra", "description": "Packs CommonJs/AMD modules for the browser. Allows to split your codebase into multiple bundles, which can be loaded on demand. Support loaders to preprocess files, i.e. json, jsx, es7, css, less, ... and your custom stuff.", "license": "MIT", diff --git a/test/configCases/contenthash/salt/img.jpg b/test/configCases/contenthash/salt/img.jpg new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/configCases/contenthash/salt/index.js b/test/configCases/contenthash/salt/index.js new file mode 100644 index 00000000000..2d2b98703ee --- /dev/null +++ b/test/configCases/contenthash/salt/index.js @@ -0,0 +1,5 @@ +import img from "./img.jpg"; + +it("should compile", () => { + expect(typeof img).toBe("string"); +}); diff --git a/test/configCases/contenthash/salt/test.config.js b/test/configCases/contenthash/salt/test.config.js new file mode 100644 index 00000000000..530c9147c05 --- /dev/null +++ b/test/configCases/contenthash/salt/test.config.js @@ -0,0 +1,24 @@ +const findOutputFiles = require("../../../helpers/findOutputFiles"); + +const allAssets = new Set(); +const allBundles = new Set(); + +module.exports = { + findBundle: function(i, options) { + const bundle = findOutputFiles(options, new RegExp(`^bundle${i}`))[0]; + allBundles.add(/\.([^.]+)\./.exec(bundle)[1]); + + const assets = findOutputFiles(options, /^img/); + for (const asset of assets) { + allAssets.add(asset); + } + + return `./${bundle}`; + }, + afterExecute: () => { + // Since there are exactly 2 unique values of output.hashSalt, + // there should be exactly 2 unique output hashes for each file. + expect(allBundles.size).toBe(2); + expect(allAssets.size).toBe(2); + } +}; diff --git a/test/configCases/contenthash/salt/webpack.config.js b/test/configCases/contenthash/salt/webpack.config.js new file mode 100644 index 00000000000..1ec1c83b9d9 --- /dev/null +++ b/test/configCases/contenthash/salt/webpack.config.js @@ -0,0 +1,48 @@ +/** @type {import("../../../../").Configuration[]} */ +module.exports = [ + { + output: { + filename: "bundle0.[contenthash].js", + assetModuleFilename: "[name].[contenthash][ext]", + hashSalt: "1" + }, + module: { + rules: [ + { + test: /\.jpg$/, + type: "asset/resource" + } + ] + } + }, + { + output: { + filename: "bundle1.[contenthash].js", + assetModuleFilename: "[name].[contenthash][ext]", + hashSalt: "1" + }, + module: { + rules: [ + { + test: /\.jpg$/, + type: "asset/resource" + } + ] + } + }, + { + output: { + filename: "bundle2.[contenthash].js", + assetModuleFilename: "[name].[contenthash][ext]", + hashSalt: "2" + }, + module: { + rules: [ + { + test: /\.jpg$/, + type: "asset/resource" + } + ] + } + } +];