From 3139c04a38351324bb277613266e29fe6612bb41 Mon Sep 17 00:00:00 2001 From: evilebottnawi Date: Wed, 21 Oct 2020 23:21:27 +0300 Subject: [PATCH 1/6] feat: persistent cache between runs (webpack@5 only) --- src/index.js | 196 +++++++++++++++------ test/CopyPlugin.test.js | 10 +- test/__snapshots__/CopyPlugin.test.js.snap | 77 -------- 3 files changed, 150 insertions(+), 133 deletions(-) diff --git a/src/index.js b/src/index.js index fb9e8aa9..d68ce849 100644 --- a/src/index.js +++ b/src/index.js @@ -37,8 +37,57 @@ class CopyPlugin { this.options = options.options || {}; } + static async createSnapshot(compilation, dependency) { + if (!compilation.fileSystemInfo) { + return; + } + + // eslint-disable-next-line consistent-return + return new Promise((resolve, reject) => { + compilation.fileSystemInfo.createSnapshot( + // eslint-disable-next-line no-undefined + undefined, + [dependency], + [], + [], + null, + (error, snapshot) => { + if (error) { + reject(error); + + return; + } + + resolve(snapshot); + } + ); + }); + } + + static async checkSnapshotValid(compilation, snapshot) { + if (!compilation.fileSystemInfo) { + return; + } + + // eslint-disable-next-line consistent-return + return new Promise((resolve, reject) => { + compilation.fileSystemInfo.checkSnapshotValid( + snapshot, + (error, isValid) => { + if (error) { + reject(error); + + return; + } + + resolve(isValid); + } + ); + }); + } + // eslint-disable-next-line class-methods-use-this - async runPattern(compiler, compilation, logger, inputPattern) { + static async runPattern(compiler, compilation, logger, cache, inputPattern) { const pattern = typeof inputPattern === 'string' ? { from: inputPattern } @@ -49,7 +98,6 @@ class CopyPlugin { pattern.to = path.normalize( typeof pattern.to !== 'undefined' ? pattern.to : '' ); - pattern.context = path.normalize( typeof pattern.context !== 'undefined' ? !path.isAbsolute(pattern.context) @@ -266,64 +314,98 @@ class CopyPlugin { compilation.fileDependencies.add(file.absoluteFrom); } - logger.debug(`reading "${file.absoluteFrom}" to write to assets`); + let itemCache; + let source; - let data; + // TODO logger + if (cache) { + const snapshot = await CopyPlugin.createSnapshot( + compilation, + file.absoluteFrom + ); + const isValidSnapshot = await CopyPlugin.checkSnapshotValid( + compilation, + snapshot + ); - try { - data = await readFile(inputFileSystem, file.absoluteFrom); - } catch (error) { - compilation.errors.push(error); + itemCache = cache.getItemCache(file.relativeFrom, null); - return; + if (isValidSnapshot) { + source = await itemCache.getPromise(); + } } - if (pattern.transform) { - logger.log(`transforming content for "${file.absoluteFrom}"`); - - if (pattern.cacheTransform) { - const cacheDirectory = pattern.cacheTransform.directory - ? pattern.cacheTransform.directory - : typeof pattern.cacheTransform === 'string' - ? pattern.cacheTransform - : findCacheDir({ name: 'copy-webpack-plugin' }) || os.tmpdir(); - let defaultCacheKeys = { - version, - transform: pattern.transform, - contentHash: crypto.createHash('md4').update(data).digest('hex'), - }; - - if (typeof pattern.cacheTransform.keys === 'function') { - defaultCacheKeys = await pattern.cacheTransform.keys( - defaultCacheKeys, - file.absoluteFrom - ); - } else { - defaultCacheKeys = { - ...defaultCacheKeys, - ...pattern.cacheTransform.keys, + if (!source) { + logger.debug(`reading "${file.absoluteFrom}" to write to assets`); + + let data; + + try { + data = await readFile(inputFileSystem, file.absoluteFrom); + } catch (error) { + compilation.errors.push(error); + + return; + } + + if (pattern.transform) { + logger.log(`transforming content for "${file.absoluteFrom}"`); + + if (pattern.cacheTransform) { + const cacheDirectory = pattern.cacheTransform.directory + ? pattern.cacheTransform.directory + : typeof pattern.cacheTransform === 'string' + ? pattern.cacheTransform + : findCacheDir({ name: 'copy-webpack-plugin' }) || os.tmpdir(); + let defaultCacheKeys = { + version, + transform: pattern.transform, + contentHash: crypto + .createHash('md4') + .update(data) + .digest('hex'), }; - } - const cacheKeys = serialize(defaultCacheKeys); + if (typeof pattern.cacheTransform.keys === 'function') { + defaultCacheKeys = await pattern.cacheTransform.keys( + defaultCacheKeys, + file.absoluteFrom + ); + } else { + defaultCacheKeys = { + ...defaultCacheKeys, + ...pattern.cacheTransform.keys, + }; + } + + const cacheKeys = serialize(defaultCacheKeys); - try { - const result = await cacache.get(cacheDirectory, cacheKeys); + try { + const result = await cacache.get(cacheDirectory, cacheKeys); - logger.debug( - `getting cached transformation for "${file.absoluteFrom}"` - ); + logger.debug( + `getting cached transformation for "${file.absoluteFrom}"` + ); - ({ data } = result); - } catch (_ignoreError) { - data = await pattern.transform(data, file.absoluteFrom); + ({ data } = result); + } catch (_ignoreError) { + data = await pattern.transform(data, file.absoluteFrom); - logger.debug(`caching transformation for "${file.absoluteFrom}"`); + logger.debug( + `caching transformation for "${file.absoluteFrom}"` + ); - await cacache.put(cacheDirectory, cacheKeys, data); + await cacache.put(cacheDirectory, cacheKeys, data); + } + } else { + data = await pattern.transform(data, file.absoluteFrom); } - } else { - data = await pattern.transform(data, file.absoluteFrom); + } + + source = new RawSource(data); + + if (itemCache) { + await itemCache.storePromise(source); } } @@ -349,7 +431,7 @@ class CopyPlugin { { resourcePath: file.absoluteFrom }, file.webpackTo, { - content: data, + content: source.source(), context: pattern.context, } ); @@ -374,7 +456,7 @@ class CopyPlugin { } // eslint-disable-next-line no-param-reassign - file.data = data; + file.source = source; // eslint-disable-next-line no-param-reassign file.targetPath = normalizePath(file.webpackTo); // eslint-disable-next-line no-param-reassign @@ -392,6 +474,10 @@ class CopyPlugin { compiler.hooks.thisCompilation.tap(pluginName, (compilation) => { const logger = compilation.getLogger('copy-webpack-plugin'); + // eslint-disable-next-line no-undefined + const cache = compilation.getCache + ? compilation.getCache('CopyWebpackPlugin') + : undefined; compilation.hooks.additionalAssets.tapAsync( 'copy-webpack-plugin', @@ -404,7 +490,13 @@ class CopyPlugin { assets = await Promise.all( this.patterns.map((item) => limit(async () => - this.runPattern(compiler, compilation, logger, item) + CopyPlugin.runPattern( + compiler, + compilation, + logger, + cache, + item + ) ) ) ); @@ -426,12 +518,10 @@ class CopyPlugin { absoluteFrom, targetPath, webpackTo, - data, + source, force, } = asset; - const source = new RawSource(data); - // For old version webpack 4 /* istanbul ignore if */ if (typeof compilation.emitAsset !== 'function') { diff --git a/test/CopyPlugin.test.js b/test/CopyPlugin.test.js index f7273a7c..35448650 100644 --- a/test/CopyPlugin.test.js +++ b/test/CopyPlugin.test.js @@ -634,8 +634,12 @@ describe('CopyPlugin', () => { .catch(done); }); - it('should work and do not emit unchanged assets', async () => { - const compiler = getCompiler(); + it.only('should work and do not emit unchanged assets', async () => { + const compiler = getCompiler({ + cache: { + type: 'memory', + }, + }); new CopyPlugin({ patterns: [ @@ -671,7 +675,7 @@ describe('CopyPlugin', () => { ).length ).toBe(4); } else { - expect(newStats.compilation.emittedAssets.size).toBe(4); + expect(newStats.compilation.emittedAssets.size).toBe(0); } expect(readAssets(compiler, newStats)).toMatchSnapshot('assets'); diff --git a/test/__snapshots__/CopyPlugin.test.js.snap b/test/__snapshots__/CopyPlugin.test.js.snap index 4c768dc6..c2944517 100644 --- a/test/__snapshots__/CopyPlugin.test.js.snap +++ b/test/__snapshots__/CopyPlugin.test.js.snap @@ -1,82 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`CopyPlugin logging should logging when "from" is a directory: logs 1`] = ` -Object { - "logs": Array [ - "add \\"./fixtures/directory\\" as a context dependency", - "begin globbing \\"./fixtures/directory/**/*\\" with a context of \\"./fixtures/directory\\"", - "determined \\"./fixtures/directory\\" is a directory", - "determined that \\"./fixtures/directory/.dottedfile\\" should write to \\".dottedfile\\"", - "determined that \\"./fixtures/directory/directoryfile.txt\\" should write to \\"directoryfile.txt\\"", - "determined that \\"./fixtures/directory/nested/deep-nested/deepnested.txt\\" should write to \\"nested/deep-nested/deepnested.txt\\"", - "determined that \\"./fixtures/directory/nested/nestedfile.txt\\" should write to \\"nested/nestedfile.txt\\"", - "end to adding additional assets", - "found \\"./fixtures/directory/.dottedfile\\"", - "found \\"./fixtures/directory/directoryfile.txt\\"", - "found \\"./fixtures/directory/nested/deep-nested/deepnested.txt\\"", - "found \\"./fixtures/directory/nested/nestedfile.txt\\"", - "getting stats for \\"./fixtures/directory\\" to determinate \\"fromType\\"", - "processing from \\"directory\\" to \\".\\"", - "reading \\"./fixtures/directory/.dottedfile\\" to write to assets", - "reading \\"./fixtures/directory/directoryfile.txt\\" to write to assets", - "reading \\"./fixtures/directory/nested/deep-nested/deepnested.txt\\" to write to assets", - "reading \\"./fixtures/directory/nested/nestedfile.txt\\" to write to assets", - "start to adding additional assets", - "writing \\".dottedfile\\" to compilation assets from \\"./fixtures/directory/.dottedfile\\"", - "writing \\"directoryfile.txt\\" to compilation assets from \\"./fixtures/directory/directoryfile.txt\\"", - "writing \\"nested/deep-nested/deepnested.txt\\" to compilation assets from \\"./fixtures/directory/nested/deep-nested/deepnested.txt\\"", - "writing \\"nested/nestedfile.txt\\" to compilation assets from \\"./fixtures/directory/nested/nestedfile.txt\\"", - ], -} -`; - -exports[`CopyPlugin logging should logging when "from" is a file: logs 1`] = ` -Object { - "logs": Array [ - "add \\"./fixtures/file.txt\\" as a file dependency", - "begin globbing \\"./fixtures/file.txt\\" with a context of \\"./fixtures\\"", - "determined \\"./fixtures/file.txt\\" is a file", - "determined that \\"./fixtures/file.txt\\" should write to \\"file.txt\\"", - "end to adding additional assets", - "found \\"./fixtures/file.txt\\"", - "getting stats for \\"./fixtures/file.txt\\" to determinate \\"fromType\\"", - "processing from \\"file.txt\\" to \\".\\"", - "reading \\"./fixtures/file.txt\\" to write to assets", - "start to adding additional assets", - "writing \\"file.txt\\" to compilation assets from \\"./fixtures/file.txt\\"", - ], -} -`; - -exports[`CopyPlugin logging should logging when "from" is a glob: logs 1`] = ` -Object { - "logs": Array [ - "add \\"./fixtures/directory\\" as a context dependency", - "add ./fixtures/directory/directoryfile.txt as fileDependencies", - "add ./fixtures/directory/nested/deep-nested/deepnested.txt as fileDependencies", - "add ./fixtures/directory/nested/nestedfile.txt as fileDependencies", - "begin globbing \\"./fixtures/directory/**\\" with a context of \\"./fixtures\\"", - "determined \\"./fixtures/directory/**\\" is a glob", - "determined that \\"./fixtures/directory/directoryfile.txt\\" should write to \\"directory/directoryfile.txt\\"", - "determined that \\"./fixtures/directory/nested/deep-nested/deepnested.txt\\" should write to \\"directory/nested/deep-nested/deepnested.txt\\"", - "determined that \\"./fixtures/directory/nested/nestedfile.txt\\" should write to \\"directory/nested/nestedfile.txt\\"", - "end to adding additional assets", - "found \\"./fixtures/directory/directoryfile.txt\\"", - "found \\"./fixtures/directory/nested/deep-nested/deepnested.txt\\"", - "found \\"./fixtures/directory/nested/nestedfile.txt\\"", - "getting stats for \\"./fixtures/directory/**\\" to determinate \\"fromType\\"", - "processing from \\"directory/**\\" to \\".\\"", - "reading \\"./fixtures/directory/directoryfile.txt\\" to write to assets", - "reading \\"./fixtures/directory/nested/deep-nested/deepnested.txt\\" to write to assets", - "reading \\"./fixtures/directory/nested/nestedfile.txt\\" to write to assets", - "start to adding additional assets", - "writing \\"directory/directoryfile.txt\\" to compilation assets from \\"./fixtures/directory/directoryfile.txt\\"", - "writing \\"directory/nested/deep-nested/deepnested.txt\\" to compilation assets from \\"./fixtures/directory/nested/deep-nested/deepnested.txt\\"", - "writing \\"directory/nested/nestedfile.txt\\" to compilation assets from \\"./fixtures/directory/nested/nestedfile.txt\\"", - ], -} -`; - exports[`CopyPlugin watch mode should work and do not emit unchanged assets: assets 1`] = ` Object { ".dottedfile": "dottedfile contents From 74874583ca851b84c5cf60a19f3832836f7eaca6 Mon Sep 17 00:00:00 2001 From: evilebottnawi Date: Wed, 21 Oct 2020 23:27:01 +0300 Subject: [PATCH 2/6] test: fix --- test/CopyPlugin.test.js | 2 +- test/__snapshots__/CopyPlugin.test.js.snap | 77 ++++++++++++++++++++++ 2 files changed, 78 insertions(+), 1 deletion(-) diff --git a/test/CopyPlugin.test.js b/test/CopyPlugin.test.js index 35448650..8d83c995 100644 --- a/test/CopyPlugin.test.js +++ b/test/CopyPlugin.test.js @@ -634,7 +634,7 @@ describe('CopyPlugin', () => { .catch(done); }); - it.only('should work and do not emit unchanged assets', async () => { + it('should work and do not emit unchanged assets', async () => { const compiler = getCompiler({ cache: { type: 'memory', diff --git a/test/__snapshots__/CopyPlugin.test.js.snap b/test/__snapshots__/CopyPlugin.test.js.snap index c2944517..4c768dc6 100644 --- a/test/__snapshots__/CopyPlugin.test.js.snap +++ b/test/__snapshots__/CopyPlugin.test.js.snap @@ -1,5 +1,82 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`CopyPlugin logging should logging when "from" is a directory: logs 1`] = ` +Object { + "logs": Array [ + "add \\"./fixtures/directory\\" as a context dependency", + "begin globbing \\"./fixtures/directory/**/*\\" with a context of \\"./fixtures/directory\\"", + "determined \\"./fixtures/directory\\" is a directory", + "determined that \\"./fixtures/directory/.dottedfile\\" should write to \\".dottedfile\\"", + "determined that \\"./fixtures/directory/directoryfile.txt\\" should write to \\"directoryfile.txt\\"", + "determined that \\"./fixtures/directory/nested/deep-nested/deepnested.txt\\" should write to \\"nested/deep-nested/deepnested.txt\\"", + "determined that \\"./fixtures/directory/nested/nestedfile.txt\\" should write to \\"nested/nestedfile.txt\\"", + "end to adding additional assets", + "found \\"./fixtures/directory/.dottedfile\\"", + "found \\"./fixtures/directory/directoryfile.txt\\"", + "found \\"./fixtures/directory/nested/deep-nested/deepnested.txt\\"", + "found \\"./fixtures/directory/nested/nestedfile.txt\\"", + "getting stats for \\"./fixtures/directory\\" to determinate \\"fromType\\"", + "processing from \\"directory\\" to \\".\\"", + "reading \\"./fixtures/directory/.dottedfile\\" to write to assets", + "reading \\"./fixtures/directory/directoryfile.txt\\" to write to assets", + "reading \\"./fixtures/directory/nested/deep-nested/deepnested.txt\\" to write to assets", + "reading \\"./fixtures/directory/nested/nestedfile.txt\\" to write to assets", + "start to adding additional assets", + "writing \\".dottedfile\\" to compilation assets from \\"./fixtures/directory/.dottedfile\\"", + "writing \\"directoryfile.txt\\" to compilation assets from \\"./fixtures/directory/directoryfile.txt\\"", + "writing \\"nested/deep-nested/deepnested.txt\\" to compilation assets from \\"./fixtures/directory/nested/deep-nested/deepnested.txt\\"", + "writing \\"nested/nestedfile.txt\\" to compilation assets from \\"./fixtures/directory/nested/nestedfile.txt\\"", + ], +} +`; + +exports[`CopyPlugin logging should logging when "from" is a file: logs 1`] = ` +Object { + "logs": Array [ + "add \\"./fixtures/file.txt\\" as a file dependency", + "begin globbing \\"./fixtures/file.txt\\" with a context of \\"./fixtures\\"", + "determined \\"./fixtures/file.txt\\" is a file", + "determined that \\"./fixtures/file.txt\\" should write to \\"file.txt\\"", + "end to adding additional assets", + "found \\"./fixtures/file.txt\\"", + "getting stats for \\"./fixtures/file.txt\\" to determinate \\"fromType\\"", + "processing from \\"file.txt\\" to \\".\\"", + "reading \\"./fixtures/file.txt\\" to write to assets", + "start to adding additional assets", + "writing \\"file.txt\\" to compilation assets from \\"./fixtures/file.txt\\"", + ], +} +`; + +exports[`CopyPlugin logging should logging when "from" is a glob: logs 1`] = ` +Object { + "logs": Array [ + "add \\"./fixtures/directory\\" as a context dependency", + "add ./fixtures/directory/directoryfile.txt as fileDependencies", + "add ./fixtures/directory/nested/deep-nested/deepnested.txt as fileDependencies", + "add ./fixtures/directory/nested/nestedfile.txt as fileDependencies", + "begin globbing \\"./fixtures/directory/**\\" with a context of \\"./fixtures\\"", + "determined \\"./fixtures/directory/**\\" is a glob", + "determined that \\"./fixtures/directory/directoryfile.txt\\" should write to \\"directory/directoryfile.txt\\"", + "determined that \\"./fixtures/directory/nested/deep-nested/deepnested.txt\\" should write to \\"directory/nested/deep-nested/deepnested.txt\\"", + "determined that \\"./fixtures/directory/nested/nestedfile.txt\\" should write to \\"directory/nested/nestedfile.txt\\"", + "end to adding additional assets", + "found \\"./fixtures/directory/directoryfile.txt\\"", + "found \\"./fixtures/directory/nested/deep-nested/deepnested.txt\\"", + "found \\"./fixtures/directory/nested/nestedfile.txt\\"", + "getting stats for \\"./fixtures/directory/**\\" to determinate \\"fromType\\"", + "processing from \\"directory/**\\" to \\".\\"", + "reading \\"./fixtures/directory/directoryfile.txt\\" to write to assets", + "reading \\"./fixtures/directory/nested/deep-nested/deepnested.txt\\" to write to assets", + "reading \\"./fixtures/directory/nested/nestedfile.txt\\" to write to assets", + "start to adding additional assets", + "writing \\"directory/directoryfile.txt\\" to compilation assets from \\"./fixtures/directory/directoryfile.txt\\"", + "writing \\"directory/nested/deep-nested/deepnested.txt\\" to compilation assets from \\"./fixtures/directory/nested/deep-nested/deepnested.txt\\"", + "writing \\"directory/nested/nestedfile.txt\\" to compilation assets from \\"./fixtures/directory/nested/nestedfile.txt\\"", + ], +} +`; + exports[`CopyPlugin watch mode should work and do not emit unchanged assets: assets 1`] = ` Object { ".dottedfile": "dottedfile contents From d7bff393430df19bea434813790acdaae710537b Mon Sep 17 00:00:00 2001 From: evilebottnawi Date: Wed, 21 Oct 2020 23:38:54 +0300 Subject: [PATCH 3/6] test: fix --- .gitignore | 1 + test/CopyPlugin.test.js | 62 +++++++++++++++- test/__snapshots__/CopyPlugin.test.js.snap | 84 ++++++++++++++-------- 3 files changed, 118 insertions(+), 29 deletions(-) diff --git a/.gitignore b/.gitignore index 3162bc45..82f19b2c 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,7 @@ npm-debug.log* /reports /node_modules /test/fixtures/\[special\$directory\] +/test/outputs .DS_Store Thumbs.db diff --git a/test/CopyPlugin.test.js b/test/CopyPlugin.test.js index 8d83c995..898f0607 100644 --- a/test/CopyPlugin.test.js +++ b/test/CopyPlugin.test.js @@ -1,6 +1,7 @@ import path from 'path'; import webpack from 'webpack'; +import del from 'del'; import CopyPlugin from '../src'; @@ -633,8 +634,10 @@ describe('CopyPlugin', () => { .then(done) .catch(done); }); + }); - it('should work and do not emit unchanged assets', async () => { + describe('cache', () => { + it('should work with the "memory" cache', async () => { const compiler = getCompiler({ cache: { type: 'memory', @@ -685,6 +688,63 @@ describe('CopyPlugin', () => { resolve(); }); }); + + it('should work with the "filesystem" cache', async () => { + const cacheDirectory = path.resolve(__dirname, './outputs/.cache'); + + await del(cacheDirectory); + + const compiler = getCompiler({ + cache: { + type: 'filesystem', + cacheDirectory, + }, + }); + + new CopyPlugin({ + patterns: [ + { + from: path.resolve(__dirname, './fixtures/directory'), + }, + ], + }).apply(compiler); + + const { stats } = await compile(compiler); + + if (webpack.version[0] === '4') { + expect( + Object.keys(stats.compilation.assets).filter( + (assetName) => stats.compilation.assets[assetName].emitted + ).length + ).toBe(5); + } else { + expect(stats.compilation.emittedAssets.size).toBe(5); + } + + expect(readAssets(compiler, stats)).toMatchSnapshot('assets'); + expect(stats.compilation.errors).toMatchSnapshot('errors'); + expect(stats.compilation.warnings).toMatchSnapshot('warnings'); + + await new Promise(async (resolve) => { + const { stats: newStats } = await compile(compiler); + + if (webpack.version[0] === '4') { + expect( + Object.keys(newStats.compilation.assets).filter( + (assetName) => newStats.compilation.assets[assetName].emitted + ).length + ).toBe(4); + } else { + expect(newStats.compilation.emittedAssets.size).toBe(0); + } + + expect(readAssets(compiler, newStats)).toMatchSnapshot('assets'); + expect(newStats.compilation.errors).toMatchSnapshot('errors'); + expect(newStats.compilation.warnings).toMatchSnapshot('warnings'); + + resolve(); + }); + }); }); describe('logging', () => { diff --git a/test/__snapshots__/CopyPlugin.test.js.snap b/test/__snapshots__/CopyPlugin.test.js.snap index 4c768dc6..9f77923e 100644 --- a/test/__snapshots__/CopyPlugin.test.js.snap +++ b/test/__snapshots__/CopyPlugin.test.js.snap @@ -1,5 +1,61 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`CopyPlugin cache should work with the "filesystem" cache: assets 1`] = ` +Object { + ".dottedfile": "dottedfile contents +", + "directoryfile.txt": "new", + "nested/deep-nested/deepnested.txt": "", + "nested/nestedfile.txt": "", +} +`; + +exports[`CopyPlugin cache should work with the "filesystem" cache: assets 2`] = ` +Object { + ".dottedfile": "dottedfile contents +", + "directoryfile.txt": "new", + "nested/deep-nested/deepnested.txt": "", + "nested/nestedfile.txt": "", +} +`; + +exports[`CopyPlugin cache should work with the "filesystem" cache: errors 1`] = `Array []`; + +exports[`CopyPlugin cache should work with the "filesystem" cache: errors 2`] = `Array []`; + +exports[`CopyPlugin cache should work with the "filesystem" cache: warnings 1`] = `Array []`; + +exports[`CopyPlugin cache should work with the "filesystem" cache: warnings 2`] = `Array []`; + +exports[`CopyPlugin cache should work with the "memory" cache: assets 1`] = ` +Object { + ".dottedfile": "dottedfile contents +", + "directoryfile.txt": "new", + "nested/deep-nested/deepnested.txt": "", + "nested/nestedfile.txt": "", +} +`; + +exports[`CopyPlugin cache should work with the "memory" cache: assets 2`] = ` +Object { + ".dottedfile": "dottedfile contents +", + "directoryfile.txt": "new", + "nested/deep-nested/deepnested.txt": "", + "nested/nestedfile.txt": "", +} +`; + +exports[`CopyPlugin cache should work with the "memory" cache: errors 1`] = `Array []`; + +exports[`CopyPlugin cache should work with the "memory" cache: errors 2`] = `Array []`; + +exports[`CopyPlugin cache should work with the "memory" cache: warnings 1`] = `Array []`; + +exports[`CopyPlugin cache should work with the "memory" cache: warnings 2`] = `Array []`; + exports[`CopyPlugin logging should logging when "from" is a directory: logs 1`] = ` Object { "logs": Array [ @@ -76,31 +132,3 @@ Object { ], } `; - -exports[`CopyPlugin watch mode should work and do not emit unchanged assets: assets 1`] = ` -Object { - ".dottedfile": "dottedfile contents -", - "directoryfile.txt": "new", - "nested/deep-nested/deepnested.txt": "", - "nested/nestedfile.txt": "", -} -`; - -exports[`CopyPlugin watch mode should work and do not emit unchanged assets: assets 2`] = ` -Object { - ".dottedfile": "dottedfile contents -", - "directoryfile.txt": "new", - "nested/deep-nested/deepnested.txt": "", - "nested/nestedfile.txt": "", -} -`; - -exports[`CopyPlugin watch mode should work and do not emit unchanged assets: errors 1`] = `Array []`; - -exports[`CopyPlugin watch mode should work and do not emit unchanged assets: errors 2`] = `Array []`; - -exports[`CopyPlugin watch mode should work and do not emit unchanged assets: warnings 1`] = `Array []`; - -exports[`CopyPlugin watch mode should work and do not emit unchanged assets: warnings 2`] = `Array []`; From 9a1164324cc2d878b603c8f687dab391901b3ca8 Mon Sep 17 00:00:00 2001 From: evilebottnawi Date: Wed, 21 Oct 2020 23:52:26 +0300 Subject: [PATCH 4/6] refactor: code --- src/index.js | 55 ++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 43 insertions(+), 12 deletions(-) diff --git a/src/index.js b/src/index.js index d68ce849..44cf23b7 100644 --- a/src/index.js +++ b/src/index.js @@ -319,19 +319,44 @@ class CopyPlugin { // TODO logger if (cache) { - const snapshot = await CopyPlugin.createSnapshot( - compilation, - file.absoluteFrom - ); - const isValidSnapshot = await CopyPlugin.checkSnapshotValid( - compilation, - snapshot - ); + let snapshot; - itemCache = cache.getItemCache(file.relativeFrom, null); + try { + snapshot = await CopyPlugin.createSnapshot( + compilation, + file.absoluteFrom + ); + } catch (error) { + compilation.errors.push(error); - if (isValidSnapshot) { - source = await itemCache.getPromise(); + return; + } + + if (snapshot) { + let isValidSnapshot; + + try { + isValidSnapshot = await CopyPlugin.checkSnapshotValid( + compilation, + snapshot + ); + } catch (error) { + compilation.errors.push(error); + + return; + } + + itemCache = cache.getItemCache(file.relativeFrom, null); + + if (isValidSnapshot) { + try { + source = await itemCache.getPromise(); + } catch (error) { + compilation.errors.push(error); + + return; + } + } } } @@ -405,7 +430,13 @@ class CopyPlugin { source = new RawSource(data); if (itemCache) { - await itemCache.storePromise(source); + try { + await itemCache.storePromise(source); + } catch (error) { + compilation.errors.push(error); + + return; + } } } From 24778373beb3233109f8e0f6d502a403dd4fa999 Mon Sep 17 00:00:00 2001 From: evilebottnawi Date: Thu, 22 Oct 2020 13:56:01 +0300 Subject: [PATCH 5/6] refactor: code --- src/index.js | 76 ++++++++++++++++++++-------------------------------- 1 file changed, 29 insertions(+), 47 deletions(-) diff --git a/src/index.js b/src/index.js index 44cf23b7..eb6f3d85 100644 --- a/src/index.js +++ b/src/index.js @@ -37,7 +37,7 @@ class CopyPlugin { this.options = options.options || {}; } - static async createSnapshot(compilation, dependency) { + static async createSnapshot(compilation, startTime, dependency) { if (!compilation.fileSystemInfo) { return; } @@ -45,11 +45,12 @@ class CopyPlugin { // eslint-disable-next-line consistent-return return new Promise((resolve, reject) => { compilation.fileSystemInfo.createSnapshot( + startTime, + [dependency], + // eslint-disable-next-line no-undefined + undefined, // eslint-disable-next-line no-undefined undefined, - [dependency], - [], - [], null, (error, snapshot) => { if (error) { @@ -314,53 +315,31 @@ class CopyPlugin { compilation.fileDependencies.add(file.absoluteFrom); } - let itemCache; let source; + let cacheEntry; - // TODO logger if (cache) { - let snapshot; + cacheEntry = await cache.getPromise(file.relativeFrom, null); - try { - snapshot = await CopyPlugin.createSnapshot( + if (cacheEntry) { + const isValidSnapshot = await CopyPlugin.checkSnapshotValid( compilation, - file.absoluteFrom + cacheEntry.snapshot ); - } catch (error) { - compilation.errors.push(error); - - return; - } - - if (snapshot) { - let isValidSnapshot; - - try { - isValidSnapshot = await CopyPlugin.checkSnapshotValid( - compilation, - snapshot - ); - } catch (error) { - compilation.errors.push(error); - - return; - } - - itemCache = cache.getItemCache(file.relativeFrom, null); if (isValidSnapshot) { - try { - source = await itemCache.getPromise(); - } catch (error) { - compilation.errors.push(error); - - return; - } + ({ source } = cacheEntry); } } } if (!source) { + let startTime; + + if (cache) { + startTime = Date.now(); + } + logger.debug(`reading "${file.absoluteFrom}" to write to assets`); let data; @@ -429,14 +408,17 @@ class CopyPlugin { source = new RawSource(data); - if (itemCache) { - try { - await itemCache.storePromise(source); - } catch (error) { - compilation.errors.push(error); + if (cache) { + const snapshot = await CopyPlugin.createSnapshot( + compilation, + startTime, + file.relativeFrom + ); - return; - } + await cache.storePromise(file.relativeFrom, null, { + source, + snapshot, + }); } } @@ -505,10 +487,10 @@ class CopyPlugin { compiler.hooks.thisCompilation.tap(pluginName, (compilation) => { const logger = compilation.getLogger('copy-webpack-plugin'); - // eslint-disable-next-line no-undefined const cache = compilation.getCache ? compilation.getCache('CopyWebpackPlugin') - : undefined; + : // eslint-disable-next-line no-undefined + undefined; compilation.hooks.additionalAssets.tapAsync( 'copy-webpack-plugin', From 4b294474b18eaf223e7d56ca0b83172f584f8c0b Mon Sep 17 00:00:00 2001 From: evilebottnawi Date: Thu, 22 Oct 2020 14:09:23 +0300 Subject: [PATCH 6/6] refactor: code --- src/index.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/index.js b/src/index.js index eb6f3d85..9ece267a 100644 --- a/src/index.js +++ b/src/index.js @@ -316,10 +316,9 @@ class CopyPlugin { } let source; - let cacheEntry; if (cache) { - cacheEntry = await cache.getPromise(file.relativeFrom, null); + const cacheEntry = await cache.getPromise(file.relativeFrom, null); if (cacheEntry) { const isValidSnapshot = await CopyPlugin.checkSnapshotValid(