diff --git a/crates/node_binding/napi-binding.d.ts b/crates/node_binding/napi-binding.d.ts index 9a58a49c7c52..4989349711f2 100644 --- a/crates/node_binding/napi-binding.d.ts +++ b/crates/node_binding/napi-binding.d.ts @@ -2101,22 +2101,22 @@ export interface RawEntryDynamicResult { } export interface RawEnvironment { - const?: boolean - methodShorthand?: boolean - arrowFunction?: boolean - nodePrefixForCoreModules?: boolean - asyncFunction?: boolean - bigIntLiteral?: boolean - destructuring?: boolean - document?: boolean - dynamicImport?: boolean - forOf?: boolean - globalThis?: boolean - module?: boolean - optionalChaining?: boolean - templateLiteral?: boolean - dynamicImportInWorker?: boolean - importMetaDirnameAndFilename?: boolean + const: boolean + methodShorthand: boolean + arrowFunction: boolean + nodePrefixForCoreModules: boolean + asyncFunction: boolean + bigIntLiteral: boolean + destructuring: boolean + document: boolean + dynamicImport: boolean + forOf: boolean + globalThis: boolean + module: boolean + optionalChaining: boolean + templateLiteral: boolean + dynamicImportInWorker: boolean + importMetaDirnameAndFilename: boolean } export interface RawEsmLibraryPlugin { @@ -2406,7 +2406,7 @@ export interface RawLightningCssBrowsers { export interface RawLightningCssMinimizerOptions { errorRecovery: boolean - targets?: Array + targets?: string[] | RawLightningCssBrowsers include?: number exclude?: number drafts?: RawDraft diff --git a/crates/rspack/src/builder/mod.rs b/crates/rspack/src/builder/mod.rs index db62007b374d..b1acacf9886c 100644 --- a/crates/rspack/src/builder/mod.rs +++ b/crates/rspack/src/builder/mod.rs @@ -3078,23 +3078,44 @@ impl OutputOptionsBuilder { } let mut environment = f!(self.environment.take(), Environment::default); - environment.global_this = tp.and_then(|t| t.global_this); - environment.big_int_literal = tp.map(|t| optimistic!(t.big_int_literal)); - environment.r#const = tp.map(|t| optimistic!(t.r#const)); - environment.arrow_function = tp.map(|t| optimistic!(t.arrow_function)); - environment.async_function = tp.map(|t| optimistic!(t.async_function)); - environment.for_of = tp.map(|t| optimistic!(t.for_of)); - environment.destructuring = tp.map(|t| optimistic!(t.destructuring)); - environment.optional_chaining = tp.map(|t| optimistic!(t.optional_chaining)); - environment.node_prefix_for_core_modules = - tp.map(|t| optimistic!(t.node_prefix_for_core_modules)); - environment.template_literal = tp.map(|t| optimistic!(t.template_literal)); - environment.dynamic_import = - tp.map(|t| conditionally_optimistic!(t.dynamic_import, output_module)); - environment.dynamic_import_in_worker = - tp.map(|t| conditionally_optimistic!(t.dynamic_import_in_worker, output_module)); - environment.module = tp.map(|t| conditionally_optimistic!(t.module, output_module)); - environment.document = tp.map(|t| optimistic!(t.document)); + environment.global_this = tp.and_then(|t| t.global_this).unwrap_or_default(); + environment.big_int_literal = tp + .map(|t| optimistic!(t.big_int_literal)) + .unwrap_or_default(); + environment.r#const = tp.map(|t| optimistic!(t.r#const)).unwrap_or_default(); + environment.method_shorthand = tp + .map(|t| optimistic!(t.method_shorthand)) + .unwrap_or_default(); + environment.arrow_function = tp + .map(|t| optimistic!(t.arrow_function)) + .unwrap_or_default(); + environment.async_function = tp + .map(|t| optimistic!(t.async_function)) + .unwrap_or_default(); + environment.for_of = tp.map(|t| optimistic!(t.for_of)).unwrap_or_default(); + environment.destructuring = tp.map(|t| optimistic!(t.destructuring)).unwrap_or_default(); + environment.optional_chaining = tp + .map(|t| optimistic!(t.optional_chaining)) + .unwrap_or_default(); + environment.node_prefix_for_core_modules = tp + .map(|t| optimistic!(t.node_prefix_for_core_modules)) + .unwrap_or_default(); + environment.import_meta_dirname_and_filename = tp + .and_then(|t| t.import_meta_dirname_and_filename) + .unwrap_or_default(); + environment.template_literal = tp + .map(|t| optimistic!(t.template_literal)) + .unwrap_or_default(); + environment.dynamic_import = tp + .map(|t| conditionally_optimistic!(t.dynamic_import, output_module)) + .unwrap_or_default(); + environment.dynamic_import_in_worker = tp + .map(|t| conditionally_optimistic!(t.dynamic_import_in_worker, output_module)) + .unwrap_or_default(); + environment.module = tp + .map(|t| conditionally_optimistic!(t.module, output_module)) + .unwrap_or_default(); + environment.document = tp.map(|t| optimistic!(t.document)).unwrap_or_default(); Ok(OutputOptions { path, diff --git a/crates/rspack/src/builder/snapshots/rspack__builder__browserslist_target__tests__browserslist_targets_snapshots.snap b/crates/rspack/src/builder/snapshots/rspack__builder__browserslist_target__tests__browserslist_targets_snapshots.snap index 12077b5dc7b3..2d04f7e34b46 100644 --- a/crates/rspack/src/builder/snapshots/rspack__builder__browserslist_target__tests__browserslist_targets_snapshots.snap +++ b/crates/rspack/src/builder/snapshots/rspack__builder__browserslist_target__tests__browserslist_targets_snapshots.snap @@ -62,6 +62,7 @@ expression: results const: Some( false, ), + method_shorthand: None, arrow_function: Some( false, ), @@ -89,6 +90,7 @@ expression: results async_function: Some( false, ), + import_meta_dirname_and_filename: None, }, ), ( @@ -150,6 +152,7 @@ expression: results const: Some( false, ), + method_shorthand: None, arrow_function: Some( false, ), @@ -177,6 +180,7 @@ expression: results async_function: Some( false, ), + import_meta_dirname_and_filename: None, }, ), ( @@ -238,6 +242,7 @@ expression: results const: Some( true, ), + method_shorthand: None, arrow_function: Some( true, ), @@ -265,6 +270,7 @@ expression: results async_function: Some( true, ), + import_meta_dirname_and_filename: None, }, ), ( @@ -326,6 +332,7 @@ expression: results const: Some( false, ), + method_shorthand: None, arrow_function: Some( false, ), @@ -353,6 +360,7 @@ expression: results async_function: Some( false, ), + import_meta_dirname_and_filename: None, }, ), ( @@ -414,6 +422,7 @@ expression: results const: Some( false, ), + method_shorthand: None, arrow_function: Some( false, ), @@ -441,6 +450,7 @@ expression: results async_function: Some( false, ), + import_meta_dirname_and_filename: None, }, ), ( @@ -502,6 +512,7 @@ expression: results const: Some( false, ), + method_shorthand: None, arrow_function: Some( false, ), @@ -529,6 +540,7 @@ expression: results async_function: Some( false, ), + import_meta_dirname_and_filename: None, }, ), ( @@ -590,6 +602,7 @@ expression: results const: Some( true, ), + method_shorthand: None, arrow_function: Some( true, ), @@ -617,6 +630,7 @@ expression: results async_function: Some( true, ), + import_meta_dirname_and_filename: None, }, ), ( @@ -678,6 +692,7 @@ expression: results const: Some( true, ), + method_shorthand: None, arrow_function: Some( true, ), @@ -705,6 +720,7 @@ expression: results async_function: Some( true, ), + import_meta_dirname_and_filename: None, }, ), ( @@ -766,6 +782,7 @@ expression: results const: Some( true, ), + method_shorthand: None, arrow_function: Some( true, ), @@ -793,6 +810,7 @@ expression: results async_function: Some( true, ), + import_meta_dirname_and_filename: None, }, ), ( @@ -854,6 +872,7 @@ expression: results const: Some( true, ), + method_shorthand: None, arrow_function: Some( true, ), @@ -881,6 +900,7 @@ expression: results async_function: Some( true, ), + import_meta_dirname_and_filename: None, }, ), ( @@ -942,6 +962,7 @@ expression: results const: Some( true, ), + method_shorthand: None, arrow_function: Some( true, ), @@ -969,6 +990,7 @@ expression: results async_function: Some( true, ), + import_meta_dirname_and_filename: None, }, ), ( @@ -1030,6 +1052,7 @@ expression: results const: Some( true, ), + method_shorthand: None, arrow_function: Some( true, ), @@ -1057,6 +1080,7 @@ expression: results async_function: Some( true, ), + import_meta_dirname_and_filename: None, }, ), ( @@ -1118,6 +1142,7 @@ expression: results const: Some( true, ), + method_shorthand: None, arrow_function: Some( true, ), @@ -1145,6 +1170,7 @@ expression: results async_function: Some( true, ), + import_meta_dirname_and_filename: None, }, ), ( @@ -1206,6 +1232,7 @@ expression: results const: Some( true, ), + method_shorthand: None, arrow_function: Some( true, ), @@ -1233,6 +1260,7 @@ expression: results async_function: Some( false, ), + import_meta_dirname_and_filename: None, }, ), ( @@ -1294,6 +1322,7 @@ expression: results const: Some( true, ), + method_shorthand: None, arrow_function: Some( true, ), @@ -1321,6 +1350,7 @@ expression: results async_function: Some( true, ), + import_meta_dirname_and_filename: None, }, ), ( @@ -1382,6 +1412,7 @@ expression: results const: Some( true, ), + method_shorthand: None, arrow_function: Some( true, ), @@ -1409,6 +1440,7 @@ expression: results async_function: Some( true, ), + import_meta_dirname_and_filename: None, }, ), ( @@ -1470,6 +1502,7 @@ expression: results const: Some( true, ), + method_shorthand: None, arrow_function: Some( true, ), @@ -1497,6 +1530,7 @@ expression: results async_function: Some( true, ), + import_meta_dirname_and_filename: None, }, ), ( @@ -1558,6 +1592,7 @@ expression: results const: Some( true, ), + method_shorthand: None, arrow_function: Some( true, ), @@ -1585,6 +1620,7 @@ expression: results async_function: Some( true, ), + import_meta_dirname_and_filename: None, }, ), ( @@ -1646,6 +1682,7 @@ expression: results const: Some( true, ), + method_shorthand: None, arrow_function: Some( true, ), @@ -1673,6 +1710,7 @@ expression: results async_function: Some( true, ), + import_meta_dirname_and_filename: None, }, ), ( @@ -1734,6 +1772,7 @@ expression: results const: Some( true, ), + method_shorthand: None, arrow_function: Some( true, ), @@ -1761,6 +1800,7 @@ expression: results async_function: Some( true, ), + import_meta_dirname_and_filename: None, }, ), ( @@ -1822,6 +1862,7 @@ expression: results const: Some( false, ), + method_shorthand: None, arrow_function: Some( false, ), @@ -1849,6 +1890,7 @@ expression: results async_function: Some( false, ), + import_meta_dirname_and_filename: None, }, ), ( @@ -1910,6 +1952,7 @@ expression: results const: Some( true, ), + method_shorthand: None, arrow_function: Some( true, ), @@ -1937,6 +1980,7 @@ expression: results async_function: Some( true, ), + import_meta_dirname_and_filename: None, }, ), ( @@ -1998,6 +2042,7 @@ expression: results const: Some( true, ), + method_shorthand: None, arrow_function: Some( true, ), @@ -2025,6 +2070,7 @@ expression: results async_function: Some( true, ), + import_meta_dirname_and_filename: None, }, ), ( @@ -2086,6 +2132,7 @@ expression: results const: Some( false, ), + method_shorthand: None, arrow_function: Some( false, ), @@ -2113,6 +2160,7 @@ expression: results async_function: Some( false, ), + import_meta_dirname_and_filename: None, }, ), ( @@ -2174,6 +2222,7 @@ expression: results const: Some( false, ), + method_shorthand: None, arrow_function: Some( false, ), @@ -2201,6 +2250,7 @@ expression: results async_function: Some( false, ), + import_meta_dirname_and_filename: None, }, ), ( @@ -2262,6 +2312,7 @@ expression: results const: Some( false, ), + method_shorthand: None, arrow_function: Some( false, ), @@ -2289,6 +2340,7 @@ expression: results async_function: Some( false, ), + import_meta_dirname_and_filename: None, }, ), ( @@ -2350,6 +2402,7 @@ expression: results const: Some( false, ), + method_shorthand: None, arrow_function: Some( false, ), @@ -2377,6 +2430,7 @@ expression: results async_function: Some( false, ), + import_meta_dirname_and_filename: None, }, ), ( @@ -2438,6 +2492,7 @@ expression: results const: Some( true, ), + method_shorthand: None, arrow_function: Some( true, ), @@ -2465,6 +2520,7 @@ expression: results async_function: Some( true, ), + import_meta_dirname_and_filename: None, }, ), ( @@ -2526,6 +2582,7 @@ expression: results const: Some( true, ), + method_shorthand: None, arrow_function: Some( true, ), @@ -2553,6 +2610,7 @@ expression: results async_function: Some( true, ), + import_meta_dirname_and_filename: None, }, ), ( @@ -2614,6 +2672,7 @@ expression: results const: Some( true, ), + method_shorthand: None, arrow_function: Some( true, ), @@ -2641,6 +2700,7 @@ expression: results async_function: Some( true, ), + import_meta_dirname_and_filename: None, }, ), ( @@ -2702,6 +2762,7 @@ expression: results const: Some( true, ), + method_shorthand: None, arrow_function: Some( true, ), @@ -2729,6 +2790,7 @@ expression: results async_function: Some( false, ), + import_meta_dirname_and_filename: None, }, ), ( @@ -2790,6 +2852,7 @@ expression: results const: Some( true, ), + method_shorthand: None, arrow_function: Some( true, ), @@ -2817,6 +2880,7 @@ expression: results async_function: Some( false, ), + import_meta_dirname_and_filename: None, }, ), ( @@ -2878,6 +2942,7 @@ expression: results const: Some( true, ), + method_shorthand: None, arrow_function: Some( true, ), @@ -2905,6 +2970,7 @@ expression: results async_function: Some( false, ), + import_meta_dirname_and_filename: None, }, ), ( @@ -2966,6 +3032,7 @@ expression: results const: Some( false, ), + method_shorthand: None, arrow_function: Some( true, ), @@ -2993,6 +3060,7 @@ expression: results async_function: Some( false, ), + import_meta_dirname_and_filename: None, }, ), ( @@ -3055,6 +3123,7 @@ expression: results const: Some( true, ), + method_shorthand: None, arrow_function: Some( true, ), @@ -3082,6 +3151,7 @@ expression: results async_function: Some( true, ), + import_meta_dirname_and_filename: None, }, ), ( @@ -3128,6 +3198,7 @@ expression: results const: Some( true, ), + method_shorthand: None, arrow_function: Some( true, ), @@ -3155,6 +3226,7 @@ expression: results async_function: Some( true, ), + import_meta_dirname_and_filename: None, }, ), ( @@ -3216,6 +3288,7 @@ expression: results const: Some( false, ), + method_shorthand: None, arrow_function: Some( false, ), @@ -3243,6 +3316,7 @@ expression: results async_function: Some( false, ), + import_meta_dirname_and_filename: None, }, ), ] diff --git a/crates/rspack/src/builder/target.rs b/crates/rspack/src/builder/target.rs index fd13625265c5..843e602fbdbc 100644 --- a/crates/rspack/src/builder/target.rs +++ b/crates/rspack/src/builder/target.rs @@ -26,6 +26,7 @@ pub struct TargetProperties { pub global_this: Option, pub big_int_literal: Option, pub r#const: Option, + pub method_shorthand: Option, pub arrow_function: Option, pub for_of: Option, pub destructuring: Option, @@ -35,6 +36,7 @@ pub struct TargetProperties { pub optional_chaining: Option, pub template_literal: Option, pub async_function: Option, + pub import_meta_dirname_and_filename: Option, } #[allow(unused)] @@ -252,6 +254,7 @@ fn get_target_properties(target: &str, context: &Context) -> TargetProperties { import_scripts_in_worker: Some(false), global_this: Some(version_dependent(12, None, major, minor)), r#const: Some(version_dependent(6, None, major, minor)), + method_shorthand: Some(version_dependent(4, None, major, minor)), template_literal: Some(version_dependent(4, None, major, minor)), optional_chaining: Some(version_dependent(14, None, major, minor)), arrow_function: Some(version_dependent(6, None, major, minor)), @@ -362,6 +365,7 @@ fn get_target_properties(target: &str, context: &Context) -> TargetProperties { import_scripts_in_worker: Some(true), global_this: Some(version_dependent(5, None, major, minor)), r#const: Some(version_dependent(1, Some(1), major, minor)), + method_shorthand: Some(version_dependent(1, Some(1), major, minor)), template_literal: Some(version_dependent(1, Some(1), major, minor)), optional_chaining: Some(version_dependent(8, None, major, minor)), arrow_function: Some(version_dependent(1, Some(1), major, minor)), @@ -372,6 +376,7 @@ fn get_target_properties(target: &str, context: &Context) -> TargetProperties { dynamic_import: Some(version_dependent(11, None, major, minor)), dynamic_import_in_worker: if major.is_some() { Some(false) } else { None }, module: Some(version_dependent(11, None, major, minor)), + import_meta_dirname_and_filename: None, }; } @@ -407,6 +412,7 @@ fn get_target_properties(target: &str, context: &Context) -> TargetProperties { require: Some(false), global_this: Some(version_dependent(0, Some(43), major, minor)), r#const: Some(version_dependent(0, Some(15), major, minor)), + method_shorthand: Some(version_dependent(0, Some(15), major, minor)), template_literal: Some(version_dependent(0, Some(13), major, minor)), optional_chaining: Some(version_dependent(0, Some(44), major, minor)), arrow_function: Some(version_dependent(0, Some(15), major, minor)), @@ -440,6 +446,7 @@ fn get_target_properties(target: &str, context: &Context) -> TargetProperties { r#const: Some(version >= 2015), template_literal: Some(version >= 2015), optional_chaining: Some(version >= 2020), + method_shorthand: Some(version >= 2015), arrow_function: Some(version >= 2015), for_of: Some(version >= 2015), destructuring: Some(version >= 2015), diff --git a/crates/rspack/tests/snapshots/defaults__default_options.snap b/crates/rspack/tests/snapshots/defaults__default_options.snap index 82b762a6476b..deadffcc507a 100644 --- a/crates/rspack/tests/snapshots/defaults__default_options.snap +++ b/crates/rspack/tests/snapshots/defaults__default_options.snap @@ -95,50 +95,22 @@ CompilerOptions { worker_public_path: "", script_type: "", environment: Environment { - const: Some( - false, - ), - method_shorthand: None, - arrow_function: Some( - false, - ), - node_prefix_for_core_modules: Some( - false, - ), - async_function: Some( - false, - ), - big_int_literal: Some( - false, - ), - destructuring: Some( - false, - ), - document: Some( - true, - ), - dynamic_import: Some( - false, - ), - for_of: Some( - false, - ), - global_this: Some( - false, - ), - module: Some( - false, - ), - optional_chaining: Some( - false, - ), - template_literal: Some( - false, - ), - dynamic_import_in_worker: Some( - false, - ), - import_meta_dirname_and_filename: None, + const: false, + method_shorthand: true, + arrow_function: false, + node_prefix_for_core_modules: false, + async_function: false, + big_int_literal: false, + destructuring: false, + document: true, + dynamic_import: false, + for_of: false, + global_this: false, + module: false, + optional_chaining: false, + template_literal: false, + dynamic_import_in_worker: false, + import_meta_dirname_and_filename: false, }, compare_before_emit: true, }, diff --git a/crates/rspack_binding_api/src/raw_options/raw_builtins/raw_lightning_css_minimizer.rs b/crates/rspack_binding_api/src/raw_options/raw_builtins/raw_lightning_css_minimizer.rs index d91e8895b60b..6525d694ea43 100644 --- a/crates/rspack_binding_api/src/raw_options/raw_builtins/raw_lightning_css_minimizer.rs +++ b/crates/rspack_binding_api/src/raw_options/raw_builtins/raw_lightning_css_minimizer.rs @@ -1,8 +1,9 @@ +use napi::Either; use napi_derive::napi; use rspack_browserslist::browserslist_to_lightningcss_targets; use rspack_error::{Result, ToStringResultToRspackResultExt}; use rspack_plugin_lightning_css_minimizer::{ - Draft, MinimizerOptions, NonStandard, PluginOptions, PseudoClasses, + Browsers, Draft, MinimizerOptions, NonStandard, PluginOptions, PseudoClasses, }; use crate::asset_condition::{RawAssetConditions, into_asset_conditions}; @@ -24,7 +25,8 @@ pub struct RawLightningCssMinimizerRspackPluginOptions { #[napi(object)] pub struct RawLightningCssMinimizerOptions { pub error_recovery: bool, - pub targets: Option>, + #[napi(ts_type = "string[] | RawLightningCssBrowsers")] + pub targets: Option, RawLightningCssBrowsers>>, pub include: Option, pub exclude: Option, pub drafts: Option, @@ -35,7 +37,6 @@ pub struct RawLightningCssMinimizerOptions { #[derive(Debug)] #[napi(object)] -#[allow(unused)] pub struct RawLightningCssBrowsers { pub android: Option, pub chrome: Option, @@ -85,7 +86,20 @@ impl TryFrom for PluginOptions { targets: value .minimizer_options .targets - .map(browserslist_to_lightningcss_targets) + .map(|targets| match targets { + Either::A(query) => browserslist_to_lightningcss_targets(query), + Either::B(browsers) => Ok(Some(Browsers { + android: browsers.android, + chrome: browsers.chrome, + edge: browsers.edge, + firefox: browsers.firefox, + ie: browsers.ie, + ios_saf: browsers.ios_saf, + opera: browsers.opera, + safari: browsers.safari, + samsung: browsers.samsung, + })), + }) .transpose() .to_rspack_result_with_message(|e| format!("Failed to parse browserslist: {e}"))? .flatten(), diff --git a/crates/rspack_binding_api/src/raw_options/raw_output.rs b/crates/rspack_binding_api/src/raw_options/raw_output.rs index 6f9b34f0d74b..8934cb9fa1e7 100644 --- a/crates/rspack_binding_api/src/raw_options/raw_output.rs +++ b/crates/rspack_binding_api/src/raw_options/raw_output.rs @@ -43,22 +43,22 @@ impl From for CrossOriginLoading { #[derive(Debug, Clone)] #[napi(object)] pub struct RawEnvironment { - pub r#const: Option, - pub method_shorthand: Option, - pub arrow_function: Option, - pub node_prefix_for_core_modules: Option, - pub async_function: Option, - pub big_int_literal: Option, - pub destructuring: Option, - pub document: Option, - pub dynamic_import: Option, - pub for_of: Option, - pub global_this: Option, - pub module: Option, - pub optional_chaining: Option, - pub template_literal: Option, - pub dynamic_import_in_worker: Option, - pub import_meta_dirname_and_filename: Option, + pub r#const: bool, + pub method_shorthand: bool, + pub arrow_function: bool, + pub node_prefix_for_core_modules: bool, + pub async_function: bool, + pub big_int_literal: bool, + pub destructuring: bool, + pub document: bool, + pub dynamic_import: bool, + pub for_of: bool, + pub global_this: bool, + pub module: bool, + pub optional_chaining: bool, + pub template_literal: bool, + pub dynamic_import_in_worker: bool, + pub import_meta_dirname_and_filename: bool, } impl From for Environment { diff --git a/crates/rspack_core/src/options/output.rs b/crates/rspack_core/src/options/output.rs index d9486fd05fe2..d2985b5c0f7b 100644 --- a/crates/rspack_core/src/options/output.rs +++ b/crates/rspack_core/src/options/output.rs @@ -523,82 +523,86 @@ pub struct LibraryCustomUmdObject { #[derive(Debug, Default, Copy, Clone)] pub struct Environment { - pub r#const: Option, - pub method_shorthand: Option, - pub arrow_function: Option, - pub node_prefix_for_core_modules: Option, - pub async_function: Option, - pub big_int_literal: Option, - pub destructuring: Option, - pub document: Option, - pub dynamic_import: Option, - pub for_of: Option, - pub global_this: Option, - pub module: Option, - pub optional_chaining: Option, - pub template_literal: Option, - pub dynamic_import_in_worker: Option, - pub import_meta_dirname_and_filename: Option, + pub r#const: bool, + pub method_shorthand: bool, + pub arrow_function: bool, + pub node_prefix_for_core_modules: bool, + pub async_function: bool, + pub big_int_literal: bool, + pub destructuring: bool, + pub document: bool, + pub dynamic_import: bool, + pub for_of: bool, + pub global_this: bool, + pub module: bool, + pub optional_chaining: bool, + pub template_literal: bool, + pub dynamic_import_in_worker: bool, + pub import_meta_dirname_and_filename: bool, } impl Environment { pub fn supports_const(&self) -> bool { - self.r#const.unwrap_or_default() + self.r#const } pub fn supports_method_shorthand(&self) -> bool { - self.method_shorthand.unwrap_or_default() + self.method_shorthand } pub fn supports_arrow_function(&self) -> bool { - self.arrow_function.unwrap_or_default() + self.arrow_function } pub fn supports_node_prefix_for_core_modules(&self) -> bool { - self.node_prefix_for_core_modules.unwrap_or_default() + self.node_prefix_for_core_modules + } + + pub fn supports_import_meta_dirname_and_filename(&self) -> bool { + self.import_meta_dirname_and_filename } pub fn supports_async_function(&self) -> bool { - self.async_function.unwrap_or_default() + self.async_function } pub fn supports_big_int_literal(&self) -> bool { - self.big_int_literal.unwrap_or_default() + self.big_int_literal } pub fn supports_destructuring(&self) -> bool { - self.destructuring.unwrap_or_default() + self.destructuring } pub fn supports_document(&self) -> bool { - self.document.unwrap_or_default() + self.document } pub fn supports_dynamic_import(&self) -> bool { - self.dynamic_import.unwrap_or_default() + self.dynamic_import } pub fn supports_dynamic_import_in_worker(&self) -> bool { - self.dynamic_import_in_worker.unwrap_or_default() + self.dynamic_import_in_worker } pub fn supports_for_of(&self) -> bool { - self.for_of.unwrap_or_default() + self.for_of } pub fn supports_global_this(&self) -> bool { - self.global_this.unwrap_or_default() + self.global_this } pub fn supports_module(&self) -> bool { - self.module.unwrap_or_default() + self.module } pub fn supports_optional_chaining(&self) -> bool { - self.optional_chaining.unwrap_or_default() + self.optional_chaining } pub fn supports_template_literal(&self) -> bool { - self.template_literal.unwrap_or_default() + self.template_literal } } diff --git a/crates/rspack_loader_lightningcss/src/config.rs b/crates/rspack_loader_lightningcss/src/config.rs index 8758078e9acc..e0201c1da532 100644 --- a/crates/rspack_loader_lightningcss/src/config.rs +++ b/crates/rspack_loader_lightningcss/src/config.rs @@ -52,7 +52,7 @@ pub struct Config { pub struct RawConfig { pub minify: Option, pub error_recovery: Option, - pub targets: Option>, + pub targets: Option, pub include: Option, pub exclude: Option, pub drafts: Option, @@ -61,6 +61,13 @@ pub struct RawConfig { pub unused_symbols: Option>, } +#[derive(Debug, Deserialize)] +#[serde(untagged)] +pub enum RawConfigTargets { + Browserslist(Vec), + Targets(Browsers), +} + impl TryFrom for Config { type Error = rspack_error::Error; fn try_from(value: RawConfig) -> Result { @@ -69,7 +76,10 @@ impl TryFrom for Config { error_recovery: value.error_recovery, targets: value .targets - .map(browserslist_to_lightningcss_targets) + .map(|targets| match targets { + RawConfigTargets::Browserslist(query) => browserslist_to_lightningcss_targets(query), + RawConfigTargets::Targets(browsers) => Ok(Some(browsers)), + }) .transpose() .to_rspack_result_with_message(|e| format!("Failed to parse browserslist: {e}"))? .flatten(), diff --git a/crates/rspack_plugin_javascript/src/parser_plugin/node_stuff_plugin.rs b/crates/rspack_plugin_javascript/src/parser_plugin/node_stuff_plugin.rs index 2ea5d325221d..4023ecc019b8 100644 --- a/crates/rspack_plugin_javascript/src/parser_plugin/node_stuff_plugin.rs +++ b/crates/rspack_plugin_javascript/src/parser_plugin/node_stuff_plugin.rs @@ -326,8 +326,7 @@ impl NodeStuffPlugin { .compiler_options .output .environment - .import_meta_dirname_and_filename - .unwrap_or(false) + .supports_import_meta_dirname_and_filename() { // Keep as import.meta.filename/dirname - runtime supports it return Some(property.import_meta_name().to_string()); @@ -385,8 +384,7 @@ impl NodeStuffPlugin { .compiler_options .output .environment - .import_meta_dirname_and_filename - .unwrap_or(false) + .supports_import_meta_dirname_and_filename() { return Some(property.import_meta_name().to_string()); } diff --git a/crates/rspack_plugin_wasm/src/loading_plugin.rs b/crates/rspack_plugin_wasm/src/loading_plugin.rs index 348e7b5ea554..5b242039ac1c 100644 --- a/crates/rspack_plugin_wasm/src/loading_plugin.rs +++ b/crates/rspack_plugin_wasm/src/loading_plugin.rs @@ -94,8 +94,7 @@ async fn read_file_compile_async_wasm_plugin_runtime_requirements_in_tree( .options .output .environment - .dynamic_import - .unwrap_or_default(); + .supports_dynamic_import(); compilation.add_runtime_module( chunk_ukey, diff --git a/packages/rspack/etc/core.api.md b/packages/rspack/etc/core.api.md index 84ae8a0d6f1d..838022cd3b50 100644 --- a/packages/rspack/etc/core.api.md +++ b/packages/rspack/etc/core.api.md @@ -127,8 +127,8 @@ export type AmdContainer = string; export const applyRspackOptionsBaseDefaults: (options: RspackOptionsNormalized) => void; // @public (undocumented) -export const applyRspackOptionsDefaults: (options: RspackOptionsNormalized) => { - platform: false | { +export const applyRspackOptionsDefaults: (options: RspackOptionsNormalized) => false | { + platform: { web: boolean | null | undefined; browser: boolean | null | undefined; webworker: boolean | null | undefined; @@ -136,6 +136,8 @@ export const applyRspackOptionsDefaults: (options: RspackOptionsNormalized) => { nwjs: boolean | null | undefined; electron: boolean | null | undefined; }; + esVersion: number | null | undefined; + platforms: string[] | null | undefined; }; // @public (undocumented) @@ -1340,6 +1342,9 @@ export class Compiler { runAsChild(callback: (err?: null | Error, entries?: Chunk[], compilation?: Compilation) => any): void; // (undocumented) running: boolean; + // (undocumented) + get target(): ExtractedTargetProperties; + set target(target: ExtractedTargetProperties); // @internal unsafeFastDrop: boolean; // (undocumented) @@ -2828,6 +2833,12 @@ type ExtractCommentsObject = { // @public (undocumented) type ExtractCommentsOptions = ExtractCommentsCondition | ExtractCommentsObject; +// @public (undocumented) +type ExtractedTargetProperties = { + esVersion?: number | null; + platforms?: string[] | null; +}; + // @public (undocumented) type ExtraPluginHookData = { plugin: { @@ -4481,7 +4492,7 @@ export type LightningCssMinimizerRspackPluginOptions = { removeUnusedLocalIdents?: boolean; minimizerOptions?: { errorRecovery?: boolean; - targets?: string[] | string; + targets?: string[] | string | Targets; include?: LightningcssFeatureOptions; exclude?: LightningcssFeatureOptions; drafts?: Drafts; @@ -7371,7 +7382,7 @@ const RuntimeChunkPlugin: { }; // @public (undocumented) -export const RuntimeGlobals: Record<"publicPath" | "chunkName" | "moduleId" | "module" | "exports" | "require" | "global" | "system" | "requireScope" | "thisAsExports" | "returnExportsFromRuntime" | "moduleLoaded" | "entryModuleId" | "moduleCache" | "moduleFactories" | "moduleFactoriesAddOnly" | "ensureChunk" | "ensureChunkHandlers" | "ensureChunkIncludeEntries" | "prefetchChunk" | "prefetchChunkHandlers" | "preloadChunk" | "preloadChunkHandlers" | "definePropertyGetters" | "makeNamespaceObject" | "createFakeNamespaceObject" | "compatGetDefaultExport" | "harmonyModuleDecorator" | "nodeModuleDecorator" | "getFullHash" | "wasmInstances" | "instantiateWasm" | "uncaughtErrorHandler" | "scriptNonce" | "loadScript" | "createScript" | "createScriptUrl" | "getTrustedTypesPolicy" | "hasFetchPriority" | "runtimeId" | "getChunkScriptFilename" | "getChunkCssFilename" | "rspackVersion" | "hasCssModules" | "rspackUniqueId" | "getChunkUpdateScriptFilename" | "getChunkUpdateCssFilename" | "startup" | "startupNoDefault" | "startupOnlyAfter" | "startupOnlyBefore" | "chunkCallback" | "startupEntrypoint" | "startupChunkDependencies" | "onChunksLoaded" | "externalInstallChunk" | "interceptModuleExecution" | "shareScopeMap" | "initializeSharing" | "currentRemoteGetScope" | "getUpdateManifestFilename" | "hmrDownloadManifest" | "hmrDownloadUpdateHandlers" | "hmrModuleData" | "hmrInvalidateModuleHandlers" | "hmrRuntimeStatePrefix" | "amdDefine" | "amdOptions" | "hasOwnProperty" | "systemContext" | "baseURI" | "relativeUrl" | "asyncModule" | "asyncModuleExportSymbol" | "makeDeferredNamespaceObject" | "makeDeferredNamespaceObjectSymbol", string>; +export const RuntimeGlobals: Record<"publicPath" | "chunkName" | "moduleId" | "module" | "require" | "global" | "system" | "exports" | "requireScope" | "thisAsExports" | "returnExportsFromRuntime" | "moduleLoaded" | "entryModuleId" | "moduleCache" | "moduleFactories" | "moduleFactoriesAddOnly" | "ensureChunk" | "ensureChunkHandlers" | "ensureChunkIncludeEntries" | "prefetchChunk" | "prefetchChunkHandlers" | "preloadChunk" | "preloadChunkHandlers" | "definePropertyGetters" | "makeNamespaceObject" | "createFakeNamespaceObject" | "compatGetDefaultExport" | "harmonyModuleDecorator" | "nodeModuleDecorator" | "getFullHash" | "wasmInstances" | "instantiateWasm" | "uncaughtErrorHandler" | "scriptNonce" | "loadScript" | "createScript" | "createScriptUrl" | "getTrustedTypesPolicy" | "hasFetchPriority" | "runtimeId" | "getChunkScriptFilename" | "getChunkCssFilename" | "rspackVersion" | "hasCssModules" | "rspackUniqueId" | "getChunkUpdateScriptFilename" | "getChunkUpdateCssFilename" | "startup" | "startupNoDefault" | "startupOnlyAfter" | "startupOnlyBefore" | "chunkCallback" | "startupEntrypoint" | "startupChunkDependencies" | "onChunksLoaded" | "externalInstallChunk" | "interceptModuleExecution" | "shareScopeMap" | "initializeSharing" | "currentRemoteGetScope" | "getUpdateManifestFilename" | "hmrDownloadManifest" | "hmrDownloadUpdateHandlers" | "hmrModuleData" | "hmrInvalidateModuleHandlers" | "hmrRuntimeStatePrefix" | "amdDefine" | "amdOptions" | "hasOwnProperty" | "systemContext" | "baseURI" | "relativeUrl" | "asyncModule" | "asyncModuleExportSymbol" | "makeDeferredNamespaceObject" | "makeDeferredNamespaceObjectSymbol", string>; // @public (undocumented) export class RuntimeModule { @@ -8265,23 +8276,23 @@ export type Target = false | AllowTarget | AllowTarget[]; // @public (undocumented) interface Targets { // (undocumented) - android?: number; + android?: string; // (undocumented) - chrome?: number; + chrome?: string; // (undocumented) - edge?: number; + edge?: string; // (undocumented) - firefox?: number; + firefox?: string; // (undocumented) - ie?: number; + ie?: string; // (undocumented) - ios_saf?: number; + ios_saf?: string; // (undocumented) - opera?: number; + opera?: string; // (undocumented) - safari?: number; + safari?: string; // (undocumented) - samsung?: number; + samsung?: string; } // @public diff --git a/packages/rspack/src/Compiler.ts b/packages/rspack/src/Compiler.ts index 42a9cd4b0e3a..b92bab8a47b0 100644 --- a/packages/rspack/src/Compiler.ts +++ b/packages/rspack/src/Compiler.ts @@ -32,7 +32,10 @@ import type { } from './config'; import { getRawOptions } from './config'; import { applyRspackOptionsDefaults, getPnpDefault } from './config/defaults'; -import type { PlatformTargetProperties } from './config/target'; +import type { + ExtractedTargetProperties, + PlatformTargetProperties, +} from './config/target'; import ExecuteModulePlugin from './ExecuteModulePlugin'; import ConcurrentCompilationError from './error/ConcurrentCompilationError'; import * as rspackExports from './exports'; @@ -182,6 +185,7 @@ class Compiler { cache: Cache; compilerPath: string; #platform: PlatformTargetProperties; + #target: ExtractedTargetProperties; options: RspackOptionsNormalized; /** * Whether to skip dropping Rust compiler instance to improve performance. @@ -294,6 +298,7 @@ class Compiler { nwjs: null, electron: null, }; + this.#target = {}; this.__internal_browser_require = () => { throw new Error( @@ -353,6 +358,14 @@ class Compiler { this.#platform = platform; } + get target() { + return this.#target; + } + + set target(target: ExtractedTargetProperties) { + this.#target = target; + } + /** * Note: This is not a webpack public API, maybe removed in future. * @internal diff --git a/packages/rspack/src/builtin-loader/index.ts b/packages/rspack/src/builtin-loader/index.ts deleted file mode 100644 index f6e196139551..000000000000 --- a/packages/rspack/src/builtin-loader/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './swc'; diff --git a/packages/rspack/src/builtin-loader/lightningcss/index.ts b/packages/rspack/src/builtin-loader/lightningcss/index.ts index 5372520ba2a0..4e6863403572 100644 --- a/packages/rspack/src/builtin-loader/lightningcss/index.ts +++ b/packages/rspack/src/builtin-loader/lightningcss/index.ts @@ -1,5 +1,8 @@ // code modified based on https://github.com/parcel-bundler/lightningcss/blob/34b67a431c043fda5d4979bcdccb3008d082e243/node/browserslistToTargets.js +import type { GetLoaderOptions } from '../../config/adapterRuleUse'; +import { encodeTargets, resolveDefaultLightningCssTargets } from './target'; + /** MIT License @@ -144,15 +147,15 @@ export enum Features { } export interface Targets { - android?: number; - chrome?: number; - edge?: number; - firefox?: number; - ie?: number; - ios_saf?: number; - opera?: number; - safari?: number; - samsung?: number; + android?: string; + chrome?: string; + edge?: string; + firefox?: string; + ie?: string; + ios_saf?: string; + opera?: string; + safari?: string; + samsung?: string; } export interface Drafts { @@ -210,3 +213,42 @@ export type LoaderOptions = { pseudoClasses?: PseudoClasses; unusedSymbols?: string[]; }; + +export const getLightningcssLoaderOptions: GetLoaderOptions = ( + o, + composeOptions, +) => { + const options = o ?? {}; + if (typeof options === 'object') { + if (typeof options.targets === 'string') { + options.targets = [options.targets]; + } else if ( + typeof options.targets === 'object' && + !Array.isArray(options.targets) + ) { + options.targets = encodeTargets(options.targets); + } else if ( + options.targets === undefined && + composeOptions.compiler.target?.platforms + ) { + // Default target derived from rspack target + options.targets = resolveDefaultLightningCssTargets( + composeOptions.compiler.target.platforms, + ); + } + + if (options.include && typeof options.include === 'object') { + options.include = toFeatures( + options.include as unknown as FeatureOptions, + ); + } + + if (options.exclude && typeof options.exclude === 'object') { + options.exclude = toFeatures( + options.exclude as unknown as FeatureOptions, + ); + } + } + + return options; +}; diff --git a/packages/rspack/src/builtin-loader/lightningcss/target.ts b/packages/rspack/src/builtin-loader/lightningcss/target.ts new file mode 100644 index 000000000000..a2d8f749532e --- /dev/null +++ b/packages/rspack/src/builtin-loader/lightningcss/target.ts @@ -0,0 +1,44 @@ +import type binding from '@rspack/binding'; +import { encodeVersion } from '../../util/targetVersion'; +import type { Targets } from './index'; + +const REMAP: Record = { + and_chr: 'chrome', + and_ff: 'firefox', + ie_mob: 'ie', + op_mob: 'opera', + and_qq: null, + and_uc: null, + baidu: null, + bb: null, + kaios: null, + op_mini: null, +}; + +export const resolveDefaultLightningCssTargets = ( + platforms: string[], +): binding.RawLightningCssBrowsers => { + const targets: Record = {}; + for (const p of platforms) { + const [n, v] = p.split(' '); + const remap = REMAP[n]; + if (remap === null) continue; + + const name = remap || n; + const version = encodeVersion(v); + if (version === null) continue; + + if (!targets[name] || version < targets[name]) { + targets[name] = version; + } + } + return targets; +}; + +export const encodeTargets = ( + targets: Targets, +): binding.RawLightningCssBrowsers => { + return Object.fromEntries( + Object.entries(targets).map(([k, v]) => [k, encodeVersion(v)]), + ); +}; diff --git a/packages/rspack/src/builtin-loader/swc/index.ts b/packages/rspack/src/builtin-loader/swc/index.ts index aa0d5c633687..4215f2d4486d 100644 --- a/packages/rspack/src/builtin-loader/swc/index.ts +++ b/packages/rspack/src/builtin-loader/swc/index.ts @@ -1,8 +1,11 @@ +import type { GetLoaderOptions } from '../../config/adapterRuleUse'; +import { deprecate } from '../../util'; +import { resolveCollectTypeScriptInfo } from './collectTypeScriptInfo'; +import { resolvePluginImport } from './pluginImport'; +import { resolveDefaultSwcTargets } from './target'; + export type { CollectTypeScriptInfoOptions } from './collectTypeScriptInfo'; -export { resolveCollectTypeScriptInfo } from './collectTypeScriptInfo'; export type { PluginImportOptions } from './pluginImport'; -export { resolvePluginImport } from './pluginImport'; - export type { SwcLoaderEnvConfig, SwcLoaderEsParserConfig, @@ -13,3 +16,59 @@ export type { SwcLoaderTransformConfig, SwcLoaderTsParserConfig, } from './types'; + +export const getSwcLoaderOptions: GetLoaderOptions = (o, composeOptions) => { + const options = o ?? {}; + if (typeof options === 'object') { + // enable `disableAllLints` by default to reduce performance overhead + options.jsc ??= {}; + options.jsc.experimental ??= {}; + options.jsc.experimental.disableAllLints ??= true; + + // Default target derived from rspack target + if ( + options.env?.targets === undefined && + options.jsc?.target === undefined + ) { + if (composeOptions.compiler.target?.platforms) { + const { platforms } = composeOptions.compiler.target; + options.env ??= {}; + options.env.targets ??= resolveDefaultSwcTargets(platforms); + } else if (composeOptions.compiler.target?.esVersion) { + const { esVersion } = composeOptions.compiler.target; + options.jsc.target ??= esVersion >= 2015 ? `es${esVersion}` : 'es5'; + } + } + + // resolve top-level `collectTypeScriptInfo` options (stable API) + if (options.collectTypeScriptInfo) { + options.collectTypeScriptInfo = resolveCollectTypeScriptInfo( + options.collectTypeScriptInfo, + ); + } + + // resolve `rspackExperiments.import` options + const { rspackExperiments } = options; + if (rspackExperiments) { + if (rspackExperiments.import || rspackExperiments.pluginImport) { + rspackExperiments.import = resolvePluginImport( + rspackExperiments.import || rspackExperiments.pluginImport, + ); + } + if (rspackExperiments.collectTypeScriptInfo) { + deprecate( + '`rspackExperiments.collectTypeScriptInfo` is deprecated and will be removed in Rspack v2.0. Use top-level `collectTypeScriptInfo` instead.', + ); + // If top-level is not set, use rspackExperiments config + if (!options.collectTypeScriptInfo) { + options.collectTypeScriptInfo = resolveCollectTypeScriptInfo( + rspackExperiments.collectTypeScriptInfo, + ); + } + // Remove from rspackExperiments to avoid duplication + delete rspackExperiments.collectTypeScriptInfo; + } + } + } + return options; +}; diff --git a/packages/rspack/src/builtin-loader/swc/target.ts b/packages/rspack/src/builtin-loader/swc/target.ts new file mode 100644 index 000000000000..0e6a0563b325 --- /dev/null +++ b/packages/rspack/src/builtin-loader/swc/target.ts @@ -0,0 +1,36 @@ +import { decodeVersion, encodeVersion } from '../../util/targetVersion'; + +const REMAP: Record = { + and_chr: 'chrome', + and_ff: 'firefox', + ie_mob: 'ie', + ios_saf: 'ios', + op_mob: 'opera', + and_qq: null, + and_uc: null, + baidu: null, + bb: null, + kaios: null, + op_mini: null, +}; + +export const resolveDefaultSwcTargets = (platforms: string[]) => { + const targets: Record = {}; + for (const p of platforms) { + const [n, v] = p.split(' '); + const remap = REMAP[n]; + if (remap === null) { + continue; + } + const name = remap || n; + const version = encodeVersion(v); + if (version === null) continue; + + if (!targets[name] || version < targets[name]) { + targets[name] = version; + } + } + return Object.fromEntries( + Object.entries(targets).map(([k, v]) => [k, decodeVersion(v)]), + ); +}; diff --git a/packages/rspack/src/builtin-plugin/LightningCssMinimizerRspackPlugin.ts b/packages/rspack/src/builtin-plugin/LightningCssMinimizerRspackPlugin.ts index b9b05ddbfeca..daed1c3831b5 100644 --- a/packages/rspack/src/builtin-plugin/LightningCssMinimizerRspackPlugin.ts +++ b/packages/rspack/src/builtin-plugin/LightningCssMinimizerRspackPlugin.ts @@ -1,15 +1,21 @@ import { BuiltinPluginName, + type RawLightningCssMinimizerOptions, type RawLightningCssMinimizerRspackPluginOptions, } from '@rspack/binding'; - import { type Drafts, type FeatureOptions, type NonStandard, type PseudoClasses, + type Targets, toFeatures, } from '../builtin-loader/lightningcss'; +import { + encodeTargets, + resolveDefaultLightningCssTargets, +} from '../builtin-loader/lightningcss/target'; +import type { Compiler } from '../Compiler'; import type { AssetConditions } from '../util/assetCondition'; import { create } from './base'; @@ -20,7 +26,7 @@ export type LightningCssMinimizerRspackPluginOptions = { removeUnusedLocalIdents?: boolean; minimizerOptions?: { errorRecovery?: boolean; - targets?: string[] | string; + targets?: string[] | string | Targets; include?: FeatureOptions; exclude?: FeatureOptions; drafts?: Drafts; @@ -32,12 +38,26 @@ export type LightningCssMinimizerRspackPluginOptions = { export const LightningCssMinimizerRspackPlugin = create( BuiltinPluginName.LightningCssMinimizerRspackPlugin, - ( + function ( + this: Compiler, options?: LightningCssMinimizerRspackPluginOptions, - ): RawLightningCssMinimizerRspackPluginOptions => { + ): RawLightningCssMinimizerRspackPluginOptions { const { include, exclude, nonStandard, pseudoClasses, drafts } = options?.minimizerOptions ?? {}; - const targets = options?.minimizerOptions?.targets ?? 'fully supports es6'; // last not support es module chrome version + let targets: RawLightningCssMinimizerOptions['targets'] = [ + 'fully supports es6', + ]; + if (options?.minimizerOptions?.targets) { + if (typeof options.minimizerOptions.targets === 'string') + targets = [options.minimizerOptions.targets]; + else if (Array.isArray(options.minimizerOptions.targets)) + targets = options.minimizerOptions.targets; + else if (typeof options.minimizerOptions.targets === 'object') + targets = encodeTargets(options.minimizerOptions.targets); + } else if (this.target.platforms) { + // Default target derived from rspack target + targets = resolveDefaultLightningCssTargets(this.target.platforms); + } return { test: options?.test, include: options?.include, @@ -48,7 +68,7 @@ export const LightningCssMinimizerRspackPlugin = create( unusedSymbols: options?.minimizerOptions?.unusedSymbols ?? [], include: include ? toFeatures(include) : undefined, exclude: exclude ? toFeatures(exclude) : undefined, - targets: typeof targets === 'string' ? [targets] : targets, + targets, drafts: drafts ? { customMedia: drafts.customMedia ?? false } : undefined, diff --git a/packages/rspack/src/builtin-plugin/SwcJsMinimizerPlugin.ts b/packages/rspack/src/builtin-plugin/SwcJsMinimizerPlugin.ts index 5b5c060b05f3..4055ec9a74c1 100644 --- a/packages/rspack/src/builtin-plugin/SwcJsMinimizerPlugin.ts +++ b/packages/rspack/src/builtin-plugin/SwcJsMinimizerPlugin.ts @@ -4,6 +4,7 @@ import { type RawSwcJsMinimizerRspackPluginOptions, } from '@rspack/binding'; +import type { Compiler } from '../Compiler'; import type { LiteralUnion } from '../config'; import type { AssetConditions } from '../util/assetCondition'; import { create } from './base'; @@ -270,12 +271,17 @@ function getRawExtractCommentsOptions( export const SwcJsMinimizerRspackPlugin = create( BuiltinPluginName.SwcJsMinimizerRspackPlugin, - ( + function ( + this: Compiler, options?: SwcJsMinimizerRspackPluginOptions, - ): RawSwcJsMinimizerRspackPluginOptions => { + ): RawSwcJsMinimizerRspackPluginOptions { let compress = options?.minimizerOptions?.compress ?? true; const mangle = options?.minimizerOptions?.mangle ?? true; - const ecma = options?.minimizerOptions?.ecma ?? 5; + const ecma = + options?.minimizerOptions?.ecma ?? + // Default target derived from rspack target + this.target?.esVersion ?? + 5; const format = { comments: false, // terser and swc use different default value: 'some' ...options?.minimizerOptions?.format, diff --git a/packages/rspack/src/config/adapterRuleUse.ts b/packages/rspack/src/config/adapterRuleUse.ts index 7b82a9493c88..6b6959ada0f6 100644 --- a/packages/rspack/src/config/adapterRuleUse.ts +++ b/packages/rspack/src/config/adapterRuleUse.ts @@ -1,12 +1,6 @@ import type { AssetInfo, RawModuleRuleUse, RawOptions } from '@rspack/binding'; -import { - resolveCollectTypeScriptInfo, - resolvePluginImport, -} from '../builtin-loader'; -import { - type FeatureOptions, - toFeatures, -} from '../builtin-loader/lightningcss'; +import { getLightningcssLoaderOptions } from '../builtin-loader/lightningcss'; +import { getSwcLoaderOptions } from '../builtin-loader/swc'; import type { Compilation } from '../Compilation'; import type { Compiler } from '../Compiler'; import { type LoaderObject, parsePathQueryFragment } from '../loader-runner'; @@ -487,56 +481,11 @@ export function createRawModuleRuleUses( return createRawModuleRuleUsesImpl(allUses, path, options); } -type GetLoaderOptions = ( +export type GetLoaderOptions = ( o: RuleSetLoaderWithOptions['options'], options: ComposeJsUseOptions, ) => RuleSetLoaderWithOptions['options']; -const getSwcLoaderOptions: GetLoaderOptions = (options, _) => { - if (options && typeof options === 'object') { - // enable `disableAllLints` by default to reduce performance overhead - options.jsc ??= {}; - options.jsc.experimental ??= {}; - options.jsc.experimental.disableAllLints ??= true; - - // resolve top-level `collectTypeScriptInfo` options (stable API) - if (options.collectTypeScriptInfo) { - options.collectTypeScriptInfo = resolveCollectTypeScriptInfo( - options.collectTypeScriptInfo, - ); - } - - // resolve `rspackExperiments.import` options - const { rspackExperiments } = options; - if (rspackExperiments) { - if (rspackExperiments.import || rspackExperiments.pluginImport) { - rspackExperiments.import = resolvePluginImport( - rspackExperiments.import || rspackExperiments.pluginImport, - ); - } - } - } - return options; -}; - -const getLightningcssLoaderOptions: GetLoaderOptions = (o, _) => { - if (o && typeof o === 'object') { - if (typeof o.targets === 'string') { - o.targets = [o.targets]; - } - - if (o.include && typeof o.include === 'object') { - o.include = toFeatures(o.include as unknown as FeatureOptions); - } - - if (o.exclude && typeof o.exclude === 'object') { - o.exclude = toFeatures(o.exclude as unknown as FeatureOptions); - } - } - - return o; -}; - function getBuiltinLoaderOptions( identifier: string, o: RuleSetLoaderWithOptions['options'], diff --git a/packages/rspack/src/config/defaults.ts b/packages/rspack/src/config/defaults.ts index 4c4007d8ef1d..9f26f759e9b2 100644 --- a/packages/rspack/src/config/defaults.ts +++ b/packages/rspack/src/config/defaults.ts @@ -65,7 +65,7 @@ export const applyRspackOptionsDefaults = ( throw new Error('target should not be nil after defaults'); } - const targetProperties = + const targetProperties: false | TargetProperties = target === false ? (false as const) : typeof target === 'string' @@ -127,6 +127,7 @@ export const applyRspackOptionsDefaults = ( applyExternalsPresetsDefaults(options.externalsPresets, { targetProperties, buildHttp: Boolean(options.experiments.buildHttp), + outputModule: options.output.module!, }); F(options, 'externalsType', () => { @@ -174,19 +175,20 @@ export const applyRspackOptionsDefaults = ( options.resolveLoader, ); - return { - platform: - targetProperties === false - ? targetProperties - : { - web: targetProperties.web, - browser: targetProperties.browser, - webworker: targetProperties.webworker, - node: targetProperties.node, - nwjs: targetProperties.nwjs, - electron: targetProperties.electron, - }, - }; + return targetProperties === false + ? targetProperties + : { + platform: { + web: targetProperties.web, + browser: targetProperties.browser, + webworker: targetProperties.webworker, + node: targetProperties.node, + nwjs: targetProperties.nwjs, + electron: targetProperties.electron, + }, + esVersion: targetProperties.esVersion, + platforms: targetProperties.platforms, + }; }; export const applyRspackOptionsBaseDefaults = ( @@ -309,7 +311,7 @@ const applyModuleDefaults = ( cache: boolean; asyncWebAssembly: boolean; css?: boolean; - targetProperties: any; + targetProperties: false | TargetProperties; mode?: Mode; uniqueName?: string; deferImport?: boolean; @@ -544,7 +546,7 @@ const applyOutputDefaults = ( }: { context: Context; outputModule?: boolean; - targetProperties: any; + targetProperties: false | TargetProperties; isAffectedByBrowserslist: boolean; entry: EntryNormalized; }, @@ -593,11 +595,17 @@ const applyOutputDefaults = ( F(output, 'module', () => !!outputModule); const environment = output.environment!; - const optimistic = (v?: boolean) => v || v === undefined; - const conditionallyOptimistic = (v?: boolean, c?: boolean) => + + // For old features we optimistically assume user's target already support it + const optimistic = (v?: boolean | null) => v || v === undefined; + const conditionallyOptimistic = (v?: boolean | null, c?: boolean) => (v === undefined && c) || v; - F(environment, 'globalThis', () => tp?.globalThis); + F( + environment, + 'globalThis', + () => tp && (tp.globalThis as boolean | undefined), + ); F(environment, 'bigIntLiteral', () => tp && optimistic(tp.bigIntLiteral)); F(environment, 'const', () => tp && optimistic(tp.const)); // IGNORE(output.environment.methodShorthand): will align method shorthand optimization for webpack soon @@ -619,19 +627,36 @@ const applyOutputDefaults = ( F( environment, 'importMetaDirnameAndFilename', - () => - // No optimistic, because it is new - tp?.importMetaDirnameAndFilename, + // No optimistic, because it is new + () => tp && (tp.importMetaDirnameAndFilename as boolean | undefined), ); F(environment, 'templateLiteral', () => tp && optimistic(tp.templateLiteral)); - F(environment, 'dynamicImport', () => - conditionallyOptimistic(tp?.dynamicImport, output.module), + F( + environment, + 'dynamicImport', + () => + tp && + (conditionallyOptimistic(tp.dynamicImport, output.module) as + | boolean + | undefined), ); - F(environment, 'dynamicImportInWorker', () => - conditionallyOptimistic(tp?.dynamicImportInWorker, output.module), + F( + environment, + 'dynamicImportInWorker', + () => + tp && + (conditionallyOptimistic(tp.dynamicImportInWorker, output.module) as + | boolean + | undefined), ); - F(environment, 'module', () => - conditionallyOptimistic(tp?.module, output.module), + F( + environment, + 'module', + () => + tp && + (conditionallyOptimistic(tp.module, output.module) as + | boolean + | undefined), ); F(environment, 'document', () => tp && optimistic(tp.document)); @@ -887,27 +912,60 @@ const applyExternalsPresetsDefaults = ( { targetProperties, buildHttp, - }: { targetProperties: any; buildHttp: boolean }, + outputModule, + }: { + targetProperties: false | TargetProperties; + buildHttp: boolean; + outputModule: boolean; + }, ) => { - D(externalsPresets, 'web', !buildHttp && targetProperties?.web); - D(externalsPresets, 'node', targetProperties?.node); - D(externalsPresets, 'electron', targetProperties?.electron); + const isUniversal = (key: keyof TargetProperties) => + Boolean(outputModule && targetProperties && targetProperties[key] === null); + + D( + externalsPresets, + 'web', + !buildHttp && + targetProperties && + (targetProperties.web || isUniversal('node')), + ); + D( + externalsPresets, + 'node', + targetProperties && (targetProperties.node || isUniversal('node')), + ); + D( + externalsPresets, + 'electron', + // biome-ignore lint/complexity/useOptionalChain: change to optionalChain will have type error + (targetProperties && targetProperties.electron) || isUniversal('electron'), + ); D( externalsPresets, 'electronMain', - targetProperties?.electron && targetProperties.electronMain, + targetProperties && + !!targetProperties.electron && + (targetProperties.electronMain || isUniversal('electronMain')), ); D( externalsPresets, 'electronPreload', - targetProperties?.electron && targetProperties.electronPreload, + targetProperties && + !!targetProperties.electron && + (targetProperties.electronPreload || isUniversal('electronPreload')), ); D( externalsPresets, 'electronRenderer', - targetProperties?.electron && targetProperties.electronRenderer, + targetProperties && + !!targetProperties.electron && + (targetProperties.electronRenderer || isUniversal('electronRenderer')), + ); + D( + externalsPresets, + 'nwjs', + targetProperties && (targetProperties.nwjs || isUniversal('nwjs')), ); - D(externalsPresets, 'nwjs', targetProperties?.nwjs); }; const applyLoaderDefaults = ( @@ -915,7 +973,7 @@ const applyLoaderDefaults = ( { targetProperties, environment, - }: { targetProperties: any; environment: any }, + }: { targetProperties: false | TargetProperties; environment: any }, ) => { F(loader, 'target', () => { if (targetProperties) { @@ -938,24 +996,27 @@ const applyNodeDefaults = ( { outputModule, targetProperties, - }: { targetProperties: any; outputModule?: boolean }, + }: { targetProperties: false | TargetProperties; outputModule?: boolean }, ) => { if (node === false) return; // IGNORE(node.global): The default value of `global` is determined by `futureDefaults` in webpack. F(node, 'global', () => { - if (targetProperties?.global) return false; + // biome-ignore lint/complexity/useOptionalChain: change to optionalChain will have type error + if (targetProperties && targetProperties.global) return false; return 'warn'; }); // IGNORE(node.__dirname): The default value of `__dirname` is determined by `futureDefaults` in webpack. F(node, '__dirname', () => { - if (targetProperties?.node) + // biome-ignore lint/complexity/useOptionalChain: change to optionalChain will have type error + if (targetProperties && targetProperties.node) return outputModule ? 'node-module' : 'eval-only'; return 'warn-mock'; }); // IGNORE(node.__filename): The default value of `__filename` is determined by `futureDefaults` in webpack. F(node, '__filename', () => { - if (targetProperties?.node) + // biome-ignore lint/complexity/useOptionalChain: change to optionalChain will have type error + if (targetProperties && targetProperties.node) return outputModule ? 'node-module' : 'eval-only'; return 'warn-mock'; }); @@ -1079,7 +1140,7 @@ const getResolveDefaults = ({ css, }: { context: string; - targetProperties: any; + targetProperties: false | TargetProperties; mode?: Mode; css: boolean; }) => { @@ -1099,7 +1160,8 @@ const getResolveDefaults = ({ const tp = targetProperties; const browserField = - tp?.web && (!tp.node || (tp.electron && tp.electronRenderer)); + // biome-ignore lint/complexity/useOptionalChain: change to optionalChain will have type error + tp && tp.web && (!tp.node || (tp.electron && tp.electronRenderer)); const aliasFields = browserField ? ['browser'] : []; const mainFields = browserField ? ['browser', 'module', '...'] diff --git a/packages/rspack/src/config/target.ts b/packages/rspack/src/config/target.ts index 454dfb9ef21d..2f12efdfab1b 100644 --- a/packages/rspack/src/config/target.ts +++ b/packages/rspack/src/config/target.ts @@ -1,5 +1,3 @@ -import { createRequire } from 'node:module'; -import binding from '@rspack/binding'; /** * The following code is modified based on * https://github.com/webpack/webpack/blob/4b4ca3b/lib/config/target.js @@ -9,6 +7,9 @@ import binding from '@rspack/binding'; * Copyright (c) JS Foundation and other contributors * https://github.com/webpack/webpack/blob/main/LICENSE */ + +import { createRequire } from 'node:module'; +import binding from '@rspack/binding'; import { memoize } from '../util/memoize'; import * as browserslistTargetHandler from './browserslistTargetHandler'; @@ -103,13 +104,10 @@ export type EcmaTargetProperties = { asyncFunction: boolean | null; }; -// type TargetProperties = -// | PlatformTargetProperties -// | ApiTargetProperties -// | EcmaTargetProperties -// | (PlatformTargetProperties & ApiTargetProperties) -// | (PlatformTargetProperties & EcmaTargetProperties) -// | (ApiTargetProperties & EcmaTargetProperties); +export type ExtractedTargetProperties = { + esVersion?: number | null; + platforms?: string[] | null; +}; type Never = { [P in keyof T]?: never }; type Mix = (A & Never) | (Never & B) | (A & B); @@ -117,7 +115,85 @@ type Mix = (A & Never) | (Never & B) | (A & B); export type TargetProperties = Mix< Mix, Mix ->; +> & + ExtractedTargetProperties; + +// modify based on https://github.com/rstackjs/browserslist-to-es-version/blob/a6c1be0afef412fc288d6a2214d307e8f2e647cf/src/index.ts +function browsersToESVersion(browsers: string[]) { + // The minimal version for [es2015, es2016, es2017, es2018, es2019, es2020, es2021, es2022] + const ES_VERSIONS_MAP: Record = { + chrome: [51, 52, 57, 64, 73, 80, 85, 94], + edge: [15, 15, 15, 79, 79, 80, 85, 94], + safari: [10, 10.3, 11, 16.4, 17, 17, 17, 17], + firefox: [54, 54, 54, 78, 78, 80, 80, 93], + opera: [38, 39, 44, 51, 60, 67, 71, 80], + samsung: [5, 6.2, 6.2, 8.2, 11.1, 13, 14, 17], + }; + + const aliases: Record = { + ios_saf: 'safari', + and_chr: 'chrome', + and_ff: 'firefox', + }; + + const renameBrowser = (name: string) => { + return aliases[name] || name; + }; + + // SWC minifier only supports up to 2022 + let esVersion = 2022; + + for (const item of browsers) { + const pairs = item.split(' '); + + // skip invalid item + if (pairs.length < 2) { + continue; + } + + const browser = renameBrowser(pairs[0]); + const version = Number(pairs[1].split('-')[0]); + + // ignore unknown version + if (Number.isNaN(version)) { + continue; + } + + // IE / Android 4.x ~ 5.x only supports es5 + if (browser === 'ie' || (browser === 'android' && version < 6)) { + esVersion = 5; + break; + } + + // skip unknown browsers + const versions = ES_VERSIONS_MAP[browser]; + if (!versions) { + continue; + } + + if (version < versions[0]) { + esVersion = Math.min(5, esVersion); + } else if (version < versions[1]) { + esVersion = Math.min(2015, esVersion); + } else if (version < versions[2]) { + esVersion = Math.min(2016, esVersion); + } else if (version < versions[3]) { + esVersion = Math.min(2017, esVersion); + } else if (version < versions[4]) { + esVersion = Math.min(2018, esVersion); + } else if (version < versions[5]) { + esVersion = Math.min(2019, esVersion); + } else if (version < versions[6]) { + esVersion = Math.min(2020, esVersion); + } else if (version < versions[7]) { + esVersion = Math.min(2021, esVersion); + } else if (version < versions[8]) { + esVersion = Math.min(2022, esVersion); + } + } + + return esVersion; +} /** * @param major major version @@ -172,7 +248,11 @@ You can also more options via the 'target' option: 'browserslist' / 'browserslis } const browserslistTargetHandler = getBrowserslistTargetHandler(); - return browserslistTargetHandler.resolve(browsers); + return { + ...browserslistTargetHandler.resolve(browsers), + platforms: browsers, + esVersion: browsersToESVersion(browsers), + }; }, ], [ @@ -236,6 +316,26 @@ You can also more options via the 'target' option: 'browserslist' / 'browserslis webworker: false, browser: false, + platforms: major ? [`node ${major}${minor ? `.${minor}` : ''}`] : [], + // https://github.com/microsoft/TypeScript/wiki/Node-Target-Mapping + esVersion: v(18) + ? 2022 + : v(16) + ? 2021 + : v(14) + ? 2020 + : v(12) + ? 2019 + : v(10) + ? 2018 + : v(8) + ? 2017 + : v(7) + ? 2016 + : v(6, 5) + ? 2015 + : 5, + require: !asyncFlag, nodeBuiltins: true, // v16.0.0, v14.18.0 @@ -271,7 +371,7 @@ You can also more options via the 'target' option: 'browserslist' / 'browserslis /^electron((\d+)(?:\.(\d+))?)?-(main|preload|renderer)$/, (_, major, minor, context) => { const v = versionDependent(major, minor); - // see https://node.green/ + https://github.com/electron/releases + // see https://node.green/ + https://releases.electronjs.org/releases.json return { node: true, electron: true, @@ -284,6 +384,27 @@ You can also more options via the 'target' option: 'browserslist' / 'browserslis electronPreload: context === 'preload', electronRenderer: context === 'renderer', + platforms: major + ? [`electron ${major}${minor ? `.${minor}` : ''}`] + : [], + esVersion: v(23) + ? 2022 + : v(15) + ? 2021 + : v(12) + ? 2020 + : v(5) + ? 2019 + : v(3) + ? 2018 + : v(1, 8) + ? 2017 + : v(1, 5) + ? 2016 + : v(1, 4) + ? 2015 + : 5, + global: true, nodeBuiltins: true, // 15.0.0 - Node.js v16.5 @@ -320,7 +441,7 @@ You can also more options via the 'target' option: 'browserslist' / 'browserslis /^(?:nwjs|node-webkit)((\d+)(?:\.(\d+))?)?$/, (_, major, minor) => { const v = versionDependent(major, minor); - // see https://node.green/ + https://github.com/nwjs/nw.js/blob/nw48/CHANGELOG.md + // see https://node.green/ + https://github.com/nwjs/nw.js/blob/main/CHANGELOG.md return { node: true, web: true, @@ -329,6 +450,25 @@ You can also more options via the 'target' option: 'browserslist' / 'browserslis browser: false, electron: false, + platforms: major ? [`nwjs ${major}${minor ? `.${minor}` : ''}`] : [], + esVersion: v(0, 65) + ? 2022 + : v(0, 54) + ? 2021 + : v(0, 46) + ? 2020 + : v(0, 39) + ? 2019 + : v(0, 31) + ? 2018 + : v(0, 23) + ? 2017 + : v(0, 20) + ? 2016 + : v(0, 17) + ? 2015 + : 5, + global: true, nodeBuiltins: true, document: false, @@ -359,8 +499,10 @@ You can also more options via the 'target' option: 'browserslist' / 'browserslis /^es(\d+)$/, (version) => { let v = +version; - if (v < 1000) v = v + 2009; + if (5 < v && v < 1000) v = v + 2009; return { + // SWC minifier only supports up to 2022 + esVersion: v > 2022 ? 2022 : v, const: v >= 2015, templateLiteral: v >= 2015, optionalChaining: v >= 2020, @@ -379,11 +521,6 @@ You can also more options via the 'target' option: 'browserslist' / 'browserslis ], ]; -/** - * @param target the target - * @param context the context directory - * @returns target properties - */ export const getTargetProperties = ( target: string, context: string, @@ -415,6 +552,31 @@ const mergeTargetProperties = ( const result: Partial = {}; for (const key of keys) { + if (key === 'esVersion') { + let minVersion: number | undefined; + for (const tp of targetProperties) { + if (typeof tp.esVersion === 'number') { + minVersion = + minVersion === undefined + ? tp.esVersion + : Math.min(minVersion, tp.esVersion); + } + } + if (minVersion !== undefined) result[key] = minVersion; + continue; + } + + if (key === 'platforms') { + const merged = new Set(); + for (const tp of targetProperties) { + if (Array.isArray(tp.platforms)) { + for (const p of tp.platforms) merged.add(p); + } + } + if (merged.size > 0) result[key] = Array.from(merged); + continue; + } + let hasTrue = false; let hasFalse = false; for (const tp of targetProperties) { @@ -433,12 +595,10 @@ const mergeTargetProperties = ( return result as TargetProperties; }; -/** - * @param targets the targets - * @param context the context directory - * @returns target properties - */ -export const getTargetsProperties = (targets: string[], context: string) => { +export const getTargetsProperties = ( + targets: string[], + context: string, +): TargetProperties => { return mergeTargetProperties( targets.map((t) => getTargetProperties(t, context)), ); diff --git a/packages/rspack/src/rspack.ts b/packages/rspack/src/rspack.ts index 59d51f6846f0..364c3c2fbb4a 100644 --- a/packages/rspack/src/rspack.ts +++ b/packages/rspack/src/rspack.ts @@ -69,10 +69,11 @@ function createCompiler(userOptions: RspackOptions): Compiler { } } } - const { platform } = applyRspackOptionsDefaults(compiler.options); - if (platform) { - compiler.platform = platform; + const tp = applyRspackOptionsDefaults(compiler.options); + if (tp) { + compiler.platform = tp.platform; + compiler.target = { esVersion: tp.esVersion, platforms: tp.platforms }; } compiler.hooks.environment.call(); diff --git a/packages/rspack/src/util/targetVersion.ts b/packages/rspack/src/util/targetVersion.ts new file mode 100644 index 000000000000..4d213b73d0f4 --- /dev/null +++ b/packages/rspack/src/util/targetVersion.ts @@ -0,0 +1,19 @@ +export function encodeVersion(version: string) { + const [major, minor = 0, patch = 0] = version + .split('-')[0] + .split('.') + .map((v) => parseInt(v, 10)); + + if (Number.isNaN(major) || Number.isNaN(minor) || Number.isNaN(patch)) { + return null; + } + + return (major << 16) | (minor << 8) | patch; +} + +export function decodeVersion(n: number) { + const major = (n >> 16) & 0xff; + const minor = (n >> 8) & 0xff; + const patch = n & 0xff; + return `${major}.${minor}.${patch}`; +} diff --git a/tests/rspack-test/configCases/builtin-lightningcss-loader/default-target-by-rspack-target/index.css b/tests/rspack-test/configCases/builtin-lightningcss-loader/default-target-by-rspack-target/index.css new file mode 100644 index 000000000000..b8d4d6379bf5 --- /dev/null +++ b/tests/rspack-test/configCases/builtin-lightningcss-loader/default-target-by-rspack-target/index.css @@ -0,0 +1,5 @@ +.foo { + -webkit-border-radius: 2px; + -moz-border-radius: 2px; + border-radius: 2px; +} diff --git a/tests/rspack-test/configCases/builtin-lightningcss-loader/default-target-by-rspack-target/index.js b/tests/rspack-test/configCases/builtin-lightningcss-loader/default-target-by-rspack-target/index.js new file mode 100644 index 000000000000..46cf52760c15 --- /dev/null +++ b/tests/rspack-test/configCases/builtin-lightningcss-loader/default-target-by-rspack-target/index.js @@ -0,0 +1,8 @@ +import "./index.css"; + +const css = /** @type {string} */ (__non_webpack_require__("fs").readFileSync(__non_webpack_require__("path").resolve(__dirname, "bundle0.css"), "utf-8")); + +it("should use high-level syntax", () => { + expect(css.includes("-webkit-")).toBe(false); + expect(css.includes("-moz-")).toBe(false); +}); diff --git a/tests/rspack-test/configCases/builtin-lightningcss-loader/default-target-by-rspack-target/rspack.config.js b/tests/rspack-test/configCases/builtin-lightningcss-loader/default-target-by-rspack-target/rspack.config.js new file mode 100644 index 000000000000..a128dd1a2151 --- /dev/null +++ b/tests/rspack-test/configCases/builtin-lightningcss-loader/default-target-by-rspack-target/rspack.config.js @@ -0,0 +1,15 @@ +/** @type {import("@rspack/core").Configuration} */ +module.exports = { + target: ["web", "browserslist:chrome > 95"], + module: { + rules: [ + { + test: /\.css$/, + use: "builtin:lightningcss-loader", + } + ] + }, + node: { + __dirname: false, + } +}; diff --git a/tests/rspack-test/configCases/builtin-lightningcss-loader/default-target-override/index.css b/tests/rspack-test/configCases/builtin-lightningcss-loader/default-target-override/index.css new file mode 100644 index 000000000000..b8d4d6379bf5 --- /dev/null +++ b/tests/rspack-test/configCases/builtin-lightningcss-loader/default-target-override/index.css @@ -0,0 +1,5 @@ +.foo { + -webkit-border-radius: 2px; + -moz-border-radius: 2px; + border-radius: 2px; +} diff --git a/tests/rspack-test/configCases/builtin-lightningcss-loader/default-target-override/index.js b/tests/rspack-test/configCases/builtin-lightningcss-loader/default-target-override/index.js new file mode 100644 index 000000000000..1cbdd3adbd05 --- /dev/null +++ b/tests/rspack-test/configCases/builtin-lightningcss-loader/default-target-override/index.js @@ -0,0 +1,8 @@ +import "./index.css"; + +const css = /** @type {string} */ (__non_webpack_require__("fs").readFileSync(__non_webpack_require__("path").resolve(__dirname, "bundle0.css"), "utf-8")); + +it("should use low-level syntax", () => { + expect(css.includes("-webkit-")).toBe(true); + expect(css.includes("-moz-")).toBe(false); +}); diff --git a/tests/rspack-test/configCases/builtin-lightningcss-loader/default-target-override/rspack.config.js b/tests/rspack-test/configCases/builtin-lightningcss-loader/default-target-override/rspack.config.js new file mode 100644 index 000000000000..84723c5e78ac --- /dev/null +++ b/tests/rspack-test/configCases/builtin-lightningcss-loader/default-target-override/rspack.config.js @@ -0,0 +1,20 @@ +/** @type {import("@rspack/core").Configuration} */ +module.exports = { + target: ["web", "browserslist:chrome > 95"], + module: { + rules: [ + { + test: /\.css$/, + use: { + loader: "builtin:lightningcss-loader", + options: { + targets: "safari >= 4" + } + }, + } + ] + }, + node: { + __dirname: false, + } +}; diff --git a/tests/rspack-test/configCases/builtin-swc-loader/default-target-by-rspack-target/index.js b/tests/rspack-test/configCases/builtin-swc-loader/default-target-by-rspack-target/index.js new file mode 100644 index 000000000000..915a89546a26 --- /dev/null +++ b/tests/rspack-test/configCases/builtin-swc-loader/default-target-by-rspack-target/index.js @@ -0,0 +1,11 @@ +const generated = /** @type {string} */ (__non_webpack_require__("fs").readFileSync(__filename, "utf-8")); + +it("should use high-level syntax", () => { + // START:A + const a = [1, 2, 3]; + const b = [...a]; + // END:A + const block = generated.match(/\/\/ START:A([\s\S]*)\/\/ END:A/)[1]; + expect(a).toEqual(b); + expect(block.includes("...a")).toBe(true); +}); diff --git a/tests/rspack-test/configCases/builtin-swc-loader/default-target-by-rspack-target/rspack.config.js b/tests/rspack-test/configCases/builtin-swc-loader/default-target-by-rspack-target/rspack.config.js new file mode 100644 index 000000000000..039d159ac46d --- /dev/null +++ b/tests/rspack-test/configCases/builtin-swc-loader/default-target-by-rspack-target/rspack.config.js @@ -0,0 +1,12 @@ +/** @type {import("@rspack/core").Configuration} */ +module.exports = { + target: ["async-node", "browserslist:node > 16"], + module: { + rules: [ + { + test: /\.js$/, + use: "builtin:swc-loader", + } + ] + } +}; diff --git a/tests/rspack-test/configCases/builtin-swc-loader/default-target-override/index.js b/tests/rspack-test/configCases/builtin-swc-loader/default-target-override/index.js new file mode 100644 index 000000000000..99e0cd2a7c27 --- /dev/null +++ b/tests/rspack-test/configCases/builtin-swc-loader/default-target-override/index.js @@ -0,0 +1,11 @@ +const generated = /** @type {string} */ (__non_webpack_require__("fs").readFileSync(__filename, "utf-8")); + +it("should use low-level syntax", () => { + // START:A + const a = [1, 2, 3]; + const b = [...a]; + // END:A + const block = generated.match(/\/\/ START:A([\s\S]*)\/\/ END:A/)[1]; + expect(a).toEqual(b); + expect(block.includes("...a")).toBe(false); +}); diff --git a/tests/rspack-test/configCases/builtin-swc-loader/default-target-override/rspack.config.js b/tests/rspack-test/configCases/builtin-swc-loader/default-target-override/rspack.config.js new file mode 100644 index 000000000000..4a52d7687f91 --- /dev/null +++ b/tests/rspack-test/configCases/builtin-swc-loader/default-target-override/rspack.config.js @@ -0,0 +1,19 @@ +/** @type {import("@rspack/core").Configuration} */ +module.exports = { + target: ["async-node", "browserslist:node > 16"], + module: { + rules: [ + { + test: /\.js$/, + use: { + loader: "builtin:swc-loader", + options: { + env: { + targets: "node >= 4", + } + } + }, + } + ] + } +}; diff --git a/tests/rspack-test/configCases/plugins/minify-default-target-by-rspack-target/index.css b/tests/rspack-test/configCases/plugins/minify-default-target-by-rspack-target/index.css new file mode 100644 index 000000000000..b8d4d6379bf5 --- /dev/null +++ b/tests/rspack-test/configCases/plugins/minify-default-target-by-rspack-target/index.css @@ -0,0 +1,5 @@ +.foo { + -webkit-border-radius: 2px; + -moz-border-radius: 2px; + border-radius: 2px; +} diff --git a/tests/rspack-test/configCases/plugins/minify-default-target-by-rspack-target/index.js b/tests/rspack-test/configCases/plugins/minify-default-target-by-rspack-target/index.js new file mode 100644 index 000000000000..05126b4dcc4c --- /dev/null +++ b/tests/rspack-test/configCases/plugins/minify-default-target-by-rspack-target/index.js @@ -0,0 +1,15 @@ +import "./index.css"; + +it("should use high-level css syntax", () => { + const css = /** @type {string} */ (__non_webpack_require__("fs").readFileSync(__non_webpack_require__("path").resolve(__dirname, "bundle0.css"), "utf-8")); + expect(css.includes("-webkit-")).toBe(false); + expect(css.includes("-moz-")).toBe(false); +}); + +it("should use high-level js syntax", () => { + const js = /** @type {string} */ (__non_webpack_require__("fs").readFileSync(__filename, "utf-8")); + const a = [1, 2, 3]; + const b = [...a]; + expect(a).toEqual(b); + expect(js.includes(".".repeat(3))).toBe(true); +}); diff --git a/tests/rspack-test/configCases/plugins/minify-default-target-by-rspack-target/rspack.config.js b/tests/rspack-test/configCases/plugins/minify-default-target-by-rspack-target/rspack.config.js new file mode 100644 index 000000000000..c677fe9b6034 --- /dev/null +++ b/tests/rspack-test/configCases/plugins/minify-default-target-by-rspack-target/rspack.config.js @@ -0,0 +1,11 @@ +/** @type {import("@rspack/core").Configuration} */ +module.exports = { + target: ["web", "browserslist:chrome > 95"], + node: { + __dirname: false, + __filename: false, + }, + optimization: { + minimize: true, + }, +}; diff --git a/tests/rspack-test/configCases/plugins/minify-default-target-override/deopt.js b/tests/rspack-test/configCases/plugins/minify-default-target-override/deopt.js new file mode 100644 index 000000000000..18b3f6dcb4b5 --- /dev/null +++ b/tests/rspack-test/configCases/plugins/minify-default-target-override/deopt.js @@ -0,0 +1,4 @@ +export function deopt(o) { + console.log(o); + return o; +} diff --git a/tests/rspack-test/configCases/plugins/minify-default-target-override/index.css b/tests/rspack-test/configCases/plugins/minify-default-target-override/index.css new file mode 100644 index 000000000000..b8d4d6379bf5 --- /dev/null +++ b/tests/rspack-test/configCases/plugins/minify-default-target-override/index.css @@ -0,0 +1,5 @@ +.foo { + -webkit-border-radius: 2px; + -moz-border-radius: 2px; + border-radius: 2px; +} diff --git a/tests/rspack-test/configCases/plugins/minify-default-target-override/index.js b/tests/rspack-test/configCases/plugins/minify-default-target-override/index.js new file mode 100644 index 000000000000..bdb7b86e134e --- /dev/null +++ b/tests/rspack-test/configCases/plugins/minify-default-target-override/index.js @@ -0,0 +1,15 @@ +import "./index.css"; + +it("should override to high-level css syntax", function () { + const css = /** @type {string} */ (__non_webpack_require__("fs").readFileSync(__non_webpack_require__("path").resolve(__dirname, "bundle0.css"), "utf-8")); + expect(css.includes("-webkit-")).toBe(false); + expect(css.includes("-moz-")).toBe(false); +}); + +it("should override to high-level js syntax", async function () { + const { deopt } = await import("./deopt"); + const js = /** @type {string} */ (__non_webpack_require__("fs").readFileSync(__filename, "utf-8")); + const foo = deopt("foo"); + expect(foo).toBe("foo"); + expect(js.includes(["let", "{deopt:e}", "=", "await"].join())).toBe(true); +}); diff --git a/tests/rspack-test/configCases/plugins/minify-default-target-override/rspack.config.js b/tests/rspack-test/configCases/plugins/minify-default-target-override/rspack.config.js new file mode 100644 index 000000000000..2ceb1b3305be --- /dev/null +++ b/tests/rspack-test/configCases/plugins/minify-default-target-override/rspack.config.js @@ -0,0 +1,25 @@ +const { rspack } = require("@rspack/core"); + +/** @type {import("@rspack/core").Configuration} */ +module.exports = { + target: ["web", "browserslist:safari >= 4"], + node: { + __dirname: false, + __filename: false, + }, + optimization: { + minimize: true, + minimizer: [ + new rspack.SwcJsMinimizerRspackPlugin({ + minimizerOptions: { + ecma: 2020, + } + }), + new rspack.LightningCssMinimizerRspackPlugin({ + minimizerOptions: { + targets: "chrome > 95", + } + }) + ] + }, +};