Skip to content

Commit

Permalink
feat: support size option for optimization.chunkIds config (#8642)
Browse files Browse the repository at this point in the history
  • Loading branch information
inottn authored Dec 13, 2024
1 parent 993b792 commit 52a3e42
Show file tree
Hide file tree
Showing 16 changed files with 174 additions and 12 deletions.
5 changes: 5 additions & 0 deletions crates/node_binding/binding.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,7 @@ export declare enum BuiltinPluginName {
NaturalChunkIdsPlugin = 'NaturalChunkIdsPlugin',
NamedChunkIdsPlugin = 'NamedChunkIdsPlugin',
DeterministicChunkIdsPlugin = 'DeterministicChunkIdsPlugin',
OccurrenceChunkIdsPlugin = 'OccurrenceChunkIdsPlugin',
RealContentHashPlugin = 'RealContentHashPlugin',
RemoveEmptyChunksPlugin = 'RemoveEmptyChunksPlugin',
EnsureChunkConditionsPlugin = 'EnsureChunkConditionsPlugin',
Expand Down Expand Up @@ -1731,6 +1732,10 @@ export interface RawNonStandard {
deepSelectorCombinator: boolean
}

export interface RawOccurrenceChunkIdsPluginOptions {
prioritiseInitial?: boolean
}

export interface RawOptimizationOptions {
removeAvailableModules: boolean
sideEffects: string
Expand Down
11 changes: 10 additions & 1 deletion crates/rspack_binding_options/src/options/raw_builtins/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ mod raw_copy;
mod raw_css_extract;
mod raw_dll;
mod raw_html;
mod raw_ids;
mod raw_ignore;
mod raw_lazy_compilation;
mod raw_lightning_css_minimizer;
Expand All @@ -17,13 +18,14 @@ mod raw_swc_js_minimizer;
use napi::{bindgen_prelude::FromNapiValue, Env, JsUnknown};
use napi_derive::napi;
use raw_dll::{RawDllReferenceAgencyPluginOptions, RawFlagAllModulesAsUsedPluginOptions};
use raw_ids::RawOccurrenceChunkIdsPluginOptions;
use raw_lightning_css_minimizer::RawLightningCssMinimizerRspackPluginOptions;
use rspack_binding_values::entry::JsEntryPluginOptions;
use rspack_core::{BoxPlugin, Plugin, PluginExt};
use rspack_error::Result;
use rspack_ids::{
DeterministicChunkIdsPlugin, DeterministicModuleIdsPlugin, NamedChunkIdsPlugin,
NamedModuleIdsPlugin, NaturalChunkIdsPlugin, NaturalModuleIdsPlugin,
NamedModuleIdsPlugin, NaturalChunkIdsPlugin, NaturalModuleIdsPlugin, OccurrenceChunkIdsPlugin,
};
use rspack_napi::NapiResultExt;
use rspack_plugin_asset::AssetPlugin;
Expand Down Expand Up @@ -149,6 +151,7 @@ pub enum BuiltinPluginName {
NaturalChunkIdsPlugin,
NamedChunkIdsPlugin,
DeterministicChunkIdsPlugin,
OccurrenceChunkIdsPlugin,
RealContentHashPlugin,
RemoveEmptyChunksPlugin,
EnsureChunkConditionsPlugin,
Expand Down Expand Up @@ -370,6 +373,12 @@ impl BuiltinPlugin {
BuiltinPluginName::DeterministicChunkIdsPlugin => {
plugins.push(DeterministicChunkIdsPlugin::default().boxed())
}
BuiltinPluginName::OccurrenceChunkIdsPlugin => plugins.push(
OccurrenceChunkIdsPlugin::new(
downcast_into::<RawOccurrenceChunkIdsPluginOptions>(self.options)?.into(),
)
.boxed(),
),
BuiltinPluginName::RealContentHashPlugin => {
plugins.push(RealContentHashPlugin::default().boxed())
}
Expand Down
16 changes: 16 additions & 0 deletions crates/rspack_binding_options/src/options/raw_builtins/raw_ids.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
use napi_derive::napi;
use rspack_ids::OccurrenceChunkIdsPluginOptions;

#[derive(Debug)]
#[napi(object, object_to_js = false)]
pub struct RawOccurrenceChunkIdsPluginOptions {
pub prioritise_initial: Option<bool>,
}

impl From<RawOccurrenceChunkIdsPluginOptions> for OccurrenceChunkIdsPluginOptions {
fn from(value: RawOccurrenceChunkIdsPluginOptions) -> Self {
Self {
prioritise_initial: value.prioritise_initial.unwrap_or_default(),
}
}
}
4 changes: 4 additions & 0 deletions crates/rspack_core/src/chunk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,10 @@ impl Chunk {
self.groups.remove(chunk_group)
}

pub fn get_number_of_groups(&self) -> usize {
self.groups.len()
}

pub fn runtime(&self) -> &RuntimeSpec {
&self.runtime
}
Expand Down
2 changes: 2 additions & 0 deletions crates/rspack_ids/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,5 @@ mod natural_module_ids_plugin;
pub use natural_module_ids_plugin::NaturalModuleIdsPlugin;
mod natural_chunk_ids_plugin;
pub use natural_chunk_ids_plugin::NaturalChunkIdsPlugin;
mod occurrence_chunk_ids_plugin;
pub use occurrence_chunk_ids_plugin::*;
94 changes: 94 additions & 0 deletions crates/rspack_ids/src/occurrence_chunk_ids_plugin.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
use std::collections::HashMap;

use itertools::Itertools;
use rspack_collections::DatabaseItem;
use rspack_core::{
ApplyContext, Chunk, CompilationChunkIds, CompilerOptions, Plugin, PluginContext,
};
use rspack_error::Result;
use rspack_hook::{plugin, plugin_hook};

use crate::id_helpers::{assign_ascending_chunk_ids, compare_chunks_natural};

pub struct OccurrenceChunkIdsPluginOptions {
pub prioritise_initial: bool,
}

#[plugin]
#[derive(Debug, Default)]
pub struct OccurrenceChunkIdsPlugin {
prioritise_initial: bool,
}

impl OccurrenceChunkIdsPlugin {
pub fn new(option: OccurrenceChunkIdsPluginOptions) -> Self {
Self::new_inner(option.prioritise_initial)
}
}

#[plugin_hook(CompilationChunkIds for OccurrenceChunkIdsPlugin)]
fn chunk_ids(&self, compilation: &mut rspack_core::Compilation) -> Result<()> {
let chunk_graph = &compilation.chunk_graph;
let module_graph = &compilation.get_module_graph();
let chunk_group_by_ukey = &compilation.chunk_group_by_ukey;
let mut occurs_in_initial_chunks_map = HashMap::new();

for chunk in compilation.chunk_by_ukey.values() {
let mut occurs = 0;
for chunk_group_ukey in chunk.groups() {
if let Some(chunk_group) = chunk_group_by_ukey.get(chunk_group_ukey) {
for parent_ukey in &chunk_group.parents {
if let Some(parent) = chunk_group_by_ukey.get(parent_ukey) {
if parent.is_initial() {
occurs += 1;
}
}
}
}
}
occurs_in_initial_chunks_map.insert(chunk.ukey(), occurs);
}

let chunks = compilation
.chunk_by_ukey
.values()
.map(|chunk| chunk as &Chunk)
.sorted_unstable_by(|a, b| {
if self.prioritise_initial {
let a_entry_occurs = occurs_in_initial_chunks_map.get(&a.ukey()).unwrap_or(&0);
let b_entry_occurs = occurs_in_initial_chunks_map.get(&b.ukey()).unwrap_or(&0);
if a_entry_occurs != b_entry_occurs {
return b_entry_occurs.cmp(a_entry_occurs);
}
}

let a_occurs = a.get_number_of_groups();
let b_occurs = b.get_number_of_groups();
if a_occurs != b_occurs {
return b_occurs.cmp(&a_occurs);
}

compare_chunks_natural(chunk_graph, module_graph, &compilation.module_ids, a, b)
})
.map(|chunk| chunk.ukey())
.collect::<Vec<_>>();

assign_ascending_chunk_ids(&chunks, compilation);

Ok(())
}

impl Plugin for OccurrenceChunkIdsPlugin {
fn name(&self) -> &'static str {
"rspack.OccurrenceChunkIdsPlugin"
}

fn apply(&self, ctx: PluginContext<&mut ApplyContext>, _options: &CompilerOptions) -> Result<()> {
ctx
.context
.compilation_hooks
.chunk_ids
.tap(chunk_ids::new(self));
Ok(())
}
}
12 changes: 6 additions & 6 deletions packages/rspack/etc/core.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -4084,7 +4084,7 @@ type Open = (file: PathLike, flags: undefined | string | number, callback: (arg0
// @public (undocumented)
export type Optimization = {
moduleIds?: "named" | "natural" | "deterministic";
chunkIds?: "natural" | "named" | "deterministic";
chunkIds?: "natural" | "named" | "deterministic" | "size" | "total-size";
minimize?: boolean;
minimizer?: Array<"..." | Plugin_2>;
mergeDuplicateChunks?: boolean;
Expand Down Expand Up @@ -6918,7 +6918,7 @@ export const rspackOptions: z.ZodObject<{
snapshot: z.ZodOptional<z.ZodObject<{}, "strict", z.ZodTypeAny, {}, {}>>;
optimization: z.ZodOptional<z.ZodObject<{
moduleIds: z.ZodOptional<z.ZodEnum<["named", "natural", "deterministic"]>>;
chunkIds: z.ZodOptional<z.ZodEnum<["natural", "named", "deterministic"]>>;
chunkIds: z.ZodOptional<z.ZodEnum<["natural", "named", "deterministic", "size", "total-size"]>>;
minimize: z.ZodOptional<z.ZodBoolean>;
minimizer: z.ZodOptional<z.ZodArray<z.ZodUnion<[z.ZodLiteral<"...">, z.ZodUnion<[z.ZodType<t.RspackPluginInstance | t.WebpackPluginInstance | t.RspackPluginFunction | t.WebpackPluginFunction, z.ZodTypeDef, t.RspackPluginInstance | t.WebpackPluginInstance | t.RspackPluginFunction | t.WebpackPluginFunction>, z.ZodUnion<[z.ZodLiteral<false>, z.ZodLiteral<0>, z.ZodLiteral<"">, z.ZodNull, z.ZodUndefined]>]>]>, "many">>;
mergeDuplicateChunks: z.ZodOptional<z.ZodBoolean>;
Expand Down Expand Up @@ -7182,7 +7182,7 @@ export const rspackOptions: z.ZodObject<{
automaticNameDelimiter?: string | undefined;
} | undefined;
moduleIds?: "named" | "natural" | "deterministic" | undefined;
chunkIds?: "named" | "natural" | "deterministic" | undefined;
chunkIds?: "size" | "named" | "natural" | "deterministic" | "total-size" | undefined;
removeAvailableModules?: boolean | undefined;
minimize?: boolean | undefined;
minimizer?: (false | "" | 0 | "..." | t.RspackPluginInstance | t.WebpackPluginInstance | t.RspackPluginFunction | t.WebpackPluginFunction | null | undefined)[] | undefined;
Expand Down Expand Up @@ -7248,7 +7248,7 @@ export const rspackOptions: z.ZodObject<{
automaticNameDelimiter?: string | undefined;
} | undefined;
moduleIds?: "named" | "natural" | "deterministic" | undefined;
chunkIds?: "named" | "natural" | "deterministic" | undefined;
chunkIds?: "size" | "named" | "natural" | "deterministic" | "total-size" | undefined;
removeAvailableModules?: boolean | undefined;
minimize?: boolean | undefined;
minimizer?: (false | "" | 0 | "..." | t.RspackPluginInstance | t.WebpackPluginInstance | t.RspackPluginFunction | t.WebpackPluginFunction | null | undefined)[] | undefined;
Expand Down Expand Up @@ -8684,7 +8684,7 @@ export const rspackOptions: z.ZodObject<{
automaticNameDelimiter?: string | undefined;
} | undefined;
moduleIds?: "named" | "natural" | "deterministic" | undefined;
chunkIds?: "named" | "natural" | "deterministic" | undefined;
chunkIds?: "size" | "named" | "natural" | "deterministic" | "total-size" | undefined;
removeAvailableModules?: boolean | undefined;
minimize?: boolean | undefined;
minimizer?: (false | "" | 0 | "..." | t.RspackPluginInstance | t.WebpackPluginInstance | t.RspackPluginFunction | t.WebpackPluginFunction | null | undefined)[] | undefined;
Expand Down Expand Up @@ -9286,7 +9286,7 @@ export const rspackOptions: z.ZodObject<{
automaticNameDelimiter?: string | undefined;
} | undefined;
moduleIds?: "named" | "natural" | "deterministic" | undefined;
chunkIds?: "named" | "natural" | "deterministic" | undefined;
chunkIds?: "size" | "named" | "natural" | "deterministic" | "total-size" | undefined;
removeAvailableModules?: boolean | undefined;
minimize?: boolean | undefined;
minimizer?: (false | "" | 0 | "..." | t.RspackPluginInstance | t.WebpackPluginInstance | t.RspackPluginFunction | t.WebpackPluginFunction | null | undefined)[] | undefined;
Expand Down
12 changes: 12 additions & 0 deletions packages/rspack/src/builtin-plugin/OccurrenceChunkIdsPlugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import {
BuiltinPluginName,
type RawOccurrenceChunkIdsPluginOptions
} from "@rspack/binding";

import { create } from "./base";

export const OccurrenceChunkIdsPlugin = create(
BuiltinPluginName.OccurrenceChunkIdsPlugin,
(options?: RawOccurrenceChunkIdsPluginOptions) => ({ ...options }),
"compilation"
);
1 change: 1 addition & 0 deletions packages/rspack/src/builtin-plugin/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ export * from "./NamedModuleIdsPlugin";
export * from "./NaturalChunkIdsPlugin";
export * from "./NaturalModuleIdsPlugin";
export * from "./NodeTargetPlugin";
export * from "./OccurrenceChunkIdsPlugin";
export * from "./ProgressPlugin";
export * from "./ProvidePlugin";
export * from "./RealContentHashPlugin";
Expand Down
2 changes: 1 addition & 1 deletion packages/rspack/src/config/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2208,7 +2208,7 @@ export type Optimization = {
/**
* Which algorithm to use when choosing chunk ids.
*/
chunkIds?: "natural" | "named" | "deterministic";
chunkIds?: "natural" | "named" | "deterministic" | "size" | "total-size";

/**
* Whether to minimize the bundle.
Expand Down
4 changes: 3 additions & 1 deletion packages/rspack/src/config/zod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1244,7 +1244,9 @@ const optimizationSplitChunksOptions = z.strictObject({

const optimization = z.strictObject({
moduleIds: z.enum(["named", "natural", "deterministic"]).optional(),
chunkIds: z.enum(["natural", "named", "deterministic"]).optional(),
chunkIds: z
.enum(["natural", "named", "deterministic", "size", "total-size"])
.optional(),
minimize: z.boolean().optional(),
minimizer: z.literal("...").or(plugin).array().optional(),
mergeDuplicateChunks: z.boolean().optional(),
Expand Down
13 changes: 13 additions & 0 deletions packages/rspack/src/rspackOptionsApply.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ import {
NaturalModuleIdsPlugin,
NoEmitOnErrorsPlugin,
NodeTargetPlugin,
OccurrenceChunkIdsPlugin,
RealContentHashPlugin,
RemoveEmptyChunksPlugin,
RuntimeChunkPlugin,
Expand Down Expand Up @@ -337,6 +338,18 @@ export class RspackOptionsApply {
new DeterministicChunkIdsPlugin().apply(compiler);
break;
}
case "size": {
new OccurrenceChunkIdsPlugin({
prioritiseInitial: true
}).apply(compiler);
break;
}
case "total-size": {
new OccurrenceChunkIdsPlugin({
prioritiseInitial: false
}).apply(compiler);
break;
}
default:
throw new Error(`chunkIds: ${chunkIds} is not implemented`);
}
Expand Down

This file was deleted.

2 changes: 1 addition & 1 deletion website/components/PluginSupportStatusTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -413,7 +413,7 @@ const pluginSupportStatusList: PluginSupportStatus[] = [
},
{
name: 'OccurrenceChunkIdsPlugin',
status: SupportStatus.NotSupported,
status: SupportStatus.FullySupported,
},
{
name: 'OccurrenceModuleIdsPlugin',
Expand Down
3 changes: 3 additions & 0 deletions website/docs/en/config/optimization.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,11 @@ The following string values are supported:

| option | description |
| ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| `'natural'` | Use numeric ids in order of usage. |
| `'named'` | Readable ids for better debugging. |
| `'deterministic'` | Short numeric ids which will not be changing between compilation. Good for long term caching. By default a minimum length of 3 digits is used. |
| `'size'` | Use numeric ids to make the initial download package smaller. |
| `'total-size'` | Use numeric ids to make the overall download package smaller. |

```js title=rspack.config.js
module.exports = {
Expand Down
3 changes: 3 additions & 0 deletions website/docs/zh/config/optimization.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,11 @@ module.exports = {

| 选项 | 描述 |
| ----------------- | ---------------------------------------------------------------------------------------- |
| `'natural'` | 根据 Chunk 加载的顺序使用自增数字作为 Chunk id。 |
| `'named'` | 使用有意义、方便调试的内容当作 Chunk id。 |
| `'deterministic'` | 简短的数字 id,在多次编译的场景下,会尽量保持其稳定性。适合长期缓存。默认使用 3 位数字。 |
| `'size'` | 使用让初始下载包大小更小的数字 id。 |
| `'total-size'` | 使用让总下载包大小更小的数字 id。 |

```js title=rspack.config.js
module.exports = {
Expand Down

2 comments on commit 52a3e42

@rspack-bot
Copy link

Choose a reason for hiding this comment

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

📝 Ran ecosystem CI: Open

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

@rspack-bot
Copy link

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 (2024-12-13 c81fa8d) Current Change
10000_big_production-mode_disable-minimize + exec 37.7 s ± 976 ms 37.5 s ± 521 ms -0.55 %
10000_development-mode + exec 1.79 s ± 21 ms 1.78 s ± 35 ms -0.40 %
10000_development-mode_hmr + exec 656 ms ± 7.9 ms 654 ms ± 11 ms -0.35 %
10000_production-mode + exec 2.33 s ± 42 ms 2.34 s ± 23 ms +0.53 %
arco-pro_development-mode + exec 1.74 s ± 73 ms 1.74 s ± 76 ms +0.18 %
arco-pro_development-mode_hmr + exec 379 ms ± 1.3 ms 378 ms ± 1.3 ms -0.11 %
arco-pro_production-mode + exec 3.11 s ± 87 ms 3.13 s ± 120 ms +0.58 %
arco-pro_production-mode_generate-package-json-webpack-plugin + exec 3.17 s ± 78 ms 3.18 s ± 86 ms +0.30 %
arco-pro_production-mode_traverse-chunk-modules + exec 3.12 s ± 93 ms 3.12 s ± 57 ms -0.12 %
threejs_development-mode_10x + exec 1.6 s ± 9.6 ms 1.58 s ± 11 ms -1.14 %
threejs_development-mode_10x_hmr + exec 789 ms ± 24 ms 769 ms ± 13 ms -2.55 %
threejs_production-mode_10x + exec 4.94 s ± 110 ms 4.92 s ± 38 ms -0.46 %
10000_big_production-mode_disable-minimize + rss memory 9737 MiB ± 290 MiB 9587 MiB ± 120 MiB -1.54 %
10000_development-mode + rss memory 808 MiB ± 16.8 MiB 827 MiB ± 43.3 MiB +2.31 %
10000_development-mode_hmr + rss memory 1906 MiB ± 321 MiB 1965 MiB ± 284 MiB +3.09 %
10000_production-mode + rss memory 699 MiB ± 38.9 MiB 706 MiB ± 27.9 MiB +0.99 %
arco-pro_development-mode + rss memory 732 MiB ± 47.1 MiB 709 MiB ± 18.9 MiB -3.25 %
arco-pro_development-mode_hmr + rss memory 825 MiB ± 19.7 MiB 780 MiB ± 70.9 MiB -5.47 %
arco-pro_production-mode + rss memory 792 MiB ± 69.8 MiB 833 MiB ± 57.9 MiB +5.17 %
arco-pro_production-mode_generate-package-json-webpack-plugin + rss memory 815 MiB ± 54.2 MiB 836 MiB ± 51.5 MiB +2.63 %
arco-pro_production-mode_traverse-chunk-modules + rss memory 841 MiB ± 32.3 MiB 825 MiB ± 44.9 MiB -1.85 %
threejs_development-mode_10x + rss memory 782 MiB ± 63.4 MiB 743 MiB ± 42.2 MiB -4.94 %
threejs_development-mode_10x_hmr + rss memory 1686 MiB ± 334 MiB 1661 MiB ± 214 MiB -1.51 %
threejs_production-mode_10x + rss memory 1103 MiB ± 83.2 MiB 1083 MiB ± 52 MiB -1.81 %

Please sign in to comment.