Skip to content

Commit

Permalink
feat(html): support js template without child compiler (#7704)
Browse files Browse the repository at this point in the history
  • Loading branch information
LingyuCoder authored Aug 28, 2024
1 parent 67917b1 commit dc30af1
Show file tree
Hide file tree
Showing 13 changed files with 698 additions and 365 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

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

3 changes: 2 additions & 1 deletion crates/node_binding/binding.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1239,8 +1239,9 @@ export interface RawHtmlRspackPluginOptions {
filename?: string
/** template html file */
template?: string
templateFn?: (data: string) => Promise<string>
templateContent?: string
templateParameters?: Record<string, string>
templateParameters?: boolean | Record<string, any> | ((params: string) => Promise<string>)
/** "head", "body" or "false" */
inject: "head" | "body" | "false"
/** path or `auto` */
Expand Down
43 changes: 40 additions & 3 deletions crates/rspack_binding_options/src/options/raw_builtins/raw_html.rs
Original file line number Diff line number Diff line change
@@ -1,28 +1,41 @@
use std::collections::HashMap;
use std::str::FromStr;

use napi::bindgen_prelude::Either3;
use napi_derive::napi;
use rspack_napi::threadsafe_function::ThreadsafeFunction;
use rspack_plugin_html::config::HtmlInject;
use rspack_plugin_html::config::HtmlRspackPluginBaseOptions;
use rspack_plugin_html::config::HtmlRspackPluginOptions;
use rspack_plugin_html::config::HtmlScriptLoading;
use rspack_plugin_html::config::TemplateParameterFn;
use rspack_plugin_html::config::TemplateParameters;
use rspack_plugin_html::config::TemplateRenderFn;
use rspack_plugin_html::sri::HtmlSriHashFunction;

pub type RawHtmlScriptLoading = String;
pub type RawHtmlInject = String;
pub type RawHtmlSriHashFunction = String;
pub type RawHtmlFilename = String;

type RawTemplateRenderFn = ThreadsafeFunction<String, String>;

type RawTemplateParameter =
Either3<HashMap<String, String>, bool, ThreadsafeFunction<String, String>>;

#[derive(Debug)]
#[napi(object)]
#[napi(object, object_to_js = false)]
pub struct RawHtmlRspackPluginOptions {
/// emitted file name in output path
#[napi(ts_type = "string")]
pub filename: Option<RawHtmlFilename>,
/// template html file
pub template: Option<String>,
#[napi(ts_type = "(data: string) => Promise<string>")]
pub template_fn: Option<RawTemplateRenderFn>,
pub template_content: Option<String>,
pub template_parameters: Option<HashMap<String, String>>,
#[napi(ts_type = "boolean | Record<string, any> | ((params: string) => Promise<string>)")]
pub template_parameters: Option<RawTemplateParameter>,
/// "head", "body" or "false"
#[napi(ts_type = "\"head\" | \"body\" | \"false\"")]
pub inject: RawHtmlInject,
Expand Down Expand Up @@ -59,8 +72,32 @@ impl From<RawHtmlRspackPluginOptions> for HtmlRspackPluginOptions {
HtmlRspackPluginOptions {
filename: value.filename.unwrap_or_else(|| String::from("index.html")),
template: value.template,
template_fn: value.template_fn.map(|func| TemplateRenderFn {
inner: Box::new(move |data| {
let f = func.clone();
Box::pin(async move { f.call(data).await })
}),
}),
template_content: value.template_content,
template_parameters: value.template_parameters,
template_parameters: match value.template_parameters {
Some(parameters) => match parameters {
Either3::A(data) => TemplateParameters::Map(data),
Either3::B(enabled) => {
if enabled {
TemplateParameters::Map(Default::default())
} else {
TemplateParameters::Disabled
}
}
Either3::C(func) => TemplateParameters::Function(TemplateParameterFn {
inner: Box::new(move |data| {
let f = func.clone();
Box::pin(async move { f.call(data).await })
}),
}),
},
None => TemplateParameters::Map(Default::default()),
},
inject,
public_path: value.public_path,
script_loading,
Expand Down
1 change: 1 addition & 0 deletions crates/rspack_plugin_html/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ default = []

[dependencies]
anyhow = { workspace = true }
futures = { workspace = true }
itertools = { workspace = true }
path-clean = { workspace = true }
rayon = { workspace = true }
Expand Down
43 changes: 41 additions & 2 deletions crates/rspack_plugin_html/src/config.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use std::{collections::HashMap, path::PathBuf, str::FromStr};

use futures::future::BoxFuture;
use rspack_core::{Compilation, PublicPath};
use rspack_error::Result;
use serde::Serialize;
use sugar_path::SugarPath;

Expand Down Expand Up @@ -62,13 +64,46 @@ impl FromStr for HtmlScriptLoading {
}
}

type TemplateParameterTsfn =
Box<dyn for<'a> Fn(String) -> BoxFuture<'static, Result<String>> + Sync + Send>;

pub struct TemplateParameterFn {
pub inner: TemplateParameterTsfn,
}

impl std::fmt::Debug for TemplateParameterFn {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("TemplateParameterFn").finish()
}
}

#[derive(Debug)]
pub enum TemplateParameters {
Map(HashMap<String, String>),
Function(TemplateParameterFn),
Disabled,
}

#[derive(Serialize, Debug)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct HtmlRspackPluginBaseOptions {
pub href: Option<String>,
pub target: Option<String>,
}

type TemplateRenderTsfn =
Box<dyn for<'a> Fn(String) -> BoxFuture<'static, Result<String>> + Sync + Send>;

pub struct TemplateRenderFn {
pub inner: TemplateRenderTsfn,
}

impl std::fmt::Debug for TemplateRenderFn {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("TemplateRenderFn").finish()
}
}

#[derive(Serialize, Debug)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct HtmlRspackPluginOptions {
Expand All @@ -77,8 +112,11 @@ pub struct HtmlRspackPluginOptions {
pub filename: String,
/// template html file
pub template: Option<String>,
#[serde(skip)]
pub template_fn: Option<TemplateRenderFn>,
pub template_content: Option<String>,
pub template_parameters: Option<HashMap<String, String>>,
#[serde(skip)]
pub template_parameters: TemplateParameters,
/// `head`, `body`, `false`
#[serde(default = "default_inject")]
pub inject: HtmlInject,
Expand Down Expand Up @@ -121,8 +159,9 @@ impl Default for HtmlRspackPluginOptions {
HtmlRspackPluginOptions {
filename: default_filename(),
template: None,
template_fn: None,
template_content: None,
template_parameters: None,
template_parameters: TemplateParameters::Map(Default::default()),
inject: default_inject(),
public_path: None,
script_loading: default_script_loading(),
Expand Down
Loading

2 comments on commit dc30af1

@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-08-28 4757b35) Current Change
10000_development-mode + exec 2.29 s ± 36 ms 2.3 s ± 33 ms +0.80 %
10000_development-mode_hmr + exec 704 ms ± 11 ms 695 ms ± 6.4 ms -1.33 %
10000_production-mode + exec 2.97 s ± 36 ms 2.95 s ± 51 ms -0.60 %
arco-pro_development-mode + exec 1.88 s ± 77 ms 1.9 s ± 90 ms +0.88 %
arco-pro_development-mode_hmr + exec 436 ms ± 4.4 ms 435 ms ± 2 ms -0.12 %
arco-pro_production-mode + exec 3.44 s ± 95 ms 3.47 s ± 74 ms +0.61 %
arco-pro_production-mode_generate-package-json-webpack-plugin + exec 3.51 s ± 87 ms 3.48 s ± 76 ms -0.89 %
threejs_development-mode_10x + exec 1.69 s ± 17 ms 1.68 s ± 20 ms -0.26 %
threejs_development-mode_10x_hmr + exec 818 ms ± 11 ms 815 ms ± 9.7 ms -0.38 %
threejs_production-mode_10x + exec 5.5 s ± 25 ms 5.49 s ± 25 ms -0.11 %

@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 ✅ success
_selftest ✅ success
nx ❌ failure
rspress ✅ success
rslib ❌ failure
rsbuild ✅ success
examples ✅ success

Please sign in to comment.