From 7aa8e477551b510123f66ab83da6519109d6bab0 Mon Sep 17 00:00:00 2001 From: lipp <489435760@qq.com> Date: Wed, 13 Sep 2023 14:33:17 +0800 Subject: [PATCH] feat: add boolean type for builtins.html[0].inject (#3771) * feat: add boolean type for builtins.html[0].inject * refactor * fix * fix --------- Co-authored-by: ahabhgk --- crates/node_binding/binding.d.ts | 6 +- .../src/options/raw_builtins/raw_html.rs | 21 ++---- crates/rspack_plugin_html/src/config.rs | 16 +++-- crates/rspack_plugin_html/src/plugin.rs | 52 +++++++-------- .../rspack_plugin_html/src/visitors/asset.rs | 11 ++-- .../src/builtin-plugin/HtmlRspackPlugin.ts | 16 ++++- .../configCases/builtins/html-inject/index.js | 40 +++++++++++ .../builtins/html-inject/webpack.config.js | 45 +++++++++++++ pnpm-lock.yaml | 66 ++++++++----------- 9 files changed, 175 insertions(+), 98 deletions(-) create mode 100644 packages/rspack/tests/configCases/builtins/html-inject/index.js create mode 100644 packages/rspack/tests/configCases/builtins/html-inject/webpack.config.js diff --git a/crates/node_binding/binding.d.ts b/crates/node_binding/binding.d.ts index 7f4e7670c46..9c7c97f3c74 100644 --- a/crates/node_binding/binding.d.ts +++ b/crates/node_binding/binding.d.ts @@ -716,12 +716,12 @@ export interface RawHtmlRspackPluginOptions { template?: string templateContent?: string templateParameters?: Record - /** `head`, `body` or None */ - inject?: "head" | "body" + /** "head", "body" or "false" */ + inject: "head" | "body" | "false" /** path or `auto` */ publicPath?: string /** `blocking`, `defer`, or `module` */ - scriptLoading?: "blocking" | "defer" | "module" + scriptLoading: "blocking" | "defer" | "module" /** entry_chunk_name (only entry chunks are supported) */ chunks?: Array excludedChunks?: Array diff --git a/crates/rspack_binding_options/src/options/raw_builtins/raw_html.rs b/crates/rspack_binding_options/src/options/raw_builtins/raw_html.rs index 9c2d4319869..ac9ed5e4aec 100644 --- a/crates/rspack_binding_options/src/options/raw_builtins/raw_html.rs +++ b/crates/rspack_binding_options/src/options/raw_builtins/raw_html.rs @@ -25,14 +25,14 @@ pub struct RawHtmlRspackPluginOptions { pub template: Option, pub template_content: Option, pub template_parameters: Option>, - /// `head`, `body` or None - #[napi(ts_type = "\"head\" | \"body\"")] - pub inject: Option, + /// "head", "body" or "false" + #[napi(ts_type = "\"head\" | \"body\" | \"false\"")] + pub inject: RawHtmlInject, /// path or `auto` pub public_path: Option, /// `blocking`, `defer`, or `module` #[napi(ts_type = "\"blocking\" | \"defer\" | \"module\"")] - pub script_loading: Option, + pub script_loading: RawHtmlScriptLoading, /// entry_chunk_name (only entry chunks are supported) pub chunks: Option>, @@ -47,17 +47,10 @@ pub struct RawHtmlRspackPluginOptions { impl From for HtmlRspackPluginOptions { fn from(value: RawHtmlRspackPluginOptions) -> Self { - let inject = value - .inject - .as_ref() - .map(|s| HtmlInject::from_str(s).unwrap_or_else(|_| panic!("Invalid inject value: {s}"))); + let inject = HtmlInject::from_str(&value.inject).expect("Invalid inject value"); - let script_loading = HtmlScriptLoading::from_str( - &value - .script_loading - .unwrap_or_else(|| String::from("defer")), - ) - .expect("value.script_loading has unwrap_or_else so this will never happen"); + let script_loading = + HtmlScriptLoading::from_str(&value.script_loading).expect("Invalid script_loading value"); let sri = value.sri.as_ref().map(|s| { HtmlSriHashFunction::from_str(s).unwrap_or_else(|_| panic!("Invalid sri value: {s}")) diff --git a/crates/rspack_plugin_html/src/config.rs b/crates/rspack_plugin_html/src/config.rs index 1a0fcac121d..f5892bda760 100644 --- a/crates/rspack_plugin_html/src/config.rs +++ b/crates/rspack_plugin_html/src/config.rs @@ -14,6 +14,7 @@ use crate::sri::HtmlSriHashFunction; pub enum HtmlInject { Head, Body, + False, } impl FromStr for HtmlInject { @@ -24,9 +25,11 @@ impl FromStr for HtmlInject { Ok(HtmlInject::Head) } else if s.eq("body") { Ok(HtmlInject::Body) + } else if s.eq("false") { + Ok(HtmlInject::False) } else { Err(anyhow::Error::msg( - "inject in html config only support 'head' or 'body'", + "inject in html config only support 'head', 'body', or 'false'", )) } } @@ -70,8 +73,9 @@ pub struct HtmlRspackPluginOptions { pub template: Option, pub template_content: Option, pub template_parameters: Option>, - /// `head`, `body` or None - pub inject: Option, + /// `head`, `body`, `false` + #[serde(default = "default_inject")] + pub inject: HtmlInject, /// path or `auto` pub public_path: Option, /// `blocking`, `defer`, or `module` @@ -100,6 +104,10 @@ fn default_script_loading() -> HtmlScriptLoading { HtmlScriptLoading::Defer } +fn default_inject() -> HtmlInject { + HtmlInject::Head +} + impl Default for HtmlRspackPluginOptions { fn default() -> HtmlRspackPluginOptions { HtmlRspackPluginOptions { @@ -107,7 +115,7 @@ impl Default for HtmlRspackPluginOptions { template: None, template_content: None, template_parameters: None, - inject: None, + inject: default_inject(), public_path: None, script_loading: default_script_loading(), chunks: None, diff --git a/crates/rspack_plugin_html/src/plugin.rs b/crates/rspack_plugin_html/src/plugin.rs index d6868a6c5e4..17b3ad12724 100644 --- a/crates/rspack_plugin_html/src/plugin.rs +++ b/crates/rspack_plugin_html/src/plugin.rs @@ -132,36 +132,28 @@ impl Plugin for HtmlRspackPlugin { .collect::>(); let mut tags = vec![]; - for (asset_name, asset) in included_assets { - if let Some(extension) = Path::new(&asset_name).extension() { - let asset_uri = format!( - "{}{asset_name}", - config.get_public_path(compilation, &self.config.filename), - ); - let mut tag: Option = None; - if extension.eq_ignore_ascii_case("css") { - tag = Some(HTMLPluginTag::create_style( - &asset_uri, - Some(if let Some(inject) = &config.inject { - *inject - } else { - HtmlInject::Head - }), - )); - } else if extension.eq_ignore_ascii_case("js") || extension.eq_ignore_ascii_case("mjs") { - tag = Some(HTMLPluginTag::create_script( - &asset_uri, - Some(if let Some(inject) = &config.inject { - *inject - } else { - HtmlInject::Head - }), - &config.script_loading, - )) - } - - if let Some(tag) = tag { - tags.push((tag, asset)); + // if inject is 'false', don't do anything + if !matches!(config.inject, HtmlInject::False) { + for (asset_name, asset) in included_assets { + if let Some(extension) = Path::new(&asset_name).extension() { + let asset_uri = format!( + "{}{asset_name}", + config.get_public_path(compilation, &self.config.filename), + ); + let mut tag: Option = None; + if extension.eq_ignore_ascii_case("css") { + tag = Some(HTMLPluginTag::create_style(&asset_uri, config.inject)); + } else if extension.eq_ignore_ascii_case("js") || extension.eq_ignore_ascii_case("mjs") { + tag = Some(HTMLPluginTag::create_script( + &asset_uri, + config.inject, + &config.script_loading, + )) + } + + if let Some(tag) = tag { + tags.push((tag, asset)); + } } } } diff --git a/crates/rspack_plugin_html/src/visitors/asset.rs b/crates/rspack_plugin_html/src/visitors/asset.rs index 0cd90fe5169..7e00a6cfa9d 100644 --- a/crates/rspack_plugin_html/src/visitors/asset.rs +++ b/crates/rspack_plugin_html/src/visitors/asset.rs @@ -17,15 +17,15 @@ pub struct HTMLPluginTag { pub tag_name: String, pub attributes: Vec, pub void_tag: bool, - // `head` or `body` + // `head`, `body`, `false` pub append_to: HtmlInject, } impl HTMLPluginTag { - pub fn create_style(href: &str, append_to: Option) -> HTMLPluginTag { + pub fn create_style(href: &str, append_to: HtmlInject) -> HTMLPluginTag { HTMLPluginTag { tag_name: "link".to_string(), - append_to: append_to.unwrap_or(HtmlInject::Head), + append_to, attributes: vec![ HtmlPluginAttribute { attr_name: "href".to_string(), @@ -42,7 +42,7 @@ impl HTMLPluginTag { pub fn create_script( src: &str, - append_to: Option, + append_to: HtmlInject, script_loading: &HtmlScriptLoading, ) -> HTMLPluginTag { let mut attributes = vec![HtmlPluginAttribute { @@ -67,7 +67,7 @@ impl HTMLPluginTag { HTMLPluginTag { tag_name: "script".to_string(), - append_to: append_to.unwrap_or(HtmlInject::Body), + append_to, attributes, void_tag: false, } @@ -107,6 +107,7 @@ impl<'a, 'c> AssetWriter<'a, 'c> { HtmlInject::Body => { body_tags.push(ele); } + _ => (), } } AssetWriter { diff --git a/packages/rspack/src/builtin-plugin/HtmlRspackPlugin.ts b/packages/rspack/src/builtin-plugin/HtmlRspackPlugin.ts index 4a8bf1f9543..3fb22b67473 100644 --- a/packages/rspack/src/builtin-plugin/HtmlRspackPlugin.ts +++ b/packages/rspack/src/builtin-plugin/HtmlRspackPlugin.ts @@ -8,7 +8,7 @@ const htmlRspackPluginOptions = z.strictObject({ template: z.string().optional(), templateContent: z.string().optional(), templateParameters: z.record(z.string()).optional(), - inject: z.enum(["head", "body"]).optional(), + inject: z.enum(["head", "body"]).or(z.boolean()).optional(), publicPath: z.string().optional(), scriptLoading: z.enum(["blocking", "defer", "module"]).optional(), chunks: z.string().array().optional(), @@ -34,9 +34,21 @@ export const HtmlRspackPlugin = create( }; } } + const scriptLoading = c.scriptLoading ?? "defer"; + const configInject = c.inject ?? true; + const inject = + configInject === true + ? scriptLoading === "blocking" + ? "body" + : "head" + : configInject === false + ? "false" + : configInject; return { ...c, - meta + meta, + scriptLoading, + inject }; } ); diff --git a/packages/rspack/tests/configCases/builtins/html-inject/index.js b/packages/rspack/tests/configCases/builtins/html-inject/index.js new file mode 100644 index 00000000000..1d427ecf57e --- /dev/null +++ b/packages/rspack/tests/configCases/builtins/html-inject/index.js @@ -0,0 +1,40 @@ +const fs = require("fs"); +const path = require("path"); + +it("body-index.html inject", () => { + const htmlPath = path.join(__dirname, "./body-index.html"); + const htmlContent = fs.readFileSync(htmlPath, "utf-8"); + expect( + htmlContent.includes('') + ).toBe(true); +}); + +it("head-index.html inject", () => { + const htmlPath = path.join(__dirname, "./head-index.html"); + const htmlContent = fs.readFileSync(htmlPath, "utf-8"); + expect( + htmlContent.includes('') + ).toBe(true); +}); + +it("true-blocking-index.html inject", () => { + const htmlPath = path.join(__dirname, "./true-blocking-index.html"); + const htmlContent = fs.readFileSync(htmlPath, "utf-8"); + expect(htmlContent.includes('')).toBe( + true + ); +}); + +it("true-defer-index.html inject", () => { + const htmlPath = path.join(__dirname, "./true-defer-index.html"); + const htmlContent = fs.readFileSync(htmlPath, "utf-8"); + expect( + htmlContent.includes('') + ).toBe(true); +}); + +it("false-index.html inject", () => { + const htmlPath = path.join(__dirname, "./false-index.html"); + const htmlContent = fs.readFileSync(htmlPath, "utf-8"); + expect(htmlContent.includes('