mirror of https://github.com/webpack/webpack.git
feat: add `snapshot.contextModule `to configure snapshots for context modules
This commit is contained in:
parent
076863133b
commit
d224b7b334
|
@ -2475,6 +2475,19 @@ export interface SnapshotOptions {
|
|||
*/
|
||||
timestamp?: boolean;
|
||||
};
|
||||
/**
|
||||
* Options for snapshotting the context module to determine if it needs to be built again.
|
||||
*/
|
||||
contextModule?: {
|
||||
/**
|
||||
* Use hashes of the content of the files/directories to determine invalidation.
|
||||
*/
|
||||
hash?: boolean;
|
||||
/**
|
||||
* Use timestamps of the files/directories to determine invalidation.
|
||||
*/
|
||||
timestamp?: boolean;
|
||||
};
|
||||
/**
|
||||
* List of paths that are managed by a package manager and contain a version or hash in its path so all files are immutable.
|
||||
*/
|
||||
|
|
|
@ -109,8 +109,6 @@ const makeSerializable = require("./util/makeSerializable");
|
|||
|
||||
/** @typedef {Record<ModuleId, FakeMapType>} FakeMap */
|
||||
|
||||
const SNAPSHOT_OPTIONS = { timestamp: true };
|
||||
|
||||
class ContextModule extends Module {
|
||||
/**
|
||||
* @param {ResolveDependencies} resolveDependencies function to get dependencies in this context
|
||||
|
@ -535,6 +533,8 @@ class ContextModule extends Module {
|
|||
}
|
||||
if (!this.context && !this.options.resource) return callback();
|
||||
|
||||
const snapshotOptions = compilation.options.snapshot.contextModule;
|
||||
|
||||
compilation.fileSystemInfo.createSnapshot(
|
||||
startTime,
|
||||
null,
|
||||
|
@ -544,7 +544,7 @@ class ContextModule extends Module {
|
|||
? [this.options.resource]
|
||||
: /** @type {string[]} */ (this.options.resource),
|
||||
null,
|
||||
SNAPSHOT_OPTIONS,
|
||||
snapshotOptions,
|
||||
(err, snapshot) => {
|
||||
if (err) return callback(err);
|
||||
/** @type {BuildInfo} */
|
||||
|
|
|
@ -694,6 +694,7 @@ const applySnapshotDefaults = (snapshot, { production, futureDefaults }) => {
|
|||
F(snapshot, "module", () =>
|
||||
production ? { timestamp: true, hash: true } : { timestamp: true }
|
||||
);
|
||||
F(snapshot, "contextModule", () => ({ timestamp: true }));
|
||||
F(snapshot, "resolve", () =>
|
||||
production ? { timestamp: true, hash: true } : { timestamp: true }
|
||||
);
|
||||
|
|
|
@ -457,6 +457,13 @@ const getNormalizedWebpackOptions = (config) => ({
|
|||
timestamp: module.timestamp,
|
||||
hash: module.hash
|
||||
})),
|
||||
contextModule: optionalNestedConfig(
|
||||
snapshot.contextModule,
|
||||
(contextModule) => ({
|
||||
timestamp: contextModule.timestamp,
|
||||
hash: contextModule.hash
|
||||
})
|
||||
),
|
||||
immutablePaths: optionalNestedArray(snapshot.immutablePaths, (p) => [...p]),
|
||||
managedPaths: optionalNestedArray(snapshot.managedPaths, (p) => [...p]),
|
||||
unmanagedPaths: optionalNestedArray(snapshot.unmanagedPaths, (p) => [...p])
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -5022,6 +5022,21 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"contextModule": {
|
||||
"description": "Options for snapshotting the context module to determine if it needs to be built again.",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"hash": {
|
||||
"description": "Use hashes of the content of the files/directories to determine invalidation.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"timestamp": {
|
||||
"description": "Use timestamps of the files/directories to determine invalidation.",
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
},
|
||||
"immutablePaths": {
|
||||
"description": "List of paths that are managed by a package manager and contain a version or hash in its path so all files are immutable.",
|
||||
"type": "array",
|
||||
|
|
|
@ -653,6 +653,9 @@ describe("snapshots", () => {
|
|||
"hash": true,
|
||||
"timestamp": true,
|
||||
},
|
||||
"contextModule": Object {
|
||||
"timestamp": true,
|
||||
},
|
||||
"immutablePaths": Array [],
|
||||
"managedPaths": Array [
|
||||
"<cwd>/node_modules/",
|
||||
|
|
|
@ -82,6 +82,16 @@ describe("Persistent Caching", () => {
|
|||
);
|
||||
});
|
||||
|
||||
const getCacheFileTimes = async () => {
|
||||
const cacheFiles = (await readdir(cachePath)).sort();
|
||||
return new Map(
|
||||
cacheFiles.map((f) => [
|
||||
f,
|
||||
fs.statSync(path.join(cachePath, f)).mtime.toString()
|
||||
])
|
||||
);
|
||||
};
|
||||
|
||||
const execute = () => {
|
||||
const cache = {};
|
||||
const require = (name) => {
|
||||
|
@ -230,11 +240,7 @@ sum([1,2,3])
|
|||
`
|
||||
});
|
||||
await compile({ entry: "./src/main.js" });
|
||||
const firstCacheFiles = (await readdir(cachePath)).sort();
|
||||
// cSpell:words Mtimes
|
||||
const firstMtimes = firstCacheFiles.map(
|
||||
(f) => fs.statSync(path.join(cachePath, f)).mtime
|
||||
);
|
||||
const firstCacheFileTimes = await getCacheFileTimes();
|
||||
|
||||
await updateSrc({
|
||||
"main.js": `
|
||||
|
@ -248,11 +254,29 @@ import 'lodash';
|
|||
readonly: true
|
||||
}
|
||||
});
|
||||
const cacheFiles = (await readdir(cachePath)).sort();
|
||||
expect(cacheFiles).toStrictEqual(firstCacheFiles);
|
||||
expect(
|
||||
firstCacheFiles.map((f) => fs.statSync(path.join(cachePath, f)).mtime)
|
||||
// cSpell:words Mtimes
|
||||
).toStrictEqual(firstMtimes);
|
||||
await expect(getCacheFileTimes()).resolves.toEqual(firstCacheFileTimes);
|
||||
}, 20000);
|
||||
|
||||
it("should not invalidate cache files if timestamps changed with dynamic import()", async () => {
|
||||
const configAdditions = {
|
||||
entry: "./src/main.js",
|
||||
snapshot: {
|
||||
resolve: { hash: true },
|
||||
module: { hash: true },
|
||||
contextModule: { hash: true }
|
||||
}
|
||||
};
|
||||
await updateSrc({
|
||||
"newer.js": "export default 2;",
|
||||
// eslint-disable-next-line no-template-curly-in-string
|
||||
"main.js": 'const f = "newer.js"; import(`./${f}`);'
|
||||
});
|
||||
await compile(configAdditions);
|
||||
const firstCacheFileTimes = await getCacheFileTimes();
|
||||
|
||||
await utimes(path.resolve(srcPath, "newer.js"), new Date(), new Date());
|
||||
|
||||
await compile(configAdditions);
|
||||
await expect(getCacheFileTimes()).resolves.toEqual(firstCacheFileTimes);
|
||||
}, 20000);
|
||||
});
|
||||
|
|
|
@ -8830,6 +8830,32 @@ Object {
|
|||
"multiple": false,
|
||||
"simpleType": "boolean",
|
||||
},
|
||||
"snapshot-context-module-hash": Object {
|
||||
"configs": Array [
|
||||
Object {
|
||||
"description": "Use hashes of the content of the files/directories to determine invalidation.",
|
||||
"multiple": false,
|
||||
"path": "snapshot.contextModule.hash",
|
||||
"type": "boolean",
|
||||
},
|
||||
],
|
||||
"description": "Use hashes of the content of the files/directories to determine invalidation.",
|
||||
"multiple": false,
|
||||
"simpleType": "boolean",
|
||||
},
|
||||
"snapshot-context-module-timestamp": Object {
|
||||
"configs": Array [
|
||||
Object {
|
||||
"description": "Use timestamps of the files/directories to determine invalidation.",
|
||||
"multiple": false,
|
||||
"path": "snapshot.contextModule.timestamp",
|
||||
"type": "boolean",
|
||||
},
|
||||
],
|
||||
"description": "Use timestamps of the files/directories to determine invalidation.",
|
||||
"multiple": false,
|
||||
"simpleType": "boolean",
|
||||
},
|
||||
"snapshot-immutable-paths": Object {
|
||||
"configs": Array [
|
||||
Object {
|
||||
|
|
|
@ -16170,6 +16170,20 @@ declare interface SnapshotOptionsWebpackOptions {
|
|||
timestamp?: boolean;
|
||||
};
|
||||
|
||||
/**
|
||||
* Options for snapshotting the context module to determine if it needs to be built again.
|
||||
*/
|
||||
contextModule?: {
|
||||
/**
|
||||
* Use hashes of the content of the files/directories to determine invalidation.
|
||||
*/
|
||||
hash?: boolean;
|
||||
/**
|
||||
* Use timestamps of the files/directories to determine invalidation.
|
||||
*/
|
||||
timestamp?: boolean;
|
||||
};
|
||||
|
||||
/**
|
||||
* List of paths that are managed by a package manager and contain a version or hash in its path so all files are immutable.
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue