From 96084cc0a1a845f16c603f056af567494160e869 Mon Sep 17 00:00:00 2001 From: jinrui Date: Thu, 2 Jan 2025 16:46:35 +0800 Subject: [PATCH] feat: support invalidate persistent cache using `config.mode` and `config.name` (#8920) * feat: support invalidate persistent cache using `mode` and `name` * test: add test case --- crates/node_binding/binding.d.ts | 1 + .../src/raw_options/mod.rs | 2 ++ .../rspack_core/src/cache/persistent/mod.rs | 10 +++++-- .../src/cache/persistent/version.rs | 4 +-- .../src/options/compiler_options.rs | 1 + .../src/options/compiler_options_builder.rs | 8 +++++ crates/rspack_core/src/options/mode.rs | 2 +- .../invalidation/config-mode/file.js | 7 +++++ .../invalidation/config-mode/index.js | 15 ++++++++++ .../invalidation/config-mode/rspack.config.js | 30 +++++++++++++++++++ .../invalidation/config-name/file.js | 7 +++++ .../invalidation/config-name/index.js | 15 ++++++++++ .../invalidation/config-name/rspack.config.js | 26 ++++++++++++++++ packages/rspack/src/config/adapter.ts | 1 + 14 files changed, 124 insertions(+), 5 deletions(-) create mode 100644 packages/rspack-test-tools/tests/cacheCases/invalidation/config-mode/file.js create mode 100644 packages/rspack-test-tools/tests/cacheCases/invalidation/config-mode/index.js create mode 100644 packages/rspack-test-tools/tests/cacheCases/invalidation/config-mode/rspack.config.js create mode 100644 packages/rspack-test-tools/tests/cacheCases/invalidation/config-name/file.js create mode 100644 packages/rspack-test-tools/tests/cacheCases/invalidation/config-name/index.js create mode 100644 packages/rspack-test-tools/tests/cacheCases/invalidation/config-name/rspack.config.js diff --git a/crates/node_binding/binding.d.ts b/crates/node_binding/binding.d.ts index 6dd61c6f44be..37ae507b5d08 100644 --- a/crates/node_binding/binding.d.ts +++ b/crates/node_binding/binding.d.ts @@ -1752,6 +1752,7 @@ export interface RawOptimizationOptions { } export interface RawOptions { + name?: string mode?: undefined | 'production' | 'development' | 'none' context: string output: RawOutputOptions diff --git a/crates/rspack_binding_values/src/raw_options/mod.rs b/crates/rspack_binding_values/src/raw_options/mod.rs index 8d761a3809bc..d03206e6de2c 100644 --- a/crates/rspack_binding_values/src/raw_options/mod.rs +++ b/crates/rspack_binding_values/src/raw_options/mod.rs @@ -41,6 +41,7 @@ pub use crate::raw_resolve::*; #[derive(Debug)] #[napi(object, object_to_js = false)] pub struct RawOptions { + pub name: Option, #[napi(ts_type = "undefined | 'production' | 'development' | 'none'")] pub mode: Option, pub context: String, @@ -80,6 +81,7 @@ impl TryFrom for CompilerOptions { let node = value.node.map(|n| n.into()); Ok(CompilerOptions { + name: value.name, context, mode, module, diff --git a/crates/rspack_core/src/cache/persistent/mod.rs b/crates/rspack_core/src/cache/persistent/mod.rs index af4bc0c94911..0f18c7e7e1ae 100644 --- a/crates/rspack_core/src/cache/persistent/mod.rs +++ b/crates/rspack_core/src/cache/persistent/mod.rs @@ -3,7 +3,7 @@ mod occasion; pub mod snapshot; pub mod storage; mod version; -use std::{path::PathBuf, sync::Arc}; +use std::{hash::Hash, path::PathBuf, sync::Arc}; pub use cacheable_context::{CacheableContext, FromContext}; use occasion::MakeOccasion; @@ -49,7 +49,13 @@ impl PersistentCache { let version = version::get_version( input_filesystem.clone(), &option.build_dependencies, - vec![compiler_path, &option.version, rspack_version!()], + |hasher| { + compiler_path.hash(hasher); + option.version.hash(hasher); + rspack_version!().hash(hasher); + compiler_options.name.hash(hasher); + compiler_options.mode.hash(hasher); + }, ); let storage = create_storage(option.storage.clone(), version, intermediate_filesystem); let context = Arc::new(CacheableContext { diff --git a/crates/rspack_core/src/cache/persistent/version.rs b/crates/rspack_core/src/cache/persistent/version.rs index acebdb731f31..072cd26e5f8c 100644 --- a/crates/rspack_core/src/cache/persistent/version.rs +++ b/crates/rspack_core/src/cache/persistent/version.rs @@ -8,7 +8,7 @@ use rspack_paths::AssertUtf8; pub fn get_version( fs: Arc, dependencies: &Vec, - salt: Vec<&str>, + add_salt: impl FnOnce(&mut DefaultHasher), ) -> String { let mut hasher = DefaultHasher::new(); for dep in dependencies { @@ -24,6 +24,6 @@ pub fn get_version( .unwrap_or_else(|_| panic!("Failed to read buildDependency({path}) content.")); bytes.hash(&mut hasher); } - salt.hash(&mut hasher); + add_salt(&mut hasher); hex::encode(hasher.finish().to_ne_bytes()) } diff --git a/crates/rspack_core/src/options/compiler_options.rs b/crates/rspack_core/src/options/compiler_options.rs index f345cb65f57a..ad38971c55b6 100644 --- a/crates/rspack_core/src/options/compiler_options.rs +++ b/crates/rspack_core/src/options/compiler_options.rs @@ -5,6 +5,7 @@ use crate::{ #[derive(Debug)] pub struct CompilerOptions { + pub name: Option, pub context: Context, pub output: OutputOptions, pub mode: Mode, diff --git a/crates/rspack_core/src/options/compiler_options_builder.rs b/crates/rspack_core/src/options/compiler_options_builder.rs index 06bbcc82ff5a..57e45d18dbdf 100644 --- a/crates/rspack_core/src/options/compiler_options_builder.rs +++ b/crates/rspack_core/src/options/compiler_options_builder.rs @@ -32,6 +32,7 @@ macro_rules! f { #[derive(Debug, Default)] pub struct CompilerOptionsBuilder { + name: Option, target: Option, entry: IndexMap, context: Option, @@ -50,6 +51,11 @@ impl CompilerOptions { } impl CompilerOptionsBuilder { + pub fn name(&mut self, name: String) -> &mut Self { + self.name = Some(name); + self + } + pub fn target(&mut self, target: Target) -> &mut Self { self.target = Some(target); self @@ -108,6 +114,7 @@ impl CompilerOptionsBuilder { } pub fn build(&mut self) -> CompilerOptions { + let name = self.name.take(); let context = self.context.take().unwrap_or_else(|| { std::env::current_dir() .expect("`current_dir` should be available") @@ -160,6 +167,7 @@ impl CompilerOptionsBuilder { ); CompilerOptions { + name, context, output, mode, diff --git a/crates/rspack_core/src/options/mode.rs b/crates/rspack_core/src/options/mode.rs index 7308b92ad2e3..68a22f0454c2 100644 --- a/crates/rspack_core/src/options/mode.rs +++ b/crates/rspack_core/src/options/mode.rs @@ -1,4 +1,4 @@ -#[derive(Clone, Copy, Debug, PartialEq)] +#[derive(Clone, Copy, Debug, PartialEq, Hash)] pub enum Mode { Development, Production, diff --git a/packages/rspack-test-tools/tests/cacheCases/invalidation/config-mode/file.js b/packages/rspack-test-tools/tests/cacheCases/invalidation/config-mode/file.js new file mode 100644 index 000000000000..1e5de9836a06 --- /dev/null +++ b/packages/rspack-test-tools/tests/cacheCases/invalidation/config-mode/file.js @@ -0,0 +1,7 @@ +export default 1; +--- +export default 2; +--- +export default 3; +--- +export default 4; diff --git a/packages/rspack-test-tools/tests/cacheCases/invalidation/config-mode/index.js b/packages/rspack-test-tools/tests/cacheCases/invalidation/config-mode/index.js new file mode 100644 index 000000000000..d3730e87207d --- /dev/null +++ b/packages/rspack-test-tools/tests/cacheCases/invalidation/config-mode/index.js @@ -0,0 +1,15 @@ +import value from "./file"; + +it("should invalidation using config.mode work", async () => { + if (COMPILER_INDEX == 0) { + expect(value).toBe(1); + await NEXT_HMR(); + expect(value).toBe(2); + await NEXT_START(); + } + if (COMPILER_INDEX == 1) { + expect(value).toBe(3); + await NEXT_HMR(); + expect(value).toBe(4); + } +}); diff --git a/packages/rspack-test-tools/tests/cacheCases/invalidation/config-mode/rspack.config.js b/packages/rspack-test-tools/tests/cacheCases/invalidation/config-mode/rspack.config.js new file mode 100644 index 000000000000..f80d01dba034 --- /dev/null +++ b/packages/rspack-test-tools/tests/cacheCases/invalidation/config-mode/rspack.config.js @@ -0,0 +1,30 @@ +const path = require("path"); + +let index = 1; + +/** @type {import("@rspack/core").Configuration} */ +module.exports = { + context: __dirname, + experiments: { + cache: { + type: "persistent", + snapshot: { + immutablePaths: [path.join(__dirname, "./file.js")] + } + } + }, + plugins: [ + { + apply(compiler) { + compiler.hooks.beforeCompile.tap("Test Plugin", function () { + if (index === 1) { + compiler.options.mode = "development"; + } else { + compiler.options.mode = "production"; + } + index++; + }); + } + } + ] +}; diff --git a/packages/rspack-test-tools/tests/cacheCases/invalidation/config-name/file.js b/packages/rspack-test-tools/tests/cacheCases/invalidation/config-name/file.js new file mode 100644 index 000000000000..1e5de9836a06 --- /dev/null +++ b/packages/rspack-test-tools/tests/cacheCases/invalidation/config-name/file.js @@ -0,0 +1,7 @@ +export default 1; +--- +export default 2; +--- +export default 3; +--- +export default 4; diff --git a/packages/rspack-test-tools/tests/cacheCases/invalidation/config-name/index.js b/packages/rspack-test-tools/tests/cacheCases/invalidation/config-name/index.js new file mode 100644 index 000000000000..145d8a0cfa25 --- /dev/null +++ b/packages/rspack-test-tools/tests/cacheCases/invalidation/config-name/index.js @@ -0,0 +1,15 @@ +import value from "./file"; + +it("should invalidation using config.name work", async () => { + if (COMPILER_INDEX == 0) { + expect(value).toBe(1); + await NEXT_HMR(); + expect(value).toBe(2); + await NEXT_START(); + } + if (COMPILER_INDEX == 1) { + expect(value).toBe(3); + await NEXT_HMR(); + expect(value).toBe(4); + } +}); diff --git a/packages/rspack-test-tools/tests/cacheCases/invalidation/config-name/rspack.config.js b/packages/rspack-test-tools/tests/cacheCases/invalidation/config-name/rspack.config.js new file mode 100644 index 000000000000..d569dfbfcffe --- /dev/null +++ b/packages/rspack-test-tools/tests/cacheCases/invalidation/config-name/rspack.config.js @@ -0,0 +1,26 @@ +const path = require("path"); + +let index = 1; + +/** @type {import("@rspack/core").Configuration} */ +module.exports = { + context: __dirname, + experiments: { + cache: { + type: "persistent", + snapshot: { + immutablePaths: [path.join(__dirname, "./file.js")] + } + } + }, + plugins: [ + { + apply(compiler) { + compiler.hooks.beforeCompile.tap("Test Plugin", function () { + compiler.options.name = String(index); + index++; + }); + } + } + ] +}; diff --git a/packages/rspack/src/config/adapter.ts b/packages/rspack/src/config/adapter.ts index 2e65dde63b89..f41be2bbc483 100644 --- a/packages/rspack/src/config/adapter.ts +++ b/packages/rspack/src/config/adapter.ts @@ -76,6 +76,7 @@ export const getRawOptions = ( const mode = options.mode; const experiments = options.experiments as Required; return { + name: options.name, mode, context: options.context!, output: options.output as Required,