Skip to content

Commit

Permalink
feat: chunk graph get module hash (#9242)
Browse files Browse the repository at this point in the history
  • Loading branch information
ahabhgk authored Feb 11, 2025
1 parent d688f4d commit c1e945f
Show file tree
Hide file tree
Showing 11 changed files with 89 additions and 21 deletions.
1 change: 1 addition & 0 deletions crates/node_binding/binding.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ export declare class JsChunkGraph {
getChunkModulesIterableBySourceType(chunk: JsChunk, sourceType: string): JsModule[]
getModuleChunks(module: JsModule): JsChunk[]
getModuleId(jsModule: JsModule): string | null
getModuleHash(module: JsModule, runtime: string | string[] | undefined): string | null
getBlockChunkGroup(jsBlock: JsDependenciesBlock): JsChunkGroup | null
}

Expand Down
24 changes: 22 additions & 2 deletions crates/rspack_binding_values/src/chunk_graph.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
use std::ptr::NonNull;
use std::{ptr::NonNull, sync::Arc};

use napi::Result;
use napi::{Either, Result};
use napi_derive::napi;
use rspack_core::{ChunkGraph, Compilation, SourceType};

use crate::{
JsChunk, JsChunkGroupWrapper, JsChunkWrapper, JsDependenciesBlock, JsModule, JsModuleWrapper,
JsRuntimeSpec,
};

#[napi]
Expand Down Expand Up @@ -141,6 +142,25 @@ impl JsChunkGraph {
)
}

#[napi(ts_args_type = "module: JsModule, runtime: string | string[] | undefined")]
pub fn get_module_hash(
&self,
js_module: &JsModule,
js_runtime: JsRuntimeSpec,
) -> napi::Result<Option<&str>> {
let compilation = self.as_ref()?;
let Some(runtime) = js_runtime.map(|js_runtime| match js_runtime {
Either::A(str) => std::iter::once(str).map(Arc::from).collect(),
Either::B(vec) => vec.into_iter().map(Arc::from).collect(),
}) else {
return Ok(None);
};
Ok(
ChunkGraph::get_module_hash(compilation, js_module.identifier, &runtime)
.map(|hash| hash.encoded()),
)
}

#[napi(ts_return_type = "JsChunkGroup | null")]
pub fn get_block_chunk_group(
&self,
Expand Down
2 changes: 0 additions & 2 deletions crates/rspack_binding_values/src/dependency.rs
Original file line number Diff line number Diff line change
Expand Up @@ -221,8 +221,6 @@ impl ToNapiValue for JsDependencyWrapper {
}
}

pub type JsRuntimeSpec = Either<String, Vec<String>>;

#[napi(object)]
pub struct RawDependency {
pub request: String,
Expand Down
19 changes: 8 additions & 11 deletions crates/rspack_binding_values/src/exports_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,20 +37,20 @@ impl JsExportsInfo {
#[napi]
impl JsExportsInfo {
#[napi(ts_args_type = "runtime: string | string[] | undefined")]
pub fn is_used(&self, js_runtime: Option<JsRuntimeSpec>) -> napi::Result<bool> {
pub fn is_used(&self, js_runtime: JsRuntimeSpec) -> napi::Result<bool> {
let module_graph = self.as_ref()?;
let runtime: Option<RuntimeSpec> = js_runtime.map(|js_rt| match js_rt {
Either::A(str) => vec![str].into_iter().map(Arc::from).collect(),
Either::A(str) => std::iter::once(str).map(Arc::from).collect(),
Either::B(vec) => vec.into_iter().map(Arc::from).collect(),
});
Ok(self.exports_info.is_used(&module_graph, runtime.as_ref()))
}

#[napi(ts_args_type = "runtime: string | string[] | undefined")]
pub fn is_module_used(&self, js_runtime: Option<JsRuntimeSpec>) -> napi::Result<bool> {
pub fn is_module_used(&self, js_runtime: JsRuntimeSpec) -> napi::Result<bool> {
let module_graph = self.as_ref()?;
let runtime: Option<RuntimeSpec> = js_runtime.map(|js_rt| match js_rt {
Either::A(str) => vec![str].into_iter().map(Arc::from).collect(),
Either::A(str) => std::iter::once(str).map(Arc::from).collect(),
Either::B(vec) => vec.into_iter().map(Arc::from).collect(),
});
Ok(
Expand All @@ -61,13 +61,10 @@ impl JsExportsInfo {
}

#[napi(ts_args_type = "runtime: string | string[] | undefined")]
pub fn set_used_in_unknown_way(
&mut self,
js_runtime: Option<JsRuntimeSpec>,
) -> napi::Result<bool> {
pub fn set_used_in_unknown_way(&mut self, js_runtime: JsRuntimeSpec) -> napi::Result<bool> {
let mut module_graph = self.as_mut()?;
let runtime: Option<RuntimeSpec> = js_runtime.map(|js_rt| match js_rt {
Either::A(str) => vec![str].into_iter().map(Arc::from).collect(),
Either::A(str) => std::iter::once(str).map(Arc::from).collect(),
Either::B(vec) => vec.into_iter().map(Arc::from).collect(),
});
Ok(
Expand All @@ -84,15 +81,15 @@ impl JsExportsInfo {
pub fn get_used(
&self,
js_name: Either<String, Vec<String>>,
js_runtime: Option<JsRuntimeSpec>,
js_runtime: JsRuntimeSpec,
) -> napi::Result<u32> {
let module_graph = self.as_ref()?;
let name = match js_name {
Either::A(s) => UsedName::Str(s.into()),
Either::B(v) => UsedName::Vec(v.into_iter().map(Into::into).collect::<Vec<_>>()),
};
let runtime: Option<RuntimeSpec> = js_runtime.map(|js_rt| match js_rt {
Either::A(str) => vec![str].into_iter().map(Arc::from).collect(),
Either::A(str) => std::iter::once(str).map(Arc::from).collect(),
Either::B(vec) => vec.into_iter().map(Arc::from).collect(),
});
Ok(
Expand Down
3 changes: 3 additions & 0 deletions crates/rspack_binding_values/src/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use std::sync::LazyLock;

use cow_utils::CowUtils;
use heck::{ToLowerCamelCase, ToSnakeCase};
use napi::Either;
use napi_derive::napi;
use rspack_core::RuntimeGlobals;
use rspack_plugin_runtime::{
Expand Down Expand Up @@ -235,3 +236,5 @@ impl From<RuntimeModuleChunkWrapper> for JsChunkWrapper {
}
}
}

pub type JsRuntimeSpec = Option<Either<String, Vec<String>>>;
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
class Plugin {
apply(compiler) {
compiler.hooks.compilation.tap("Test", compilation => {
compilation.hooks.processAssets.tap("Test", () => {
const module = Array.from(compilation.modules)[0];
const moduleHash = compilation.chunkGraph.getModuleHash(module, "main");
expect(moduleHash).toBeTruthy();
});
});
}
}

/** @type {import("@rspack/core").Configuration} */
module.exports = {
target: "web",
node: false,
entry: {
main: "./index.js"
},
output: {
filename: "[name].js"
},
optimization: {
sideEffects: false
},
plugins: [new Plugin()]
};
4 changes: 3 additions & 1 deletion packages/rspack/etc/core.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -547,6 +547,8 @@ class ChunkGraph {
// (undocumented)
getModuleChunksIterable(module: Module): Iterable<Chunk>;
// (undocumented)
getModuleHash(module: Module, runtime: RuntimeSpec): string | null;
// (undocumented)
getModuleId(module: Module): string | null;
// (undocumented)
getNumberOfEntryModules(chunk: Chunk): number;
Expand Down Expand Up @@ -10081,7 +10083,7 @@ const RuntimePluginImpl: {
type RuntimePlugins = string[];

// @public (undocumented)
type RuntimeSpec = string | string[] | undefined;
type RuntimeSpec = string | Set<string> | undefined;

// @public (undocumented)
type SafeParseError<Input> = {
Expand Down
9 changes: 9 additions & 0 deletions packages/rspack/src/ChunkGraph.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import type { JsChunkGraph } from "@rspack/binding";
import type { RuntimeSpec } from "./util/runtime";

import { Chunk } from "./Chunk";
import { ChunkGroup } from "./ChunkGroup";
import { DependenciesBlock } from "./DependenciesBlock";
import { Module } from "./Module";
import { toJsRuntimeSpec } from "./util/runtime";

export class ChunkGraph {
#inner: JsChunkGraph;
Expand Down Expand Up @@ -72,6 +74,13 @@ export class ChunkGraph {
return this.#inner.getModuleId(Module.__to_binding(module));
}

getModuleHash(module: Module, runtime: RuntimeSpec): string | null {
return this.#inner.getModuleHash(
Module.__to_binding(module),
toJsRuntimeSpec(runtime)
);
}

getBlockChunkGroup(depBlock: DependenciesBlock): ChunkGroup | null {
const binding = this.#inner.getBlockChunkGroup(
DependenciesBlock.__to_binding(depBlock)
Expand Down
11 changes: 6 additions & 5 deletions packages/rspack/src/ExportsInfo.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { JsExportsInfo } from "@rspack/binding";
import type { RuntimeSpec } from "./util/runtime";

type RuntimeSpec = string | string[] | undefined;
import { toJsRuntimeSpec } from "./util/runtime";

/**
* Unused: 0
Expand All @@ -23,18 +24,18 @@ export class ExportsInfo {
}

isUsed(runtime: RuntimeSpec): boolean {
return this.#inner.isUsed(runtime);
return this.#inner.isUsed(toJsRuntimeSpec(runtime));
}

isModuleUsed(runtime: RuntimeSpec): boolean {
return this.#inner.isModuleUsed(runtime);
return this.#inner.isModuleUsed(toJsRuntimeSpec(runtime));
}

setUsedInUnknownWay(runtime: RuntimeSpec): boolean {
return this.#inner.setUsedInUnknownWay(runtime);
return this.#inner.setUsedInUnknownWay(toJsRuntimeSpec(runtime));
}

getUsed(name: string | string[], runtime: RuntimeSpec): UsageStateType {
return this.#inner.getUsed(name, runtime);
return this.#inner.getUsed(name, toJsRuntimeSpec(runtime));
}
}
10 changes: 10 additions & 0 deletions packages/rspack/src/util/runtime.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
export type RuntimeSpec = string | Set<string> | undefined;

export function toJsRuntimeSpec(
runtime: RuntimeSpec
): string | string[] | undefined {
if (runtime instanceof Set) {
return Array.from(runtime);
}
return runtime;
}

2 comments on commit c1e945f

@github-actions
Copy link
Contributor

@github-actions github-actions bot commented on c1e945f Feb 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 Benchmark detail: Open

Name Base (2025-02-11 9d82335) Current Change
10000_big_production-mode_disable-minimize + exec 37.7 s ± 637 ms 39.1 s ± 1.18 s +3.54 %
10000_development-mode + exec 1.88 s ± 89 ms 1.84 s ± 38 ms -1.90 %
10000_development-mode_hmr + exec 685 ms ± 7.4 ms 695 ms ± 35 ms +1.43 %
10000_production-mode + exec 2.28 s ± 51 ms 2.31 s ± 26 ms +1.47 %
10000_production-mode_persistent-cold + exec 2.47 s ± 72 ms 2.42 s ± 25 ms -2.03 %
10000_production-mode_persistent-hot + exec 1.65 s ± 61 ms 1.64 s ± 64 ms -0.28 %
arco-pro_development-mode + exec 1.78 s ± 145 ms 1.76 s ± 130 ms -0.93 %
arco-pro_development-mode_hmr + exec 389 ms ± 2.1 ms 387 ms ± 1.4 ms -0.36 %
arco-pro_production-mode + exec 3.59 s ± 217 ms 3.64 s ± 255 ms +1.31 %
arco-pro_production-mode_generate-package-json-webpack-plugin + exec 3.72 s ± 229 ms 3.69 s ± 123 ms -0.74 %
arco-pro_production-mode_persistent-cold + exec 3.85 s ± 164 ms 3.81 s ± 123 ms -0.96 %
arco-pro_production-mode_persistent-hot + exec 2.36 s ± 99 ms 2.42 s ± 199 ms +2.50 %
arco-pro_production-mode_traverse-chunk-modules + exec 3.63 s ± 69 ms 3.68 s ± 189 ms +1.53 %
large-dyn-imports_development-mode + exec 2.09 s ± 24 ms 2.15 s ± 114 ms +2.62 %
large-dyn-imports_production-mode + exec 2.15 s ± 71 ms 2.16 s ± 45 ms +0.33 %
threejs_development-mode_10x + exec 1.54 s ± 25 ms 1.56 s ± 43 ms +1.82 %
threejs_development-mode_10x_hmr + exec 779 ms ± 7 ms 788 ms ± 13 ms +1.21 %
threejs_production-mode_10x + exec 5.2 s ± 32 ms 5.32 s ± 322 ms +2.30 %
threejs_production-mode_10x_persistent-cold + exec 5.27 s ± 65 ms 5.39 s ± 352 ms +2.13 %
threejs_production-mode_10x_persistent-hot + exec 4.53 s ± 220 ms 4.57 s ± 254 ms +0.80 %
10000_big_production-mode_disable-minimize + rss memory 8706 MiB ± 32.4 MiB 8701 MiB ± 58.3 MiB -0.05 %
10000_development-mode + rss memory 649 MiB ± 12.6 MiB 664 MiB ± 16.9 MiB +2.37 %
10000_development-mode_hmr + rss memory 1344 MiB ± 112 MiB 1260 MiB ± 285 MiB -6.23 %
10000_production-mode + rss memory 621 MiB ± 21.8 MiB 652 MiB ± 23.7 MiB +5.02 %
10000_production-mode_persistent-cold + rss memory 746 MiB ± 24.7 MiB 749 MiB ± 9.47 MiB +0.27 %
10000_production-mode_persistent-hot + rss memory 717 MiB ± 23.3 MiB 754 MiB ± 18.7 MiB +5.13 %
arco-pro_development-mode + rss memory 569 MiB ± 17.5 MiB 564 MiB ± 26.3 MiB -0.94 %
arco-pro_development-mode_hmr + rss memory 643 MiB ± 49.1 MiB 663 MiB ± 37.4 MiB +3.22 %
arco-pro_production-mode + rss memory 714 MiB ± 28.8 MiB 700 MiB ± 18.7 MiB -1.91 %
arco-pro_production-mode_generate-package-json-webpack-plugin + rss memory 732 MiB ± 22.4 MiB 722 MiB ± 13.5 MiB -1.34 %
arco-pro_production-mode_persistent-cold + rss memory 853 MiB ± 45.5 MiB 827 MiB ± 39.9 MiB -3.03 %
arco-pro_production-mode_persistent-hot + rss memory 708 MiB ± 27.8 MiB 691 MiB ± 11.6 MiB -2.32 %
arco-pro_production-mode_traverse-chunk-modules + rss memory 727 MiB ± 48.2 MiB 710 MiB ± 46.4 MiB -2.32 %
large-dyn-imports_development-mode + rss memory 644 MiB ± 5.26 MiB 638 MiB ± 2.97 MiB -0.94 %
large-dyn-imports_production-mode + rss memory 526 MiB ± 7.84 MiB 520 MiB ± 4.8 MiB -1.12 %
threejs_development-mode_10x + rss memory 553 MiB ± 16.3 MiB 550 MiB ± 9.18 MiB -0.48 %
threejs_development-mode_10x_hmr + rss memory 1145 MiB ± 140 MiB 1084 MiB ± 172 MiB -5.27 %
threejs_production-mode_10x + rss memory 828 MiB ± 50.8 MiB 829 MiB ± 26.8 MiB +0.12 %
threejs_production-mode_10x_persistent-cold + rss memory 960 MiB ± 14.5 MiB 935 MiB ± 56.3 MiB -2.59 %
threejs_production-mode_10x_persistent-hot + rss memory 877 MiB ± 54.8 MiB 866 MiB ± 55.2 MiB -1.34 %

@github-actions
Copy link
Contributor

@github-actions github-actions bot commented on c1e945f Feb 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 Ecosystem CI detail: Open

suite result
modernjs ❌ failure
rspress ✅ success
rslib ❌ failure
rsbuild ❌ failure
rsdoctor ❌ failure
examples ✅ success
devserver ✅ success
nuxt ✅ success

Please sign in to comment.