Skip to content

Commit

Permalink
feat: support split chunk strategy of chunks
Browse files Browse the repository at this point in the history
  • Loading branch information
ClarkXia committed Nov 15, 2023
1 parent 2f4bf6f commit 9437bc4
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 16 deletions.
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion crates/binding_options/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,12 @@ rspack_plugin_swc_js_minimizer = { path = "../.rspack_crates/rspack_plu
rspack_plugin_wasm = { path = "../.rspack_crates/rspack_plugin_wasm" }
rspack_plugin_worker = { path = "../.rspack_crates/rspack_plugin_worker" }
rspack_regex = { path = "../.rspack_crates/rspack_regex" }
rspack_hash = { path = "../.rspack_crates/rspack_hash" }
rspack_swc_visitors = { path = "../.rspack_crates/rspack_swc_visitors" }
loader_compilation = { path = "../loader_compilation" }
plugin_manifest = { path = "../plugin_manifest" }
plugin_manifest = { path = "../plugin_manifest" }

futures-util = { workspace = true }
anyhow = { workspace = true, features = ["backtrace"] }
async-trait = { workspace = true }
better_scoped_tls = { workspace = true }
Expand Down
2 changes: 1 addition & 1 deletion crates/binding_options/src/options/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ impl RawOptionsApply for RSPackRawOptions {
self.features.split_chunks_strategy.unwrap(),
self.optimization,
);
optimization = split_chunk_strategy.apply(plugins)?;
optimization = split_chunk_strategy.apply(plugins, context.to_string())?;
} else {
optimization = IS_ENABLE_NEW_SPLIT_CHUNKS.set(&experiments.new_split_chunks, || {
self.optimization.apply(plugins)
Expand Down
91 changes: 77 additions & 14 deletions crates/binding_options/src/options/raw_features.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
use std::{sync::Arc, hash::Hasher};
use futures_util::{FutureExt, future};
use napi_derive::napi;
use serde::Deserialize;
use rspack_core::{Optimization, PluginExt, SideEffectOption, UsedExportsOption, SourceType, BoxPlugin};
use rspack_core::{
Optimization, PluginExt, SideEffectOption, UsedExportsOption, SourceType,
BoxPlugin, Module, ModuleType,
};
use rspack_error::internal_error;
use rspack_ids::{
DeterministicChunkIdsPlugin, DeterministicModuleIdsPlugin, NamedChunkIdsPlugin,
Expand All @@ -9,9 +14,10 @@ use rspack_ids::{
use rspack_binding_options::RawOptimizationOptions;
use rspack_plugin_split_chunks_new::{PluginOptions, CacheGroup};
use rspack_regex::RspackRegex;
use rspack_hash::{RspackHash, HashFunction, HashDigest};

pub struct SplitChunksStrategy {
strategy: String,
strategy: RawStrategyOptions,
// Get the neccessary options from RawOptimizationOptions.
chunk_ids: String,
module_ids: String,
Expand All @@ -23,34 +29,83 @@ pub struct SplitChunksStrategy {
remove_available_modules: bool,
}

fn get_plugin_options(strategy: String) -> rspack_plugin_split_chunks_new::PluginOptions {
fn get_modules_size(module: &dyn Module) -> f64 {
let mut size = 0f64;
for source_type in module.source_types() {
size += module.size(source_type);
}
size
}

fn get_plugin_options(strategy: RawStrategyOptions, context: String) -> rspack_plugin_split_chunks_new::PluginOptions {
use rspack_plugin_split_chunks_new::SplitChunkSizes;
tracing::info!("strategy: {}", strategy);
let default_size_types = [SourceType::JavaScript, SourceType::Unknown];
let create_sizes = |size: Option<f64>| {
size
.map(|size| SplitChunkSizes::with_initial_value(&default_size_types, size))
.unwrap_or_else(SplitChunkSizes::default)
};

let re_node_modules = RspackRegex::new("node_modules").unwrap();

let cache_groups = vec![
CacheGroup {
key: String::from("framework"),
name: rspack_plugin_split_chunks_new::create_chunk_name_getter_by_const_name("framework".to_string()),
chunk_filter: rspack_plugin_split_chunks_new::create_async_chunk_filter(),
chunk_filter: rspack_plugin_split_chunks_new::create_all_chunk_filter(),
priority: 40.0,
test: rspack_plugin_split_chunks_new::create_module_filter_from_rspack_regex(RspackRegex::new("react|react-dom").unwrap()),
test: Arc::new(move |module: &dyn Module| -> bool {
module
.name_for_condition()
.map_or(false, |name| {
strategy.top_level_frameworks.iter().any(|framework| name.starts_with(framework))
})
}),
max_initial_requests: 25,
max_async_requests: 25,
reuse_existing_chunk: true,
min_chunks: 1,
max_async_requests: 25,
// When enfoce is true, all size should be set to SplitChunkSizes::empty().
min_size: SplitChunkSizes::empty(),
max_async_size: SplitChunkSizes::empty(),
max_initial_size: SplitChunkSizes::empty(),
id_hint: String::from("framework"),
r#type: rspack_plugin_split_chunks_new::create_default_module_type_filter(),
},
CacheGroup {
key: String::from("lib"),
name: Arc::new(move |module| {
let mut hash = RspackHash::new(&HashFunction::Xxhash64);
match module.module_type() {
ModuleType::Css | ModuleType::CssModule | ModuleType::CssAuto => {
module.update_hash(&mut hash);
},
_ => {
let options = rspack_core::LibIdentOptions { context: &context };
let lib_ident = module.lib_ident(options);
hash.write(lib_ident.unwrap().as_bytes());
},
}
future::ready(Some(hash.digest(&HashDigest::Hex).rendered(8).to_string())).boxed()
}),
chunk_filter: rspack_plugin_split_chunks_new::create_all_chunk_filter(),
test: Arc::new(move |module: &dyn Module| -> bool {
module
.name_for_condition()
.map_or(false, |name| re_node_modules.test(&name))
&& get_modules_size(module) > 160000.0
}),
priority: 30.0,
min_chunks: 1,
reuse_existing_chunk: true,
max_initial_requests: 25,
max_async_requests: 25,
min_size: create_sizes(Some(20000.0)),
max_async_size: SplitChunkSizes::default(),
max_initial_size: SplitChunkSizes::default(),
id_hint: String::from("framework"),
id_hint: String::from("lib"),
r#type: rspack_plugin_split_chunks_new::create_default_module_type_filter(),
}
},
];

PluginOptions {
Expand All @@ -67,11 +122,11 @@ fn get_plugin_options(strategy: String) -> rspack_plugin_split_chunks_new::Plugi

pub trait FeatureApply {
type Options;
fn apply(self, plugins: &mut Vec<BoxPlugin>) -> Result<Self::Options, rspack_error::Error>;
fn apply(self, plugins: &mut Vec<BoxPlugin>, context: String) -> Result<Self::Options, rspack_error::Error>;
}

impl SplitChunksStrategy {
pub fn new(strategy: String, option: RawOptimizationOptions) -> Self {
pub fn new(strategy: RawStrategyOptions, option: RawOptimizationOptions) -> Self {
Self {
strategy,
chunk_ids: option.chunk_ids,
Expand All @@ -89,9 +144,9 @@ impl SplitChunksStrategy {
impl FeatureApply for SplitChunksStrategy {
type Options = Optimization;

fn apply(self, plugins: &mut Vec<Box<dyn rspack_core::Plugin>>) -> Result<Self::Options, rspack_error::Error> {
fn apply(self, plugins: &mut Vec<Box<dyn rspack_core::Plugin>>, context: String) -> Result<Self::Options, rspack_error::Error> {
let split_chunks_plugin = rspack_plugin_split_chunks_new::SplitChunksPlugin::new(
get_plugin_options(self.strategy),
get_plugin_options(self.strategy, context),
).boxed();
plugins.push(split_chunks_plugin);

Expand Down Expand Up @@ -128,9 +183,17 @@ impl FeatureApply for SplitChunksStrategy {
}
}

#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
#[napi(object)]
pub struct RawStrategyOptions {
pub name: String,
pub top_level_frameworks: Vec<String>,
}

#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
#[napi(object)]
pub struct RawFeatures {
pub split_chunks_strategy: Option<String>,
pub split_chunks_strategy: Option<RawStrategyOptions>,
}

0 comments on commit 9437bc4

Please sign in to comment.