-
-
Notifications
You must be signed in to change notification settings - Fork 282
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: persistent cache between runs (webpack@5 only) #541
Conversation
Codecov Report
@@ Coverage Diff @@
## master #541 +/- ##
==========================================
- Coverage 97.72% 95.68% -2.05%
==========================================
Files 3 3
Lines 220 255 +35
Branches 73 86 +13
==========================================
+ Hits 215 244 +29
- Misses 5 11 +6
Continue to review full report at Codecov.
|
src/index.js
Outdated
[], | ||
[], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can pass undefined
here, that saves a bit memory.
src/index.js
Outdated
try { | ||
snapshot = await CopyPlugin.createSnapshot( | ||
compilation, | ||
file.absoluteFrom | ||
); | ||
} catch (error) { | ||
compilation.errors.push(error); | ||
|
||
return; | ||
} | ||
return; | ||
} | ||
|
||
if (snapshot) { | ||
let isValidSnapshot; | ||
|
||
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 | ||
try { | ||
isValidSnapshot = await CopyPlugin.checkSnapshotValid( | ||
compilation, | ||
snapshot | ||
); | ||
} else { | ||
defaultCacheKeys = { | ||
...defaultCacheKeys, | ||
...pattern.cacheTransform.keys, | ||
}; | ||
} catch (error) { | ||
compilation.errors.push(error); | ||
|
||
return; | ||
} | ||
|
||
const cacheKeys = serialize(defaultCacheKeys); | ||
itemCache = cache.getItemCache(file.relativeFrom, null); | ||
|
||
try { | ||
const result = await cacache.get(cacheDirectory, cacheKeys); | ||
if (isValidSnapshot) { | ||
try { | ||
source = await itemCache.getPromise(); | ||
} catch (error) { | ||
compilation.errors.push(error); | ||
|
||
logger.debug( | ||
`getting cached transformation for "${file.absoluteFrom}"` | ||
); | ||
return; | ||
} | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
checkSnapshotValid
on a fresh created snapshot will always be true. You need to call checkSnapshotValid
on a snapshot that was created in the last run of webpack. The snapshot need to be stored and restored in and from the cache.
Here is some pseudo code:
// 1. check cache first, validate snapshot in cache entry
cacheEntry = await cache.getPromise(file.relativeFrom, null);
if (cacheEntry !== undefined) {
const { snapshot, source } = cacheEntry;
if (await checkSnapshotValid(snapshot)) {
// return early when cache entry can be used
return source;
}
}
// 2. create a new snapshot
const snapshot = await createSnapshot(file.relativeFrom);
// 3. create new data
const source = await createNewSource(file.relativeFrom);
// 4. store both in cache
await cache.storePromise(file.relativeFrom, null, { source, snapshot });
// 5. return new data
return source;
You are in the good position that you can call 2. before 3. Usually that's not possible, because dependencies are not known before execution. In that case one would do this:
// 2a.
const startTime = Date.now();
// 2b. create new data
const source = await createNewSource(file.relativeFrom);
// 3. create a new snapshot
const snapshot = await createSnapshot(file.relativeFrom, startTime);
} | ||
|
||
// eslint-disable-next-line consistent-return | ||
return new Promise((resolve, reject) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://nodejs.org/api/util.html#util_util_promisify_original
const checkSnapshotValid = util.promisify((compilation, snapshot, callback) =>
compilation.fileSystemInfo.checkSnapshotValid(snapshot, callback)
);
const createSnapshot = util.promisify((compilation, dependency, callback) =>
compilation.fileSystemInfo.createSnapshot(Date.now(), [dependency], undefined, undefined, null, callback)
);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Passing an undefined
startTime, would assume worse case.
This PR contains a:
Motivation / Use-Case
fixes #504
Breaking Changes
No
Additional Info
only webpack@5