diff --git a/src/index.js b/src/index.js index a195992..9e462b8 100644 --- a/src/index.js +++ b/src/index.js @@ -15,7 +15,6 @@ export default function loader(content) { const context = options.context || this.rootContext; const name = options.name || '[contenthash].[ext]'; - const immutable = /\[([^:\]]+:)?(hash|contenthash)(:[^\]]+)?\]/gi.test(name); const url = interpolateName(this, name, { context, @@ -54,7 +53,27 @@ export default function loader(content) { } if (typeof options.emitFile === 'undefined' || options.emitFile) { - this.emitFile(outputPath, content, null, { immutable }); + const assetInfo = {}; + + if (typeof name === 'string') { + let normalizedName = name; + + const idx = normalizedName.indexOf('?'); + + if (idx >= 0) { + normalizedName = normalizedName.substr(0, idx); + } + + const isImmutable = /\[([^:\]]+:)?(hash|contenthash)(:[^\]]+)?]/gi.test( + normalizedName + ); + + if (isImmutable === true) { + assetInfo.immutable = true; + } + } + + this.emitFile(outputPath, content, null, assetInfo); } const esModule = diff --git a/test/name-option.test.js b/test/name-option.test.js index b42eef5..f842e38 100644 --- a/test/name-option.test.js +++ b/test/name-option.test.js @@ -90,7 +90,7 @@ describe('"name" option', () => { const stats = await compile(compiler); for (const [name, info] of stats.compilation.assetsInfo) { - if (name.endsWith('png')) { + if (name.endsWith('.png')) { expect(info.immutable).toBe(true); } } @@ -105,7 +105,7 @@ describe('"name" option', () => { const stats = await compile(compiler); for (const [name, info] of stats.compilation.assetsInfo) { - if (name.endsWith('png')) { + if (name.endsWith('.png')) { expect(info.immutable).toBe(true); } } @@ -120,13 +120,29 @@ describe('"name" option', () => { const stats = await compile(compiler); for (const [name, info] of stats.compilation.assetsInfo) { - if (name.endsWith('png')) { + if (name.startsWith('file.39f5c21c1aee6ff21844c6e1d8251d97.asset.png')) { expect(info.immutable).toBe(true); } } }); - it('should not mark unhashed asset as immutable', async () => { + it('should work and emit "immutable" for hashed assets #3', async () => { + expect.assertions(1); + + const compiler = getCompiler('simple.js', { + name: '[name].asset.[ext]?foo=[contenthash]', + }); + const stats = await compile(compiler); + + for (const [name, info] of stats.compilation.assetsInfo) { + if (name.startsWith('file.asset.png')) { + // eslint-disable-next-line no-undefined + expect(info.immutable).toBe(undefined); + } + } + }); + + it('should work and not emit "immutable" for not hashed assets', async () => { expect.assertions(1); const compiler = getCompiler('simple.js', { @@ -135,8 +151,9 @@ describe('"name" option', () => { const stats = await compile(compiler); for (const [name, info] of stats.compilation.assetsInfo) { - if (name.endsWith('png')) { - expect(info.immutable).toBe(false); + if (name.startsWith('asset.png')) { + // eslint-disable-next-line no-undefined + expect(info.immutable).toBe(undefined); } } });