Skip to content

Commit

Permalink
feat: support module.generator.outputPath (#8554)
Browse files Browse the repository at this point in the history
  • Loading branch information
inottn authored Dec 17, 2024
1 parent aab2eb7 commit 61f0cd2
Show file tree
Hide file tree
Showing 10 changed files with 96 additions and 17 deletions.
2 changes: 2 additions & 0 deletions crates/node_binding/binding.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1126,6 +1126,7 @@ export interface RawAssetGeneratorDataUrlOptions {
export interface RawAssetGeneratorOptions {
emit?: boolean
filename?: JsFilename
outputPath?: JsFilename
publicPath?: "auto" | JsFilename
dataUrl?: RawAssetGeneratorDataUrlOptions | ((source: Buffer, context: RawAssetGeneratorDataUrlFnCtx) => string)
}
Expand All @@ -1150,6 +1151,7 @@ export interface RawAssetParserOptions {
export interface RawAssetResourceGeneratorOptions {
emit?: boolean
filename?: JsFilename
outputPath?: JsFilename
publicPath?: "auto" | JsFilename
}

Expand Down
4 changes: 4 additions & 0 deletions crates/rspack_binding_options/src/options/raw_module/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -496,6 +496,7 @@ impl From<RawGeneratorOptions> for GeneratorOptions {
pub struct RawAssetGeneratorOptions {
pub emit: Option<bool>,
pub filename: Option<JsFilename>,
pub output_path: Option<JsFilename>,
#[napi(ts_type = "\"auto\" | JsFilename")]
pub public_path: Option<JsFilename>,
#[debug(skip)]
Expand All @@ -510,6 +511,7 @@ impl From<RawAssetGeneratorOptions> for AssetGeneratorOptions {
Self {
emit: value.emit,
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()),
data_url: value
.data_url
Expand Down Expand Up @@ -543,6 +545,7 @@ impl From<RawAssetInlineGeneratorOptions> for AssetInlineGeneratorOptions {
pub struct RawAssetResourceGeneratorOptions {
pub emit: Option<bool>,
pub filename: Option<JsFilename>,
pub output_path: Option<JsFilename>,
#[napi(ts_type = "\"auto\" | JsFilename")]
pub public_path: Option<JsFilename>,
}
Expand All @@ -552,6 +555,7 @@ impl From<RawAssetResourceGeneratorOptions> for AssetResourceGeneratorOptions {
Self {
emit: value.emit,
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()),
}
}
Expand Down
13 changes: 13 additions & 0 deletions crates/rspack_core/src/options/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,17 @@ impl GeneratorOptions {
.or_else(|| self.get_asset_resource().and_then(|x| x.filename.as_ref()))
}

pub fn asset_output_path(&self) -> Option<&Filename> {
self
.get_asset()
.and_then(|x| x.output_path.as_ref())
.or_else(|| {
self
.get_asset_resource()
.and_then(|x| x.output_path.as_ref())
})
}

pub fn asset_public_path(&self) -> Option<&PublicPath> {
self
.get_asset()
Expand Down Expand Up @@ -370,6 +381,7 @@ pub struct AssetInlineGeneratorOptions {
pub struct AssetResourceGeneratorOptions {
pub emit: Option<bool>,
pub filename: Option<Filename>,
pub output_path: Option<Filename>,
pub public_path: Option<PublicPath>,
}

Expand All @@ -378,6 +390,7 @@ pub struct AssetResourceGeneratorOptions {
pub struct AssetGeneratorOptions {
pub emit: Option<bool>,
pub filename: Option<Filename>,
pub output_path: Option<Filename>,
pub public_path: Option<PublicPath>,
pub data_url: Option<AssetGeneratorDataUrl>,
}
Expand Down
54 changes: 38 additions & 16 deletions crates/rspack_plugin_asset/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#![feature(let_chains)]

use std::{borrow::Cow, hash::Hasher};
use std::{borrow::Cow, hash::Hasher, path::PathBuf};

use async_trait::async_trait;
use rayon::prelude::*;
Expand Down Expand Up @@ -242,22 +242,38 @@ impl AssetParserAndGenerator {
compilation: &Compilation,
contenthash: Option<&str>,
source_file_name: &str,
) -> Result<(String, AssetInfo)> {
use_output_path: bool,
) -> Result<(String, String, AssetInfo)> {
// Use [Rule.generator.filename] if it is set, otherwise use [output.assetModuleFilename].
let asset_filename_template = module_generator_options
.and_then(|x| x.asset_filename())
.unwrap_or(&compilation.options.output.asset_module_filename);
let path_data = PathData::default()
.module_id_optional(
ChunkGraph::get_module_id(&compilation.module_ids, module.id()).map(|s| s.as_str()),
)
.content_hash_optional(contenthash)
.hash_optional(contenthash)
.filename(source_file_name);

let (mut filename, mut asset_info) =
compilation.get_asset_path_with_info(asset_filename_template, path_data)?;
let original_filename = filename.clone();

if use_output_path {
let output_path = module_generator_options.and_then(|x| x.asset_output_path());

if let Some(output_path) = output_path {
let (output_path, another_asset_info) =
compilation.get_asset_path_with_info(output_path, path_data)?;
let output_path = PathBuf::from(output_path);
let file_path = PathBuf::from(filename);
filename = output_path.join(file_path).to_string_lossy().to_string();
asset_info.merge_another_asset(another_asset_info);
}
}

compilation.get_asset_path_with_info(
asset_filename_template,
PathData::default()
.module_id_optional(
ChunkGraph::get_module_id(&compilation.module_ids, module.id()).map(|s| s.as_str()),
)
.content_hash_optional(contenthash)
.hash_optional(contenthash)
.filename(source_file_name),
)
Ok((original_filename, filename, asset_info))
}

fn get_public_path<F: LocalFilenameFn>(
Expand Down Expand Up @@ -447,12 +463,13 @@ impl ParserAndGenerator for AssetParserAndGenerator {
let contenthash = contenthash.rendered(compilation.options.output.hash_digest_length);

let source_file_name = self.get_source_file_name(normal_module, compilation);
let (filename, mut asset_info) = self.get_asset_module_filename(
let (original_filename, filename, mut asset_info) = self.get_asset_module_filename(
normal_module,
module_generator_options,
compilation,
Some(contenthash),
&source_file_name,
true,
)?;

let asset_path = if let Some(public_path) =
Expand All @@ -472,13 +489,17 @@ impl ParserAndGenerator for AssetParserAndGenerator {
}
PublicPath::Auto => public_path.render(compilation, &filename),
};
serde_json::to_string(&format!("{public_path}{filename}"))
serde_json::to_string(&format!("{public_path}{original_filename}"))
.map_err(|e| error!(e.to_string()))?
} else {
generate_context
.runtime_requirements
.insert(RuntimeGlobals::PUBLIC_PATH);
format!(r#"{} + "{}""#, RuntimeGlobals::PUBLIC_PATH, filename)
format!(
r#"{} + "{}""#,
RuntimeGlobals::PUBLIC_PATH,
original_filename
)
};
asset_info.set_source_filename(source_file_name);

Expand Down Expand Up @@ -565,12 +586,13 @@ impl ParserAndGenerator for AssetParserAndGenerator {
data_url_options.dyn_hash(hasher);
} else if parsed_asset_config.is_resource() {
let source_file_name = self.get_source_file_name(module, compilation);
let (filename, _) = self.get_asset_module_filename(
let (filename, _, _) = self.get_asset_module_filename(
module,
module_generator_options,
compilation,
None,
&source_file_name,
false,
)?;
filename.dyn_hash(hasher);
match module_generator_options.and_then(|x| x.asset_public_path()) {
Expand Down
6 changes: 6 additions & 0 deletions packages/rspack/etc/core.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,9 @@ export type AssetInlineGeneratorOptions = {
// @public
export type AssetModuleFilename = Filename;

// @public
export type AssetModuleOutputPath = Filename;

// @public
export type AssetParserDataUrl = AssetParserDataUrlOptions;

Expand All @@ -198,6 +201,7 @@ export type AssetParserOptions = {
export type AssetResourceGeneratorOptions = {
emit?: boolean;
filename?: Filename;
outputPath?: AssetModuleOutputPath;
publicPath?: PublicPath;
};

Expand Down Expand Up @@ -5316,6 +5320,7 @@ declare namespace rspackExports {
AssetGeneratorDataUrlFunction,
AssetGeneratorDataUrl,
AssetInlineGeneratorOptions,
AssetModuleOutputPath,
AssetResourceGeneratorOptions,
AssetGeneratorOptions,
CssGeneratorExportsConvention,
Expand Down Expand Up @@ -10460,6 +10465,7 @@ declare namespace t {
AssetGeneratorDataUrlFunction,
AssetGeneratorDataUrl,
AssetInlineGeneratorOptions,
AssetModuleOutputPath,
AssetResourceGeneratorOptions,
AssetGeneratorOptions,
CssGeneratorExportsConvention,
Expand Down
1 change: 1 addition & 0 deletions packages/rspack/src/config/adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -815,6 +815,7 @@ function getRawAssetResourceGeneratorOptions(
return {
emit: options.emit,
filename: options.filename,
outputPath: options.outputPath,
publicPath: options.publicPath
};
}
Expand Down
6 changes: 6 additions & 0 deletions packages/rspack/src/config/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1128,6 +1128,9 @@ export type AssetInlineGeneratorOptions = {
dataUrl?: AssetGeneratorDataUrl;
};

/** Emit the asset in the specified folder relative to 'output.path'. */
export type AssetModuleOutputPath = Filename;

/** Options for asset modules. */
export type AssetResourceGeneratorOptions = {
/**
Expand All @@ -1139,6 +1142,9 @@ export type AssetResourceGeneratorOptions = {
/** This option determines the name of each asset resource output bundle.*/
filename?: Filename;

/** Emit the asset in the specified folder relative to 'output.path' */
outputPath?: AssetModuleOutputPath;

/** This option determines the URL prefix of the referenced 'asset' or 'asset/resource'*/
publicPath?: PublicPath;
};
Expand Down

This file was deleted.

13 changes: 13 additions & 0 deletions website/docs/en/config/module.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -506,6 +506,15 @@ module.exports = {
};
```

#### module.generator.asset.outputPath

- **Type:** `string | ((pathData: PathData, assetInfo?: AssetInfo) => string)`
- **Default:** `undefined`

Emit the asset in the specified folder relative to [`output.path`](/config/output#outputpath).

Only for modules with module type `'asset'` or `'asset/resource'`.

#### module.generator.asset.publicPath

- **Type:** `string | ((pathData: PathData, assetInfo?: AssetInfo) => string)`
Expand Down Expand Up @@ -586,6 +595,10 @@ Generator options for `asset/resource` modules.

Same as [`module.generator["asset"].filename`](#modulegeneratorassetfilename).

#### module.generator["asset/resource"].outputPath

Same as [`module.generator["asset"].outputPath`](#modulegeneratorassetoutputpath).

#### module.generator["asset/resource"].publicPath

Same as [`module.generator["asset"].publicPath`](#modulegeneratorassetpublicpath).
Expand Down
13 changes: 13 additions & 0 deletions website/docs/zh/config/module.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -506,6 +506,15 @@ module.exports = {
};
```

#### module.generator.asset.outputPath

- **类型:** `string | ((pathData: PathData, assetInfo?: AssetInfo) => string)`
- **默认值:** `undefined`

将 asset 输出到指定文件夹,该文件夹相对于 [`output.path`](/config/output#outputpath)

仅对模块类型为 `'asset'``'asset/resource'` 的模块生效。

#### module.generator.asset.publicPath

- **类型:** `string | ((pathData: PathData, assetInfo?: AssetInfo) => string)`
Expand Down Expand Up @@ -586,6 +595,10 @@ module.exports = {

[`module.generator["asset"].filename`](#modulegeneratorassetfilename) 一样。

#### module.generator["asset/resource"].outputPath

[`module.generator["asset"].outputPath`](#modulegeneratorassetoutputpath) 一样。

#### module.generator["asset/resource"].publicPath

[`module.generator["asset"].publicPath`](#modulegeneratorassetpublicpath) 一样。
Expand Down

2 comments on commit 61f0cd2

@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-17 fb2869d) Current Change
10000_big_production-mode_disable-minimize + exec 37.9 s ± 622 ms 38 s ± 492 ms +0.36 %
10000_development-mode + exec 1.87 s ± 24 ms 1.83 s ± 33 ms -2.32 %
10000_development-mode_hmr + exec 687 ms ± 28 ms 687 ms ± 47 ms -0.12 %
10000_production-mode + exec 2.47 s ± 48 ms 2.37 s ± 28 ms -3.95 %
arco-pro_development-mode + exec 1.77 s ± 90 ms 1.75 s ± 94 ms -0.98 %
arco-pro_development-mode_hmr + exec 379 ms ± 1.6 ms 377 ms ± 1.4 ms -0.41 %
arco-pro_production-mode + exec 3.31 s ± 75 ms 3.29 s ± 69 ms -0.69 %
arco-pro_production-mode_generate-package-json-webpack-plugin + exec 3.37 s ± 152 ms 3.32 s ± 102 ms -1.64 %
arco-pro_production-mode_traverse-chunk-modules + exec 3.34 s ± 124 ms 3.32 s ± 121 ms -0.71 %
threejs_development-mode_10x + exec 1.61 s ± 20 ms 1.6 s ± 16 ms -0.70 %
threejs_development-mode_10x_hmr + exec 794 ms ± 28 ms 793 ms ± 28 ms -0.12 %
threejs_production-mode_10x + exec 5.42 s ± 141 ms 5.39 s ± 97 ms -0.44 %
10000_big_production-mode_disable-minimize + rss memory 9482 MiB ± 276 MiB 9661 MiB ± 294 MiB +1.89 %
10000_development-mode + rss memory 633 MiB ± 14.8 MiB 692 MiB ± 39.7 MiB +9.23 %
10000_development-mode_hmr + rss memory 1396 MiB ± 296 MiB 1533 MiB ± 343 MiB +9.77 %
10000_production-mode + rss memory 601 MiB ± 31.9 MiB 677 MiB ± 27.1 MiB +12.66 %
arco-pro_development-mode + rss memory 587 MiB ± 40.3 MiB 621 MiB ± 28.8 MiB +5.73 %
arco-pro_development-mode_hmr + rss memory 639 MiB ± 102 MiB 648 MiB ± 38.2 MiB +1.40 %
arco-pro_production-mode + rss memory 742 MiB ± 50.5 MiB 751 MiB ± 69.7 MiB +1.28 %
arco-pro_production-mode_generate-package-json-webpack-plugin + rss memory 737 MiB ± 45.5 MiB 767 MiB ± 33 MiB +4.06 %
arco-pro_production-mode_traverse-chunk-modules + rss memory 720 MiB ± 58.3 MiB 770 MiB ± 65.2 MiB +6.85 %
threejs_development-mode_10x + rss memory 638 MiB ± 22.2 MiB 696 MiB ± 54.9 MiB +9.11 %
threejs_development-mode_10x_hmr + rss memory 1194 MiB ± 248 MiB 1226 MiB ± 191 MiB +2.68 %
threejs_production-mode_10x + rss memory 948 MiB ± 55 MiB 982 MiB ± 92.3 MiB +3.60 %

Please sign in to comment.