diff --git a/Cargo.lock b/Cargo.lock index c529e02134df..81d0005f16fd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4189,6 +4189,7 @@ name = "rspack_plugin_asset" version = "0.2.0" dependencies = [ "async-trait", + "cow-utils", "mime_guess", "rayon", "rspack_base64", @@ -4872,8 +4873,6 @@ dependencies = [ [[package]] name = "rspack_sources" version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e6385596f51f7dc3bba9e536870601f084d4851c9544b6b1d11bb58b0494259" dependencies = [ "dashmap 6.1.0", "dyn-clone", diff --git a/Cargo.toml b/Cargo.toml index 55da6222f03d..19c8eff1e5c2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -64,7 +64,7 @@ rayon = { version = "1.10.0" } regex = { version = "1.11.1" } ropey = "1.6.1" rspack_resolver = { version = "0.3.6", features = ["package_json_raw_json_api"] } -rspack_sources = { version = "0.4.1" } +rspack_sources = { version = "0.4.1", path = "/Users/bytedance/Documents/codes/rspack-sources" } rustc-hash = { version = "2.1.0" } serde = { version = "1.0.217" } serde_json = { version = "1.0.134" } diff --git a/crates/node_binding/binding.d.ts b/crates/node_binding/binding.d.ts index 37ae507b5d08..6b0aa3ce08af 100644 --- a/crates/node_binding/binding.d.ts +++ b/crates/node_binding/binding.d.ts @@ -1140,6 +1140,8 @@ export interface RawAssetGeneratorOptions { outputPath?: JsFilename publicPath?: "auto" | JsFilename dataUrl?: RawAssetGeneratorDataUrlOptions | ((source: Buffer, context: RawAssetGeneratorDataUrlFnCtx) => string) + experimentalLibReExport?: boolean + experimentalLibPreserveImport?: boolean } export interface RawAssetInlineGeneratorOptions { @@ -1164,6 +1166,8 @@ export interface RawAssetResourceGeneratorOptions { filename?: JsFilename outputPath?: JsFilename publicPath?: "auto" | JsFilename + experimentalLibPreserveImport?: boolean + experimentalLibReExport?: boolean } export interface RawBannerPluginOptions { diff --git a/crates/rspack_binding_values/src/raw_options/raw_module/mod.rs b/crates/rspack_binding_values/src/raw_options/raw_module/mod.rs index 785f12b274a8..fdc5f2740593 100644 --- a/crates/rspack_binding_values/src/raw_options/raw_module/mod.rs +++ b/crates/rspack_binding_values/src/raw_options/raw_module/mod.rs @@ -533,6 +533,9 @@ pub struct RawAssetGeneratorOptions { ts_type = "RawAssetGeneratorDataUrlOptions | ((source: Buffer, context: RawAssetGeneratorDataUrlFnCtx) => string)" )] pub data_url: Option, + + pub experimental_lib_re_export: Option, + pub experimental_lib_preserve_import: Option, } impl From for AssetGeneratorOptions { @@ -545,6 +548,8 @@ impl From for AssetGeneratorOptions { data_url: value .data_url .map(|i| RawAssetGeneratorDataUrlWrapper(i).into()), + experimental_lib_re_export: value.experimental_lib_re_export, + experimental_lib_preserve_import: value.experimental_lib_preserve_import, } } } @@ -577,6 +582,9 @@ pub struct RawAssetResourceGeneratorOptions { pub output_path: Option, #[napi(ts_type = "\"auto\" | JsFilename")] pub public_path: Option, + + pub experimental_lib_preserve_import: Option, + pub experimental_lib_re_export: Option, } impl From for AssetResourceGeneratorOptions { @@ -586,6 +594,8 @@ impl From for AssetResourceGeneratorOptions { filename: value.filename.map(|i| i.into()), output_path: value.output_path.map(|i| i.into()), public_path: value.public_path.map(|i| i.into()), + experimental_lib_preserve_import: value.experimental_lib_preserve_import, + experimental_lib_re_export: value.experimental_lib_re_export, } } } diff --git a/crates/rspack_core/src/compiler/module_executor/mod.rs b/crates/rspack_core/src/compiler/module_executor/mod.rs index 1d4294b23455..761fd2bfdfc0 100644 --- a/crates/rspack_core/src/compiler/module_executor/mod.rs +++ b/crates/rspack_core/src/compiler/module_executor/mod.rs @@ -249,7 +249,6 @@ impl ModuleExecutor { .expect("should success"); let (execute_result, assets, code_generated_modules, executed_runtime_modules) = rx.await.expect("should receiver success"); - if execute_result.error.is_none() && let Some(original_module_identifier) = original_module_identifier { diff --git a/crates/rspack_core/src/options/module.rs b/crates/rspack_core/src/options/module.rs index e19f7b3d1e05..48d47d07ff56 100644 --- a/crates/rspack_core/src/options/module.rs +++ b/crates/rspack_core/src/options/module.rs @@ -422,6 +422,8 @@ pub struct AssetResourceGeneratorOptions { pub filename: Option, pub output_path: Option, pub public_path: Option, + pub experimental_lib_re_export: Option, + pub experimental_lib_preserve_import: Option, } #[cacheable] @@ -432,6 +434,8 @@ pub struct AssetGeneratorOptions { pub output_path: Option, pub public_path: Option, pub data_url: Option, + pub experimental_lib_re_export: Option, + pub experimental_lib_preserve_import: Option, } pub struct AssetGeneratorDataUrlFnCtx<'a> { diff --git a/crates/rspack_plugin_asset/Cargo.toml b/crates/rspack_plugin_asset/Cargo.toml index a4a641a01cdc..21147684c397 100644 --- a/crates/rspack_plugin_asset/Cargo.toml +++ b/crates/rspack_plugin_asset/Cargo.toml @@ -8,19 +8,20 @@ version = "0.2.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -async-trait = { workspace = true } -mime_guess = { workspace = true } -rayon = { workspace = true } -rspack_base64 = { workspace = true } +async-trait = { workspace = true } +cow-utils = { workspace = true } +mime_guess = { workspace = true } +rayon = { workspace = true } +rspack_base64 = { workspace = true } rspack_cacheable = { workspace = true } -rspack_core = { workspace = true } -rspack_error = { workspace = true } -rspack_hash = { workspace = true } -rspack_hook = { workspace = true } -rspack_util = { workspace = true } -serde_json = { workspace = true } -tracing = { workspace = true } -urlencoding = { workspace = true } +rspack_core = { workspace = true } +rspack_error = { workspace = true } +rspack_hash = { workspace = true } +rspack_hook = { workspace = true } +rspack_util = { workspace = true } +serde_json = { workspace = true } +tracing = { workspace = true } +urlencoding = { workspace = true } [package.metadata.cargo-shear] ignored = ["tracing"] diff --git a/crates/rspack_plugin_asset/src/lib.rs b/crates/rspack_plugin_asset/src/lib.rs index 493b6310e201..3eb5e20c3c36 100644 --- a/crates/rspack_plugin_asset/src/lib.rs +++ b/crates/rspack_plugin_asset/src/lib.rs @@ -3,10 +3,12 @@ use std::{borrow::Cow, hash::Hasher, path::PathBuf}; use async_trait::async_trait; +use cow_utils::CowUtils; use rayon::prelude::*; use rspack_cacheable::{cacheable, cacheable_dyn}; use rspack_core::{ - rspack_sources::{BoxSource, RawBufferSource, RawStringSource, SourceExt}, + get_js_chunk_filename_template, + rspack_sources::{BoxSource, CachedSource, RawBufferSource, RawStringSource, SourceExt}, AssetGeneratorDataUrl, AssetGeneratorDataUrlFnCtx, AssetInfo, AssetParserDataUrl, BuildMetaDefaultObject, BuildMetaExportsType, ChunkGraph, ChunkUkey, CodeGenerationDataAssetInfo, CodeGenerationDataFilename, CodeGenerationDataUrl, Compilation, CompilationRenderManifest, @@ -20,6 +22,8 @@ use rspack_hash::{RspackHash, RspackHashDigest}; use rspack_hook::{plugin, plugin_hook}; use rspack_util::{ext::DynHash, identifier::make_paths_relative}; +pub const AUTO_PUBLIC_PATH_PLACEHOLDER: &str = "__RSPACK_PLUGIN_ASSET_AUTO_PUBLIC_PATH__"; + #[plugin] #[derive(Debug, Default)] pub struct AssetPlugin; @@ -434,7 +438,6 @@ impl ParserAndGenerator for AssetParserAndGenerator { let exported_content = if parsed_asset_config.is_inline() { let resource_data: &ResourceData = normal_module.resource_resolved_data(); let data_url = module_generator_options.and_then(|x| x.asset_data_url()); - let encoded_source: String; if let Some(custom_data_url) = @@ -524,6 +527,61 @@ impl ParserAndGenerator for AssetParserAndGenerator { } else { unreachable!() }; + + let experimental_lib_preserve_import = module_generator_options + .and_then(|x| x.get_asset()) + .and_then(|x| x.experimental_lib_preserve_import) + .or_else(|| { + module_generator_options + .and_then(|x| x.get_asset_resource()) + .and_then(|x| x.experimental_lib_preserve_import) + }) + .unwrap_or(false); + let experimental_lib_re_export = module_generator_options + .and_then(|x| x.get_asset()) + .and_then(|x| x.experimental_lib_re_export) + .or_else(|| { + module_generator_options + .and_then(|x| x.get_asset_resource()) + .and_then(|x| x.experimental_lib_re_export) + }) + .unwrap_or(false); + + if experimental_lib_preserve_import || experimental_lib_re_export { + if module_generator_options + .and_then(|x| x.asset_public_path()) + .is_some() + { + if let Some(ref mut scope) = generate_context.concatenation_scope { + scope.register_namespace_export(NAMESPACE_OBJECT_EXPORT); + return Ok(if experimental_lib_re_export { + // RawStringSource::from(format!( + // r#"import {NAMESPACE_OBJECT_EXPORT} from {exported_content}; + // export default {NAMESPACE_OBJECT_EXPORT};"# + // )) + RawStringSource::from(format!( + r#"import {NAMESPACE_OBJECT_EXPORT} from {exported_content}; + export default {NAMESPACE_OBJECT_EXPORT};"# + )) + .boxed() + } else { + RawStringSource::from(format!( + r#"import {NAMESPACE_OBJECT_EXPORT} from {exported_content};"# + )) + .boxed() + }); + } else { + return Ok( + RawStringSource::from(format!( + r#" + export default {exported_content};"# + )) + .boxed(), + ); + } + }; + } + if let Some(ref mut scope) = generate_context.concatenation_scope { scope.register_namespace_export(NAMESPACE_OBJECT_EXPORT); let supports_const = compilation.options.output.environment.supports_const(); @@ -619,7 +677,7 @@ async fn render_manifest( compilation: &Compilation, chunk_ukey: &ChunkUkey, manifest: &mut Vec, - _diagnostics: &mut Vec, + diagnostics: &mut Vec, ) -> Result<()> { let chunk = compilation.chunk_by_ukey.expect_get(chunk_ukey); let module_graph = compilation.get_module_graph(); @@ -648,6 +706,7 @@ async fn render_manifest( .get::() .expect("should have asset_info") .inner(); + RenderManifestEntry { source: source.clone(), filename: asset_filename.to_owned(), @@ -665,9 +724,78 @@ async fn render_manifest( .collect::>(); manifest.extend(assets); + + // let (source, more_diagnostics) = compilation + // .old_cache + // .chunk_render_occasion + // .use_cache(compilation, chunk, &SourceType::JavaScript, || async { + // let source = render_chunk(compilation, chunk_ukey).await?; + // Ok((CachedSource::new(source).boxed(), Vec::new())) + // }) + // .await?; + + // diagnostics.extend(more_diagnostics); + // manifest.push(RenderManifestEntry { + // source: source.boxed(), + // filename: output_path, + // has_filename: false, + // info: asset_info, + // auxiliary: false, + // }); + Ok(()) } +// pub async fn render_chunk(compilation: &Compilation, chunk_ukey: &ChunkUkey) -> Result { +// let chunk = compilation.chunk_by_ukey.expect_get(chunk_ukey); +// let module_graph = compilation.get_module_graph(); +// let chunk_graph = &compilation.chunk_graph; + +// let ordered_modules = +// chunk_graph.get_chunk_modules_by_source_type(chunk_ukey, SourceType::JavaScript, &module_graph); + +// let mut source = String::new(); +// for module in ordered_modules { +// let code_gen_result = compilation +// .code_generation_results +// .get(&module.identifier(), Some(chunk.runtime())); + +// let result = code_gen_result +// .get(&SourceType::JavaScript) +// .map(|source| source.source()); +// source += &result.unwrap_or_default(); +// } +// let filename_template = get_js_chunk_filename_template( +// chunk, +// &compilation.options.output, +// &compilation.chunk_group_by_ukey, +// ); + +// let mut asset_info = AssetInfo::default(); +// let output_path = compilation.get_path_with_info( +// &filename_template, +// PathData::default() +// .chunk_id_optional(chunk.id(&compilation.chunk_ids).map(|id| id.as_str())) +// .chunk_hash_optional(chunk.rendered_hash( +// &compilation.chunk_hashes_results, +// compilation.options.output.hash_digest_length, +// )) +// .chunk_name_optional(chunk.name_for_filename_template(&compilation.chunk_ids)) +// .content_hash_optional(chunk.rendered_content_hash_by_source_type( +// &compilation.chunk_hashes_results, +// &SourceType::Css, +// compilation.options.output.hash_digest_length, +// )) +// .runtime(chunk.runtime().as_str()), +// &mut asset_info, +// )?; + +// let undo_path = PublicPath::render_auto_public_path(compilation, &output_path); +// source.cow_replace(AUTO_PUBLIC_PATH_PLACEHOLDER, &undo_path); + +// Ok(RawStringSource::from(source).boxed()) +// } + #[async_trait] impl Plugin for AssetPlugin { fn name(&self) -> &'static str { @@ -703,6 +831,12 @@ impl Plugin for AssetPlugin { }), ); + // ctx + // .context + // .compilation_hooks + // .render_manifest + // .tap(render_manifest::new(self)); + ctx.context.register_parser_and_generator_builder( rspack_core::ModuleType::AssetInline, Box::new(|_, _| Box::new(AssetParserAndGenerator::with_inline())), diff --git a/crates/rspack_plugin_javascript/src/plugin/mod.rs b/crates/rspack_plugin_javascript/src/plugin/mod.rs index abaecb6503a6..2d08e9e4a1e1 100644 --- a/crates/rspack_plugin_javascript/src/plugin/mod.rs +++ b/crates/rspack_plugin_javascript/src/plugin/mod.rs @@ -1142,6 +1142,7 @@ impl JsPlugin { let (chunk_modules_source, chunk_init_fragments) = render_chunk_modules(compilation, chunk_ukey, &chunk_modules, all_strict)? .unwrap_or_else(|| (RawStringSource::from_static("{}").boxed(), Vec::new())); + let mut render_source = RenderSource { source: chunk_modules_source, }; diff --git a/crates/rspack_plugin_javascript/src/plugin/module_concatenation_plugin.rs b/crates/rspack_plugin_javascript/src/plugin/module_concatenation_plugin.rs index ceac4894f526..45651a133f6f 100644 --- a/crates/rspack_plugin_javascript/src/plugin/module_concatenation_plugin.rs +++ b/crates/rspack_plugin_javascript/src/plugin/module_concatenation_plugin.rs @@ -555,6 +555,9 @@ impl ModuleConcatenationPlugin { let box_module = module_graph .module_by_identifier(&root_module_id) .expect("should have module"); + let root_module_source_types = box_module.source_types(); + let is_root_module_asset_module = root_module_source_types.contains(&SourceType::Asset); + let root_module_ctxt = RootModuleContext { id: root_module_id, readable_identifier: box_module @@ -677,8 +680,26 @@ impl ModuleConcatenationPlugin { // .module_identifier_to_module // .remove(&root_module_id); // compilation.chunk_graph.clear + if is_root_module_asset_module { + chunk_graph.replace_module(&root_module_id, &new_module.id()); + chunk_graph.add_module(root_module_id); + for chunk_ukey in chunk_graph.get_module_chunks(new_module.id()).clone() { + let module = module_graph + .module_by_identifier(&root_module_id) + .expect("should exist module"); - chunk_graph.replace_module(&root_module_id, &new_module.id()); + let source_types = chunk_graph.get_chunk_module_source_types(&chunk_ukey, module); + let new_source_types = source_types + .iter() + .filter(|source_type| !matches!(source_type, SourceType::JavaScript)) + .copied() + .collect(); + chunk_graph.set_chunk_modules_source_types(&chunk_ukey, root_module_id, new_source_types); + chunk_graph.connect_chunk_and_module(chunk_ukey, root_module_id); + } + } else { + chunk_graph.replace_module(&root_module_id, &new_module.id()); + } module_graph.move_module_connections(&root_module_id, &new_module.id(), |c, dep| { let other_module = if *c.module_identifier() == root_module_id { diff --git a/packages/rspack/etc/core.api.md b/packages/rspack/etc/core.api.md index 3b7e49c10aa2..f5e83b510a1b 100644 --- a/packages/rspack/etc/core.api.md +++ b/packages/rspack/etc/core.api.md @@ -203,6 +203,8 @@ export type AssetResourceGeneratorOptions = { filename?: Filename; outputPath?: AssetModuleOutputPath; publicPath?: PublicPath; + experimentalLibReExport?: boolean; + experimentalLibPreserveImport?: boolean; }; // @public (undocumented) diff --git a/packages/rspack/src/config/adapter.ts b/packages/rspack/src/config/adapter.ts index f41be2bbc483..f112b0978321 100644 --- a/packages/rspack/src/config/adapter.ts +++ b/packages/rspack/src/config/adapter.ts @@ -670,7 +670,9 @@ function getRawAssetResourceGeneratorOptions( emit: options.emit, filename: options.filename, outputPath: options.outputPath, - publicPath: options.publicPath + publicPath: options.publicPath, + experimentalLibReExport: options.experimentalLibReExport, + experimentalLibPreserveImport: options.experimentalLibPreserveImport }; } diff --git a/packages/rspack/src/config/types.ts b/packages/rspack/src/config/types.ts index d2eed638882d..3c02ad1fba9d 100644 --- a/packages/rspack/src/config/types.ts +++ b/packages/rspack/src/config/types.ts @@ -1157,6 +1157,11 @@ export type AssetResourceGeneratorOptions = { /** This option determines the URL prefix of the referenced 'asset' or 'asset/resource'*/ publicPath?: PublicPath; + + /** */ + experimentalLibReExport?: boolean; + /** */ + experimentalLibPreserveImport?: boolean; }; /** Generator options for asset modules. */