Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support module.generator.outputPath #8554

Merged
merged 1 commit into from
Dec 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions crates/node_binding/binding.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1111,6 +1111,7 @@ export interface RawAssetGeneratorDataUrlOptions {
export interface RawAssetGeneratorOptions {
emit?: boolean
filename?: JsFilename
outputPath?: JsFilename
publicPath?: "auto" | JsFilename
dataUrl?: RawAssetGeneratorDataUrlOptions | ((arg: RawAssetGeneratorDataUrlFnArgs) => string)
}
Expand All @@ -1135,6 +1136,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 @@ -497,6 +497,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>,
#[derivative(Debug = "ignore")]
Expand All @@ -511,6 +512,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 @@ -545,6 +547,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 @@ -554,6 +557,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 @@ -334,6 +334,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 @@ -371,6 +382,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 @@ -379,6 +391,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 @@ -241,22 +241,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 @@ -444,12 +460,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 @@ -469,13 +486,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 @@ -562,12 +583,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 @@ -179,6 +179,9 @@ export type AssetInlineGeneratorOptions = {
// @public
export type AssetModuleFilename = Filename;

// @public
export type AssetModuleOutputPath = Filename;

// @public
export type AssetParserDataUrl = AssetParserDataUrlOptions;

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

Expand Down Expand Up @@ -5242,6 +5246,7 @@ declare namespace rspackExports {
AssetGeneratorDataUrlFunction,
AssetGeneratorDataUrl,
AssetInlineGeneratorOptions,
AssetModuleOutputPath,
AssetResourceGeneratorOptions,
AssetGeneratorOptions,
CssGeneratorExportsConvention,
Expand Down Expand Up @@ -10369,6 +10374,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 @@ -813,6 +813,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 @@ -1125,6 +1125,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 @@ -1136,6 +1139,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
Loading