diff --git a/src/index.js b/src/index.js index 3bbf4bb..231b029 100644 --- a/src/index.js +++ b/src/index.js @@ -2,6 +2,7 @@ import path from 'path' import SingleEntryPlugin from 'webpack/lib/SingleEntryPlugin' +import createHash from 'webpack/lib/util/createHash' import minimatch from 'minimatch' function validatePaths(assets, options) { @@ -24,6 +25,18 @@ function validatePaths(assets, options) { }) } +function hash(source, outputOptions) { + const hashFunction = outputOptions.hashFunction + const hashDigest = outputOptions.hashDigest + const hashDigestLength = outputOptions.hashDigestLength + const hash = createHash(hashFunction) + if (outputOptions.hashSalt) { + hash.update(outputOptions.hashSalt) + } + hash.update(source) + return hash.digest(hashDigest).substr(0, hashDigestLength) +} + const COMPILER_NAME = 'serviceworker-plugin' export default class ServiceWorkerPlugin { @@ -176,8 +189,11 @@ export default class ServiceWorkerPlugin { assets = validatePaths(assets, this.options) + const assetsHash = hash(JSON.stringify(assets), compilation.options.output) + const serviceWorkerOption = this.options.transformOptions({ assets, + assetsHash, jsonStats, }) diff --git a/src/index.spec.js b/src/index.spec.js index b0477d4..97e4173 100644 --- a/src/index.spec.js +++ b/src/index.spec.js @@ -14,6 +14,13 @@ function trim(str) { const filename = 'sw.js' const webpackOutputPath = path.resolve('./tmp-build') +const outputOptions = { + path: webpackOutputPath, + // these are the defaults from https://github.com/webpack/webpack/blob/master/lib/WebpackOptionsDefaulter.js#L164 + hashFunction: 'md4', + hashDigest: 'hex', + hashDigestLength: 20, +} const makeWebpackConfig = options => ({ entry: path.join(__dirname, '../test/test-build-entry'), mode: 'development', @@ -29,10 +36,9 @@ const makeWebpackConfig = options => ({ 'serviceworker-webpack-plugin/lib/runtime': path.join(__dirname, 'runtime.js'), }, }, - output: { - path: webpackOutputPath, - }, + output: outputOptions, }) +const fakeOptions = { output: outputOptions } describe('ServiceWorkerPlugin', () => { beforeEach(done => { @@ -96,6 +102,7 @@ describe('ServiceWorkerPlugin', () => { }) const compilation = { + options: fakeOptions, assets: { [filename]: { source: () => '', @@ -140,6 +147,7 @@ var serviceWorkerOption = { }) const compilation = { + options: fakeOptions, assets: { [filename]: { source: () => '', @@ -170,7 +178,73 @@ var serviceWorkerOption = { ) } ) - }) + }), + it('should get passed assetsHash', done => { + const transformOptions = serviceWorkerOption => { + expect(serviceWorkerOption) + .to.have.property('assetsHash') + .that.is.equal('bd90271e0847dcc66adb') + } + + const serviceWorkerPlugin = new ServiceWorkerPlugin({ + filename, + transformOptions, + }) + + const compilation = { + options: fakeOptions, + assets: { + [filename]: { + source: () => '', + }, + 'bar-v1.js': {}, + }, + getStats: () => ({ + toJson: () => ({}), + }), + } + + return serviceWorkerPlugin.handleEmit( + compilation, + { + options: {}, + }, + done + ) + }), + it('should change assetsHash when filename changes', done => { + const transformOptions = serviceWorkerOption => { + expect(serviceWorkerOption) + .to.have.property('assetsHash') + .that.is.equal('47633aad38a6adaca6ec') + } + + const serviceWorkerPlugin = new ServiceWorkerPlugin({ + filename, + transformOptions, + }) + + const compilation = { + options: fakeOptions, + assets: { + [filename]: { + source: () => '', + }, + 'bar-v2.js': {}, + }, + getStats: () => ({ + toJson: () => ({}), + }), + } + + return serviceWorkerPlugin.handleEmit( + compilation, + { + options: {}, + }, + done + ) + }) }) }) })