From 070751310a53b9f75f9921121314c2dc8f5e5ec8 Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Thu, 9 Jan 2025 09:23:38 -0600 Subject: [PATCH 01/18] bundle javascript --- packages/cli-opt/Cargo.toml | 79 +++++--------- packages/cli-opt/src/js.rs | 212 ++++++++++++++++++++++++++++-------- 2 files changed, 195 insertions(+), 96 deletions(-) diff --git a/packages/cli-opt/Cargo.toml b/packages/cli-opt/Cargo.toml index 633e796151..8b772a5bc0 100644 --- a/packages/cli-opt/Cargo.toml +++ b/packages/cli-opt/Cargo.toml @@ -39,57 +39,30 @@ grass = "0.13.4" codemap = "0.1.3" # Js minification - swc has introduces minor versions with breaking changes in the past so we pin all of their crates -swc = "=0.283.0" -swc_allocator = { version = "=0.1.8", default-features = false } -swc_atoms = { version = "=0.6.7", default-features = false } -swc_cached = { version = "=0.3.20", default-features = false } -swc_common = { version = "=0.37.5", default-features = false } -swc_compiler_base = { version = "=0.19.0", default-features = false } -swc_config = { version = "=0.1.15", default-features = false } -swc_config_macro = { version = "=0.1.4", default-features = false } -swc_ecma_ast = { version = "=0.118.2", default-features = false } -swc_ecma_codegen = { version = "=0.155.1", default-features = false } -swc_ecma_codegen_macros = { version = "=0.7.7", default-features = false } -swc_ecma_compat_bugfixes = { version = "=0.12.0", default-features = false } -swc_ecma_compat_common = { version = "=0.11.0", default-features = false } -swc_ecma_compat_es2015 = { version = "=0.12.0", default-features = false } -swc_ecma_compat_es2016 = { version = "=0.12.0", default-features = false } -swc_ecma_compat_es2017 = { version = "=0.12.0", default-features = false } -swc_ecma_compat_es2018 = { version = "=0.12.0", default-features = false } -swc_ecma_compat_es2019 = { version = "=0.12.0", default-features = false } -swc_ecma_compat_es2020 = { version = "=0.12.0", default-features = false } -swc_ecma_compat_es2021 = { version = "=0.12.0", default-features = false } -swc_ecma_compat_es2022 = { version = "=0.12.0", default-features = false } -swc_ecma_compat_es3 = { version = "=0.12.0", default-features = false } -swc_ecma_ext_transforms = { version = "=0.120.0", default-features = false } -swc_ecma_lints = { version = "=0.100.0", default-features = false } -swc_ecma_loader = { version = "=0.49.1", default-features = false } -swc_ecma_minifier = { version = "=0.204.0", default-features = false } -swc_ecma_parser = { version = "=0.149.1", default-features = false } -swc_ecma_preset_env = { version = "=0.217.0", default-features = false, features = [ - "serde", -] } -swc_ecma_transforms = { version = "=0.239.0", default-features = false } -swc_ecma_transforms_base = { version = "=0.145.0", default-features = false } -swc_ecma_transforms_classes = { version = "=0.134.0", default-features = false } -swc_ecma_transforms_compat = { version = "=0.171.0", default-features = false } -swc_ecma_transforms_macros = { version = "=0.5.5", default-features = false } -swc_ecma_transforms_module = { version = "=0.190.0", default-features = false } -swc_ecma_transforms_optimization = { version = "=0.208.0", default-features = false } -swc_ecma_transforms_proposal = { version = "=0.178.0", default-features = false } -swc_ecma_transforms_react = { version = "=0.191.0", default-features = false } -swc_ecma_transforms_typescript = { version = "=0.198.1", default-features = false } -swc_ecma_usage_analyzer = { version = "=0.30.3", default-features = false } -swc_ecma_utils = { version = "=0.134.2", default-features = false } -swc_ecma_visit = { version = "=0.104.8", default-features = false } -swc_eq_ignore_macros = { version = "=0.1.4", default-features = false } -swc_error_reporters = { version = "=0.21.0", default-features = false } -swc_fast_graph = { version = "=0.25.0", default-features = false } -swc_macros_common = { version = "=0.3.13", default-features = false } -swc_node_comments = { version = "=0.24.0", default-features = false } -swc_timer = { version = "=0.25.0", default-features = false } -swc_trace_macro = { version = "=0.1.3", default-features = false } -swc_transform_common = { version = "=0.1.1", default-features = false } -swc_typescript = { version = "=0.5.0", default-features = false } -swc_visit = { version = "=0.6.2", default-features = false } +swc_allocator = { version = "=2.0.0", default-features = false } +swc_atoms = { version = "=3.0.2", default-features = false } +swc_bundler = { version = "=7.0.0", default-features = false } +swc_cached = { version = "=1.0.0", default-features = false } +swc_common = { version = "=5.0.0", features = ["tty-emitter"], default-features = false } +swc_config = { version = "=1.0.0", default-features = false } +swc_config_macro = { version = "=1.0.0", default-features = false } +swc_ecma_ast = { version = "=5.0.1", default-features = false } +swc_ecma_codegen = { version = "=5.0.1", default-features = false } +swc_ecma_codegen_macros = { version = "=1.0.0", default-features = false } +swc_ecma_loader = { version = "=5.0.0", features = ["cache", "node"], default-features = false } +swc_ecma_minifier = { version = "=7.0.1", default-features = false } +swc_ecma_parser = { version = "=6.0.2", default-features = false } +swc_ecma_transforms_base = { version = "=7.0.0", default-features = false } +swc_ecma_transforms_macros = { version = "=1.0.0", default-features = false } +swc_ecma_transforms_optimization = { version = "=7.0.1", default-features = false } +swc_ecma_usage_analyzer = { version = "=7.0.0", default-features = false } +swc_ecma_utils = { version = "=7.0.0", default-features = false } +swc_ecma_visit = { version = "=5.0.0", default-features = false } +swc_eq_ignore_macros = { version = "=1.0.0", default-features = false } +swc_fast_graph = { version = "=6.0.0", default-features = false } +swc_graph_analyzer = { version = "=5.0.0", default-features = false } +swc_macros_common = { version = "=1.0.0", default-features = false } +swc_parallel = { version = "=1.0.1", default-features = false } +swc_timer = { version = "=1.0.0", default-features = false } +swc_visit = { version = "=2.0.0", default-features = false } browserslist-rs = { version = "=0.16.0" } diff --git a/packages/cli-opt/src/js.rs b/packages/cli-opt/src/js.rs index 0dc2b86d06..428e79eb3e 100644 --- a/packages/cli-opt/src/js.rs +++ b/packages/cli-opt/src/js.rs @@ -1,46 +1,170 @@ -use std::io::Read; use std::path::Path; -use std::sync::Arc; +use std::path::PathBuf; use anyhow::Context; use manganis_core::JsAssetOptions; -use swc::{config::JsMinifyOptions, try_with_handler, BoolOrDataConfig}; -use swc_common::{sync::Lrc, FileName}; -use swc_common::{SourceMap, GLOBALS}; +use swc_ecma_minifier::option::{ + CompressOptions, ExtraOptions, MangleOptions, MinifyOptions, TopLevelOptions, +}; +use swc_ecma_transforms_base::fixer::fixer; +use swc_ecma_visit::VisitMutWith; -pub(crate) fn minify_js(source: &Path) -> anyhow::Result { - let mut source_file = std::fs::File::open(source)?; - let cm = Arc::new(SourceMap::default()); - - let mut js = String::new(); - source_file.read_to_string(&mut js)?; - let c = swc::Compiler::new(cm.clone()); - let output = GLOBALS - .set(&Default::default(), || { - try_with_handler(cm.clone(), Default::default(), |handler| { - let filename = Lrc::new(FileName::Real(source.to_path_buf())); - let fm = cm.new_source_file(filename, js.to_string()); - - c.minify( - fm, - handler, - &JsMinifyOptions { - compress: BoolOrDataConfig::from_bool(true), - mangle: BoolOrDataConfig::from_bool(true), +use std::collections::HashMap; + +use anyhow::Error; +use swc_bundler::{Bundler, Config, Load, ModuleData, ModuleRecord}; +use swc_common::{ + errors::HANDLER, sync::Lrc, FileName, FilePathMapping, Globals, Mark, SourceMap, Span, GLOBALS, +}; +use swc_ecma_ast::*; +use swc_ecma_codegen::{text_writer::JsWriter, Emitter}; +use swc_ecma_loader::{resolvers::node::NodeModulesResolver, TargetEnv}; +use swc_ecma_parser::{parse_file_as_module, Syntax}; + +fn bundle_js_to_writer( + file: PathBuf, + minify: bool, + write_to: &mut impl std::io::Write, +) -> anyhow::Result<()> { + let globals = Globals::new(); + let cm = Lrc::new(SourceMap::new(FilePathMapping::empty())); + let node_resolver = NodeModulesResolver::new(TargetEnv::Browser, Default::default(), true); + let mut bundler = Bundler::new( + &globals, + cm.clone(), + PathLoader { cm: cm.clone() }, + node_resolver, + Config { + require: true, + ..Default::default() + }, + Box::new(Hook), + ); + let mut entries = HashMap::default(); + entries.insert("main".to_string(), FileName::Real(file)); + + let mut bundles = bundler + .bundle(entries) + .context("failed to bundle javascript with swc")?; + // Since we only inserted one entry, there should only be one bundle in the output + let bundle = bundles + .pop() + .ok_or_else(|| anyhow::anyhow!("swc did not output any bundles"))?; + + let mut module = bundle.module; + if minify { + GLOBALS.set(&globals, || { + module = swc_ecma_minifier::optimize( + std::mem::take(&mut module).into(), + cm.clone(), + None, + None, + &MinifyOptions { + compress: Some(CompressOptions { + top_level: Some(TopLevelOptions { functions: true }), ..Default::default() - }, - ) - .context("failed to minify javascript") + }), + mangle: Some(MangleOptions { + top_level: Some(true), + ..Default::default() + }), + ..Default::default() + }, + &ExtraOptions { + unresolved_mark: Mark::new(), + top_level_mark: Mark::new(), + mangle_name_cache: None, + }, + ) + .expect_module(); + module.visit_mut_with(&mut fixer(None)); + }) + } + + let mut emitter = Emitter { + cfg: swc_ecma_codegen::Config::default().with_minify(minify), + cm: cm.clone(), + comments: None, + wr: Box::new(JsWriter::new(cm, "\n", write_to, None)), + }; + + emitter.emit_module(&module)?; + + Ok(()) +} + +struct PathLoader { + cm: Lrc, +} + +impl Load for PathLoader { + fn load(&self, file: &FileName) -> anyhow::Result { + let file = match file { + FileName::Real(v) => v, + _ => anyhow::bail!("Only real files are supported"), + }; + + let fm = self.cm.load_file(file)?; + + let module = HANDLER.with(|handler| { + parse_file_as_module( + &fm, + Syntax::Es(Default::default()), + Default::default(), + None, + &mut Vec::new(), + ) + .map_err(|err| { + let message = err.into_diagnostic(&handler).message(); + anyhow::anyhow!("{}", message) }) + .context("Failed to parse javascript") + })?; + + Ok(ModuleData { + fm, + module, + helpers: Default::default(), }) - .map(|output| output.code); + } +} - match output { - Ok(output) => Ok(output), - Err(err) => { - tracing::error!("Failed to minify javascript: {}", err); - Ok(js) - } +// Adapted from https://github.com/swc-project/swc/blob/624680b7896cef9d8e30bd5ff910538298016974/bindings/binding_core_node/src/bundle.rs#L266-L302 +struct Hook; + +impl swc_bundler::Hook for Hook { + fn get_import_meta_props( + &self, + span: Span, + module_record: &ModuleRecord, + ) -> Result, Error> { + let file_name = module_record.file_name.to_string(); + + Ok(vec![ + KeyValueProp { + key: PropName::Ident(IdentName::new("url".into(), span)), + value: Box::new(Expr::Lit(Lit::Str(Str { + span, + raw: None, + value: file_name.into(), + }))), + }, + KeyValueProp { + key: PropName::Ident(IdentName::new("main".into(), span)), + value: Box::new(if module_record.is_entry { + Expr::Member(MemberExpr { + span, + obj: Box::new(Expr::MetaProp(MetaPropExpr { + span, + kind: MetaPropKind::ImportMeta, + })), + prop: MemberProp::Ident(IdentName::new("main".into(), span)), + }) + } else { + Expr::Lit(Lit::Bool(Bool { span, value: false })) + }), + }, + ]) } } @@ -49,16 +173,18 @@ pub(crate) fn process_js( source: &Path, output_path: &Path, ) -> anyhow::Result<()> { - let js = if js_options.minified() { - minify_js(source)? - } else { - let mut source_file = std::fs::File::open(source)?; - let mut source = String::new(); - source_file.read_to_string(&mut source)?; - source - }; + let mut writer = std::io::BufWriter::new(std::fs::File::create(output_path)?); + if js_options.minified() { + match bundle_js_to_writer(source.to_path_buf(), true, &mut writer) { + Ok(_) => return Ok(()), + Err(err) => { + tracing::error!("Failed to minify js. Falling back to non-minified: {err}"); + } + } + } - std::fs::write(output_path, js).with_context(|| { + let mut source_file = std::fs::File::open(source)?; + std::io::copy(&mut source_file, &mut writer).with_context(|| { format!( "Failed to write js to output location: {}", output_path.display() From 1ead6100ba1188a23a26a60fadd6f19a54a67d88 Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Thu, 9 Jan 2025 12:24:57 -0600 Subject: [PATCH 02/18] Move main wasm bindgen file and wasm file into the manganis bundling system --- Cargo.lock | 1492 +++-------------- packages/cli-opt/src/js.rs | 87 +- packages/cli/Cargo.toml | 1 + packages/cli/src/build/bundle.rs | 47 +- packages/cli/src/build/request.rs | 19 + packages/cli/src/build/web.rs | 108 +- packages/cli/src/serve/proxy.rs | 1 - packages/manganis/manganis-core/src/asset.rs | 15 + packages/manganis/manganis-core/src/hash.rs | 93 + packages/manganis/manganis-core/src/lib.rs | 2 + packages/manganis/manganis-macro/src/asset.rs | 116 +- .../manganis/manganis/src/macro_helpers.rs | 36 +- 12 files changed, 587 insertions(+), 1430 deletions(-) create mode 100644 packages/manganis/manganis-core/src/hash.rs diff --git a/Cargo.lock b/Cargo.lock index 5f46abda76..85cc0e1880 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,16 +2,6 @@ # It is not intended for manual editing. version = 3 -[[package]] -name = "Inflector" -version = "0.11.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" -dependencies = [ - "lazy_static", - "regex", -] - [[package]] name = "addr2line" version = "0.24.2" @@ -539,9 +529,9 @@ dependencies = [ [[package]] name = "ast_node" -version = "0.9.9" +version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9184f2b369b3e8625712493c89b785881f27eedc6cde480a81883cef78868b2" +checksum = "91fb5864e2f5bf9fd9797b94b2dfd1554d4c3092b535008b27d7e15c86675a2f" dependencies = [ "proc-macro2", "quote", @@ -1575,9 +1565,9 @@ dependencies = [ [[package]] name = "better_scoped_tls" -version = "0.1.2" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "297b153aa5e573b5863108a6ddc9d5c968bd0b20e75cc614ee9821d2f45679c7" +checksum = "50fd297a11c709be8348aec039c8b91de16075d2b2bdaee1bd562c0875993664" dependencies = [ "scoped-tls", ] @@ -1881,7 +1871,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23cdc57ce23ac53c931e88a43d06d070a6fd142f2617be5855eb75efc9beb1c2" dependencies = [ "bytecheck_derive", - "ptr_meta", + "ptr_meta 0.1.4", "simdutf8", ] @@ -2778,15 +2768,30 @@ dependencies = [ "libc", ] +[[package]] +name = "crc" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49fc9a695bca7f35f5f4c15cddc84415f66a74ea78eef08e90c5024f2b540e23" +dependencies = [ + "crc-catalog 1.1.1", +] + [[package]] name = "crc" version = "3.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636" dependencies = [ - "crc-catalog", + "crc-catalog 2.4.0", ] +[[package]] +name = "crc-catalog" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccaeedb56da03b09f598226e25e80088cb4cd25f316e6e4df7d695f0feeb1403" + [[package]] name = "crc-catalog" version = "2.4.0" @@ -3495,6 +3500,7 @@ dependencies = [ "itertools 0.13.0", "krates", "log", + "manganis", "manganis-core", "notify", "object 0.36.5", @@ -3559,56 +3565,31 @@ dependencies = [ "rayon", "serde", "serde_json", - "swc", "swc_allocator", "swc_atoms", + "swc_bundler", "swc_cached", "swc_common", - "swc_compiler_base 0.19.0", "swc_config", "swc_config_macro", "swc_ecma_ast", "swc_ecma_codegen", "swc_ecma_codegen_macros", - "swc_ecma_compat_bugfixes 0.12.0", - "swc_ecma_compat_common", - "swc_ecma_compat_es2015 0.12.0", - "swc_ecma_compat_es2016 0.12.0", - "swc_ecma_compat_es2017 0.12.0", - "swc_ecma_compat_es2018 0.12.0", - "swc_ecma_compat_es2019 0.12.0", - "swc_ecma_compat_es2020 0.12.0", - "swc_ecma_compat_es2021 0.12.0", - "swc_ecma_compat_es2022 0.12.0", - "swc_ecma_compat_es3 0.12.0", - "swc_ecma_ext_transforms", - "swc_ecma_lints 0.100.0", "swc_ecma_loader", - "swc_ecma_minifier 0.204.0", + "swc_ecma_minifier", "swc_ecma_parser", - "swc_ecma_preset_env 0.217.0", - "swc_ecma_transforms 0.239.0", - "swc_ecma_transforms_base 0.145.0", - "swc_ecma_transforms_classes 0.134.0", - "swc_ecma_transforms_compat 0.171.0", + "swc_ecma_transforms_base", "swc_ecma_transforms_macros", - "swc_ecma_transforms_module 0.190.0", - "swc_ecma_transforms_optimization 0.208.0", - "swc_ecma_transforms_proposal 0.178.0", - "swc_ecma_transforms_react 0.191.0", - "swc_ecma_transforms_typescript 0.198.1", + "swc_ecma_transforms_optimization", "swc_ecma_usage_analyzer", "swc_ecma_utils", "swc_ecma_visit", "swc_eq_ignore_macros", - "swc_error_reporters", "swc_fast_graph", + "swc_graph_analyzer", "swc_macros_common", - "swc_node_comments", + "swc_parallel", "swc_timer", - "swc_trace_macro", - "swc_transform_common", - "swc_typescript", "swc_visit", "tracing", ] @@ -4973,9 +4954,9 @@ dependencies = [ [[package]] name = "from_variant" -version = "0.1.9" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32016f1242eb82af5474752d00fd8ebcd9004bd69b462b1c91de833972d08ed4" +checksum = "8d7ccf961415e7aa17ef93dcb6c2441faaa8e768abe09e659b908089546f74c5" dependencies = [ "proc-macro2", "swc_macros_common", @@ -6264,9 +6245,9 @@ dependencies = [ [[package]] name = "hstr" -version = "0.2.12" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dae404c0c5d4e95d4858876ab02eecd6a196bb8caa42050dfa809938833fc412" +checksum = "63d6824358c0fd9a68bb23999ed2ef76c84f79408a26ef7ae53d5f370c94ad36" dependencies = [ "hashbrown 0.14.5", "new_debug_unreachable", @@ -7169,15 +7150,6 @@ dependencies = [ "thiserror 1.0.69", ] -[[package]] -name = "jsonc-parser" -version = "0.21.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b56a20e76235284255a09fcd1f45cf55d3c524ea657ebd3854735925c57743d" -dependencies = [ - "serde_json", -] - [[package]] name = "jsonptr" version = "0.4.7" @@ -7873,31 +7845,6 @@ dependencies = [ "paste", ] -[[package]] -name = "miette" -version = "7.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "317f146e2eb7021892722af37cf1b971f0a70c8406f487e24952667616192c64" -dependencies = [ - "cfg-if", - "miette-derive", - "owo-colors", - "textwrap", - "thiserror 1.0.69", - "unicode-width 0.1.14", -] - -[[package]] -name = "miette-derive" -version = "7.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23c9b935fbe1d6cbd1dac857b54a688145e2d93f48db36010514d0f612d0ad67" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.90", -] - [[package]] name = "mime" version = "0.3.17" @@ -8995,12 +8942,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ecba01bf2678719532c5e3059e0b5f0811273d94b397088b82e3bd0a78c78fdd" -[[package]] -name = "path-clean" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17359afc20d7ab31fdb42bb844c8b3bb1dabd7dcf7e68428492da7f16966fcef" - [[package]] name = "path-dedot" version = "3.1.1" @@ -9527,24 +9468,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" -[[package]] -name = "preset_env_base" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b30eab18be480c194938e433e269d5298a279f6410f02fbc73f3576a325c110" -dependencies = [ - "ahash 0.8.11", - "anyhow", - "browserslist-rs", - "dashmap", - "from_variant", - "once_cell", - "semver 1.0.23", - "serde", - "st-map", - "tracing", -] - [[package]] name = "presser" version = "0.3.1" @@ -9742,7 +9665,16 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0738ccf7ea06b608c10564b31debd4f5bc5e197fc8bfe088f68ae5ce81e7a4f1" dependencies = [ - "ptr_meta_derive", + "ptr_meta_derive 0.1.4", +] + +[[package]] +name = "ptr_meta" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe9e76f66d3f9606f44e45598d155cb13ecf09f4a28199e48daf8c8fc937ea90" +dependencies = [ + "ptr_meta_derive 0.3.0", ] [[package]] @@ -9756,6 +9688,17 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "ptr_meta_derive" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca414edb151b4c8d125c12566ab0d74dc9cdba36fb80eb7b848c15f495fd32d1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + [[package]] name = "qoi" version = "0.4.1" @@ -10160,6 +10103,12 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" +[[package]] +name = "relative-path" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba39f3699c378cd8970968dcbff9c43159ea4cfbd88d43c00b22f2ef10a435d2" + [[package]] name = "remove_dir_all" version = "0.8.4" @@ -10398,7 +10347,7 @@ dependencies = [ "bytecheck", "bytes", "hashbrown 0.12.3", - "ptr_meta", + "ptr_meta 0.1.4", "rend", "rkyv_derive", "seahash", @@ -11556,7 +11505,7 @@ dependencies = [ "byteorder", "bytes", "chrono", - "crc", + "crc 3.2.1", "crossbeam-queue", "either", "event-listener 2.5.3", @@ -11646,7 +11595,7 @@ dependencies = [ "byteorder", "bytes", "chrono", - "crc", + "crc 3.2.1", "digest", "dotenvy", "either", @@ -11693,7 +11642,7 @@ dependencies = [ "bitflags 2.6.0", "byteorder", "chrono", - "crc", + "crc 3.2.1", "dotenvy", "etcetera", "futures-channel", @@ -11753,16 +11702,6 @@ dependencies = [ "uuid", ] -[[package]] -name = "st-map" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8257dd592de7614be71a2342d36ba2d527ddad3f9a0c8d09d6ceed4c371531e4" -dependencies = [ - "arrayvec", - "static-map-macro", -] - [[package]] name = "stable_deref_trait" version = "1.2.0" @@ -11782,17 +11721,6 @@ dependencies = [ "windows-sys 0.59.0", ] -[[package]] -name = "static-map-macro" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "710e9696ef338691287aeb937ee6ffe60022f579d3c8d2fd9d58973a9a10a466" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.90", -] - [[package]] name = "static-self" version = "0.1.1" @@ -11848,9 +11776,9 @@ dependencies = [ [[package]] name = "string_enum" -version = "0.4.4" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05e383308aebc257e7d7920224fa055c632478d92744eca77f99be8fa1545b90" +checksum = "c9fe66b8ee349846ce2f9557a26b8f1e74843c4a13fb381f9a3d73617a5f956a" dependencies = [ "proc-macro2", "quote", @@ -11950,74 +11878,24 @@ dependencies = [ "serde", ] -[[package]] -name = "swc" -version = "0.283.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cb7fe4bd6a604528819c84fc9acc5d5ec1b3bd0d11d13ee5d8a77d49ff678fa" -dependencies = [ - "anyhow", - "base64 0.21.7", - "dashmap", - "either", - "indexmap 2.7.0", - "jsonc-parser", - "lru 0.10.1", - "once_cell", - "parking_lot", - "pathdiff", - "regex", - "rustc-hash 1.1.0", - "serde", - "serde_json", - "sourcemap", - "swc_atoms", - "swc_cached", - "swc_common", - "swc_compiler_base 0.16.0", - "swc_config", - "swc_ecma_ast", - "swc_ecma_codegen", - "swc_ecma_ext_transforms", - "swc_ecma_lints 0.99.0", - "swc_ecma_loader", - "swc_ecma_minifier 0.201.0", - "swc_ecma_parser", - "swc_ecma_preset_env 0.214.0", - "swc_ecma_transforms 0.236.0", - "swc_ecma_transforms_base 0.144.0", - "swc_ecma_transforms_compat 0.170.0", - "swc_ecma_transforms_optimization 0.205.0", - "swc_ecma_utils", - "swc_ecma_visit", - "swc_error_reporters", - "swc_node_comments", - "swc_timer", - "swc_transform_common", - "swc_typescript", - "swc_visit", - "tracing", - "url", -] - [[package]] name = "swc_allocator" -version = "0.1.8" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adc8bd3075d1c6964010333fae9ddcd91ad422a4f8eb8b3206a9b2b6afb4209e" +checksum = "117d5d3289663f53022ebf157df8a42b3872d7ac759e63abf96b5987b85d4af3" dependencies = [ "bumpalo", "hashbrown 0.14.5", - "ptr_meta", + "ptr_meta 0.3.0", "rustc-hash 1.1.0", "triomphe", ] [[package]] name = "swc_atoms" -version = "0.6.7" +version = "3.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb6567e4e67485b3e7662b486f1565bdae54bd5b9d6b16b2ba1a9babb1e42125" +checksum = "a640bf2e4430a149c87b5eaf377477ce8615ca7cb808054dd20e79e42da5d6ba" dependencies = [ "hstr", "once_cell", @@ -12025,11 +11903,41 @@ dependencies = [ "serde", ] +[[package]] +name = "swc_bundler" +version = "7.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c88a91910cd8430f88f8987019cf3a96d92a5d5dded3e0ba8203e0379e4a2f6f" +dependencies = [ + "anyhow", + "crc 2.1.0", + "indexmap 2.7.0", + "is-macro", + "once_cell", + "parking_lot", + "petgraph", + "radix_fmt", + "relative-path", + "swc_atoms", + "swc_common", + "swc_ecma_ast", + "swc_ecma_codegen", + "swc_ecma_loader", + "swc_ecma_parser", + "swc_ecma_transforms_base", + "swc_ecma_transforms_optimization", + "swc_ecma_utils", + "swc_ecma_visit", + "swc_fast_graph", + "swc_graph_analyzer", + "tracing", +] + [[package]] name = "swc_cached" -version = "0.3.20" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83406221c501860fce9c27444f44125eafe9e598b8b81be7563d7036784cd05c" +checksum = "96b6a5ef4cfec51d3fa30b73600f206453a37fc30cf1141e4644a57b1ed88616" dependencies = [ "ahash 0.8.11", "anyhow", @@ -12041,11 +11949,10 @@ dependencies = [ [[package]] name = "swc_common" -version = "0.37.5" +version = "5.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12d0a8eaaf1606c9207077d75828008cb2dfb51b095a766bd2b72ef893576e31" +checksum = "a521e8120dc0401580864a643b5bffa035c29fc3fc41697c972743d4f008ed22" dependencies = [ - "ahash 0.8.11", "ast_node", "better_scoped_tls", "cfg-if", @@ -12054,77 +11961,24 @@ dependencies = [ "new_debug_unreachable", "num-bigint", "once_cell", - "parking_lot", "rustc-hash 1.1.0", "serde", "siphasher", - "sourcemap", "swc_allocator", "swc_atoms", "swc_eq_ignore_macros", "swc_visit", + "termcolor", "tracing", "unicode-width 0.1.14", "url", ] -[[package]] -name = "swc_compiler_base" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9b47fac27c2e84e033bdea294ac12f575322c81c9d5d44f423e3f11ff239a86" -dependencies = [ - "anyhow", - "base64 0.21.7", - "once_cell", - "pathdiff", - "rustc-hash 1.1.0", - "serde", - "serde_json", - "sourcemap", - "swc_allocator", - "swc_atoms", - "swc_common", - "swc_config", - "swc_ecma_ast", - "swc_ecma_codegen", - "swc_ecma_minifier 0.201.0", - "swc_ecma_parser", - "swc_ecma_visit", - "swc_timer", -] - -[[package]] -name = "swc_compiler_base" -version = "0.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "feb87f8dc7be1a034d5c29bcc4be9d504ddfd2f8aa1a1338fc568e104e087d29" -dependencies = [ - "anyhow", - "base64 0.21.7", - "once_cell", - "pathdiff", - "rustc-hash 1.1.0", - "serde", - "serde_json", - "sourcemap", - "swc_allocator", - "swc_atoms", - "swc_common", - "swc_config", - "swc_ecma_ast", - "swc_ecma_codegen", - "swc_ecma_minifier 0.204.0", - "swc_ecma_parser", - "swc_ecma_visit", - "swc_timer", -] - [[package]] name = "swc_config" -version = "0.1.15" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4740e53eaf68b101203c1df0937d5161a29f3c13bceed0836ddfe245b72dd000" +checksum = "4aa30931f9b26af8edcb4cce605909d15dcfd7577220b22c50a2988f2a53c4c1" dependencies = [ "anyhow", "indexmap 2.7.0", @@ -12137,9 +11991,9 @@ dependencies = [ [[package]] name = "swc_config_macro" -version = "0.1.4" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c5f56139042c1a95b54f5ca48baa0e0172d369bcc9d3d473dad1de36bae8399" +checksum = "7f2ebd37ef52a8555c8c9be78b694d64adcb5e3bc16c928f030d82f1d65fac57" dependencies = [ "proc-macro2", "quote", @@ -12149,9 +12003,9 @@ dependencies = [ [[package]] name = "swc_ecma_ast" -version = "0.118.2" +version = "5.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6f866d12e4d519052b92a0a86d1ac7ff17570da1272ca0c89b3d6f802cd79df" +checksum = "82f448db2d1c52ffd2bd3788d89cafd8b5a75b97f0dc8aae00874dda2647f6b6" dependencies = [ "bitflags 2.6.0", "is-macro", @@ -12162,18 +12016,20 @@ dependencies = [ "string_enum", "swc_atoms", "swc_common", + "swc_visit", "unicode-id-start", ] [[package]] name = "swc_ecma_codegen" -version = "0.155.1" +version = "5.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc7641608ef117cfbef9581a99d02059b522fcca75e5244fa0cbbd8606689c6f" +checksum = "7f93692de35a77d920ce8d96a46217735e5f86bf42f76cc8f1a60628c347c4c8" dependencies = [ "memchr", "num-bigint", "once_cell", + "regex", "serde", "sourcemap", "swc_allocator", @@ -12186,9 +12042,9 @@ dependencies = [ [[package]] name = "swc_ecma_codegen_macros" -version = "0.7.7" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "859fabde36db38634f3fad548dd5e3410c1aebba1b67a3c63e67018fa57a0bca" +checksum = "5f9a42f479a6475647e248fa9750982c87cd985e19d1016a1fc18a70682305d1" dependencies = [ "proc-macro2", "quote", @@ -12197,876 +12053,125 @@ dependencies = [ ] [[package]] -name = "swc_ecma_compat_bugfixes" -version = "0.11.0" +name = "swc_ecma_loader" +version = "5.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9f9cac39f19d6509db921f4b75934aaa64fc84b599416e5c1fcaed1c313132f" +checksum = "1a19b132079bfcd19d6fdabce7e55ece93a30787f3b8684c8646ddaf2237812d" dependencies = [ + "anyhow", + "dashmap", + "lru 0.10.1", + "normpath 0.2.0", + "once_cell", + "parking_lot", + "path-clean", + "pathdiff", + "serde", + "serde_json", "swc_atoms", "swc_common", - "swc_ecma_ast", - "swc_ecma_compat_es2015 0.11.1", - "swc_ecma_transforms_base 0.144.0", - "swc_ecma_utils", - "swc_ecma_visit", - "swc_trace_macro", "tracing", ] [[package]] -name = "swc_ecma_compat_bugfixes" -version = "0.12.0" +name = "swc_ecma_minifier" +version = "7.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75429b44cc479cbe018d5994eddae5ac7ab887ebefeb3596720921bc4cdff551" -dependencies = [ - "swc_atoms", - "swc_common", - "swc_ecma_ast", - "swc_ecma_compat_es2015 0.12.0", - "swc_ecma_transforms_base 0.145.0", - "swc_ecma_utils", - "swc_ecma_visit", - "swc_trace_macro", - "tracing", -] - -[[package]] -name = "swc_ecma_compat_common" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9acdf402b36f8e83084b10e119d7ba9d07e5229ef39e1343f147db816c7b73e" -dependencies = [ - "swc_common", - "swc_ecma_ast", - "swc_ecma_utils", - "swc_ecma_visit", - "swc_trace_macro", -] - -[[package]] -name = "swc_ecma_compat_es2015" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dade6e0c6e8ddb61281fee2331c3775a920c31535b91e8cace2e0c4eed6158d3" -dependencies = [ - "arrayvec", - "indexmap 2.7.0", - "is-macro", - "serde", - "serde_derive", - "smallvec", - "swc_atoms", - "swc_common", - "swc_config", - "swc_ecma_ast", - "swc_ecma_compat_common", - "swc_ecma_transforms_base 0.144.0", - "swc_ecma_transforms_classes 0.133.0", - "swc_ecma_transforms_macros", - "swc_ecma_utils", - "swc_ecma_visit", - "swc_trace_macro", - "tracing", -] - -[[package]] -name = "swc_ecma_compat_es2015" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c988d9018d6abb22b0fcc2da6a624be2db7c56681b6180d1cb5faa2672fd8001" -dependencies = [ - "arrayvec", - "indexmap 2.7.0", - "is-macro", - "rustc-hash 1.1.0", - "serde", - "serde_derive", - "smallvec", - "swc_atoms", - "swc_common", - "swc_config", - "swc_ecma_ast", - "swc_ecma_compat_common", - "swc_ecma_transforms_base 0.145.0", - "swc_ecma_transforms_classes 0.134.0", - "swc_ecma_transforms_macros", - "swc_ecma_utils", - "swc_ecma_visit", - "swc_trace_macro", - "tracing", -] - -[[package]] -name = "swc_ecma_compat_es2016" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "209e347cdc3fb56632a1d882f981f3448f5f529c16d8da9d770207fffda4a8f6" -dependencies = [ - "swc_atoms", - "swc_common", - "swc_ecma_ast", - "swc_ecma_transforms_base 0.144.0", - "swc_ecma_transforms_macros", - "swc_ecma_utils", - "swc_ecma_visit", - "swc_trace_macro", - "tracing", -] - -[[package]] -name = "swc_ecma_compat_es2016" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b7a3e086151c70ff940531ddcd04c01351ae80aa4593fd2906255d18a836b4f" -dependencies = [ - "swc_atoms", - "swc_common", - "swc_ecma_ast", - "swc_ecma_transforms_base 0.145.0", - "swc_ecma_transforms_macros", - "swc_ecma_utils", - "swc_ecma_visit", - "swc_trace_macro", - "tracing", -] - -[[package]] -name = "swc_ecma_compat_es2017" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4aa87a6861b2adc8b0178fb450165101c4396409481c8726ec90ad28398cae5d" -dependencies = [ - "serde", - "swc_atoms", - "swc_common", - "swc_ecma_ast", - "swc_ecma_transforms_base 0.144.0", - "swc_ecma_transforms_macros", - "swc_ecma_utils", - "swc_ecma_visit", - "swc_trace_macro", - "tracing", -] - -[[package]] -name = "swc_ecma_compat_es2017" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3b74c89c9bd4fa532fba3d1ec47b129ec450b4143d3914118cd61b0e44d4a4b" -dependencies = [ - "serde", - "swc_atoms", - "swc_common", - "swc_ecma_ast", - "swc_ecma_transforms_base 0.145.0", - "swc_ecma_transforms_macros", - "swc_ecma_utils", - "swc_ecma_visit", - "swc_trace_macro", - "tracing", -] - -[[package]] -name = "swc_ecma_compat_es2018" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f577f098e7c3738ade709caadb17c9f3bd911ea2ee6cfacca561d12addcc5761" -dependencies = [ - "serde", - "swc_atoms", - "swc_common", - "swc_ecma_ast", - "swc_ecma_compat_common", - "swc_ecma_transforms_base 0.144.0", - "swc_ecma_transforms_macros", - "swc_ecma_utils", - "swc_ecma_visit", - "swc_trace_macro", - "tracing", -] - -[[package]] -name = "swc_ecma_compat_es2018" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a40bf74a06c433eee502ea6347596d5766d77da8baf32653d14a6655df4e181a" -dependencies = [ - "serde", - "swc_atoms", - "swc_common", - "swc_ecma_ast", - "swc_ecma_compat_common", - "swc_ecma_transforms_base 0.145.0", - "swc_ecma_transforms_macros", - "swc_ecma_utils", - "swc_ecma_visit", - "swc_trace_macro", - "tracing", -] - -[[package]] -name = "swc_ecma_compat_es2019" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9d52253dc2f83a3fca526c387c33e4ff9a8423b68c271414c9f870e1ced3231" -dependencies = [ - "swc_atoms", - "swc_common", - "swc_ecma_ast", - "swc_ecma_transforms_base 0.144.0", - "swc_ecma_utils", - "swc_ecma_visit", - "swc_trace_macro", - "tracing", -] - -[[package]] -name = "swc_ecma_compat_es2019" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10afb20890ffda37eefdfe06c3bb0d12e5ec8698667cb9e3689b74066b398845" -dependencies = [ - "swc_atoms", - "swc_common", - "swc_ecma_ast", - "swc_ecma_transforms_base 0.145.0", - "swc_ecma_utils", - "swc_ecma_visit", - "swc_trace_macro", - "tracing", -] - -[[package]] -name = "swc_ecma_compat_es2020" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed343932876fad34b1d4a13e30c55b94531e89916f45e7c04203bc49a29565b9" -dependencies = [ - "serde", - "swc_atoms", - "swc_common", - "swc_ecma_ast", - "swc_ecma_compat_es2022 0.11.0", - "swc_ecma_transforms_base 0.144.0", - "swc_ecma_utils", - "swc_ecma_visit", - "swc_trace_macro", - "tracing", -] - -[[package]] -name = "swc_ecma_compat_es2020" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0608c4814a362d5362bc536507d8c89b287521778e8b678fe4590bfa1843803a" -dependencies = [ - "serde", - "swc_atoms", - "swc_common", - "swc_ecma_ast", - "swc_ecma_compat_es2022 0.12.0", - "swc_ecma_transforms_base 0.145.0", - "swc_ecma_utils", - "swc_ecma_visit", - "swc_trace_macro", - "tracing", -] - -[[package]] -name = "swc_ecma_compat_es2021" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b6b28a2c109466eaa809d9b9a5b81dcbb4e269ba293a9c5c34aabc67b6427bc" -dependencies = [ - "swc_atoms", - "swc_common", - "swc_ecma_ast", - "swc_ecma_transforms_base 0.144.0", - "swc_ecma_utils", - "swc_ecma_visit", - "swc_trace_macro", - "tracing", -] - -[[package]] -name = "swc_ecma_compat_es2021" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f12ffb0f4282f4b333efa98c9653d181d89e1b5339d4be0d789189a246ef34b" -dependencies = [ - "swc_atoms", - "swc_common", - "swc_ecma_ast", - "swc_ecma_transforms_base 0.145.0", - "swc_ecma_utils", - "swc_ecma_visit", - "swc_trace_macro", - "tracing", -] - -[[package]] -name = "swc_ecma_compat_es2022" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab3a644e271ea2a9df88e3e456c5c204c4916ef5136b7d946f9cd25607f47ec6" -dependencies = [ - "swc_atoms", - "swc_common", - "swc_ecma_ast", - "swc_ecma_compat_common", - "swc_ecma_transforms_base 0.144.0", - "swc_ecma_transforms_classes 0.133.0", - "swc_ecma_transforms_macros", - "swc_ecma_utils", - "swc_ecma_visit", - "swc_trace_macro", - "tracing", -] - -[[package]] -name = "swc_ecma_compat_es2022" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc16be9dd64e1b32569375b0b73ecc7dc74f9d848e8caaf2007896e2cf8d68a7" -dependencies = [ - "swc_atoms", - "swc_common", - "swc_ecma_ast", - "swc_ecma_compat_common", - "swc_ecma_transforms_base 0.145.0", - "swc_ecma_transforms_classes 0.134.0", - "swc_ecma_transforms_macros", - "swc_ecma_utils", - "swc_ecma_visit", - "swc_trace_macro", - "tracing", -] - -[[package]] -name = "swc_ecma_compat_es3" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e55ffadc12067b21524bf7b5d6938021ee918f65f18937ed27245c23544bc910" -dependencies = [ - "swc_common", - "swc_ecma_ast", - "swc_ecma_transforms_base 0.144.0", - "swc_ecma_utils", - "swc_ecma_visit", - "swc_trace_macro", - "tracing", -] - -[[package]] -name = "swc_ecma_compat_es3" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e684ae87d26ad3012e588d0e268158cadee10ddc0cda261069f0f280a8b23ce7" -dependencies = [ - "swc_common", - "swc_ecma_ast", - "swc_ecma_transforms_base 0.145.0", - "swc_ecma_utils", - "swc_ecma_visit", - "swc_trace_macro", - "tracing", -] - -[[package]] -name = "swc_ecma_ext_transforms" -version = "0.120.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad03ee53c734eb74757d03c07ec71b1a982261830c9253ef3e2e4a089f9af25d" -dependencies = [ - "phf 0.11.2", - "swc_atoms", - "swc_common", - "swc_ecma_ast", - "swc_ecma_utils", - "swc_ecma_visit", -] - -[[package]] -name = "swc_ecma_lints" -version = "0.99.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20c11bcc9e3dc49929500c07c8b0c84a88064847d31e9ee16204b257e6bd315c" -dependencies = [ - "auto_impl", - "dashmap", - "parking_lot", - "rayon", - "regex", - "serde", - "swc_atoms", - "swc_common", - "swc_config", - "swc_ecma_ast", - "swc_ecma_utils", - "swc_ecma_visit", -] - -[[package]] -name = "swc_ecma_lints" -version = "0.100.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89907376ce67b56d8fbf79cca830a12cb41f93dccc306008c07d8eba8f6d388e" -dependencies = [ - "auto_impl", - "dashmap", - "parking_lot", - "rayon", - "regex", - "serde", - "swc_atoms", - "swc_common", - "swc_config", - "swc_ecma_ast", - "swc_ecma_utils", - "swc_ecma_visit", -] - -[[package]] -name = "swc_ecma_loader" -version = "0.49.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55fa3d55045b97894bfb04d38aff6d6302ac8a6a38e3bb3dfb0d20475c4974a9" -dependencies = [ - "anyhow", - "dashmap", - "lru 0.10.1", - "normpath 0.2.0", - "once_cell", - "parking_lot", - "path-clean 0.1.0", - "pathdiff", - "serde", - "serde_json", - "swc_atoms", - "swc_cached", - "swc_common", - "tracing", -] - -[[package]] -name = "swc_ecma_minifier" -version = "0.201.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d75a42254926bad8b7fa9390767a18ac608d99cfd5a3be675e4739c2cf7db1b" -dependencies = [ - "arrayvec", - "indexmap 2.7.0", - "num-bigint", - "num_cpus", - "once_cell", - "parking_lot", - "phf 0.11.2", - "radix_fmt", - "regex", - "rustc-hash 1.1.0", - "ryu-js", - "serde", - "serde_json", - "swc_allocator", - "swc_atoms", - "swc_common", - "swc_config", - "swc_ecma_ast", - "swc_ecma_codegen", - "swc_ecma_parser", - "swc_ecma_transforms_base 0.144.0", - "swc_ecma_transforms_optimization 0.205.0", - "swc_ecma_usage_analyzer", - "swc_ecma_utils", - "swc_ecma_visit", - "swc_timer", - "tracing", -] - -[[package]] -name = "swc_ecma_minifier" -version = "0.204.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34d88917a66b8f457c5953d2ff2d7788259658c89578636b28e9ac6ae56bbfd9" -dependencies = [ - "arrayvec", - "indexmap 2.7.0", - "num-bigint", - "num_cpus", - "once_cell", - "parking_lot", - "phf 0.11.2", - "radix_fmt", - "regex", - "rustc-hash 1.1.0", - "ryu-js", - "serde", - "serde_json", - "swc_allocator", - "swc_atoms", - "swc_common", - "swc_config", - "swc_ecma_ast", - "swc_ecma_codegen", - "swc_ecma_parser", - "swc_ecma_transforms_base 0.145.0", - "swc_ecma_transforms_optimization 0.208.0", - "swc_ecma_usage_analyzer", - "swc_ecma_utils", - "swc_ecma_visit", - "swc_timer", - "tracing", -] - -[[package]] -name = "swc_ecma_parser" -version = "0.149.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "683dada14722714588b56481399c699378b35b2ba4deb5c4db2fb627a97fb54b" -dependencies = [ - "either", - "new_debug_unreachable", - "num-bigint", - "num-traits", - "phf 0.11.2", - "serde", - "smallvec", - "smartstring", - "stacker", - "swc_atoms", - "swc_common", - "swc_ecma_ast", - "tracing", - "typed-arena", -] - -[[package]] -name = "swc_ecma_preset_env" -version = "0.214.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e85162c77f8c80b55e5aed3a5e5477b74a53ce9cca05dec6e3dabec1de0f49af" -dependencies = [ - "anyhow", - "dashmap", - "indexmap 2.7.0", - "once_cell", - "preset_env_base", - "rustc-hash 1.1.0", - "semver 1.0.23", - "serde", - "serde_json", - "st-map", - "string_enum", - "swc_atoms", - "swc_common", - "swc_ecma_ast", - "swc_ecma_transforms 0.236.0", - "swc_ecma_utils", - "swc_ecma_visit", -] - -[[package]] -name = "swc_ecma_preset_env" -version = "0.217.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51992e6bb854ef2e6c7a1b9a14ed8d0e3c8f905d348f694759f9a97bfa6a425" -dependencies = [ - "anyhow", - "dashmap", - "indexmap 2.7.0", - "once_cell", - "preset_env_base", - "rustc-hash 1.1.0", - "semver 1.0.23", - "serde", - "serde_json", - "st-map", - "string_enum", - "swc_atoms", - "swc_common", - "swc_ecma_ast", - "swc_ecma_transforms 0.239.0", - "swc_ecma_utils", - "swc_ecma_visit", -] - -[[package]] -name = "swc_ecma_transforms" -version = "0.236.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d289a83ab829d076d6c2bf2cc0beea7fbf0480ac47a415401f683181a65f4856" -dependencies = [ - "swc_atoms", - "swc_common", - "swc_ecma_ast", - "swc_ecma_transforms_base 0.144.0", - "swc_ecma_transforms_compat 0.170.0", - "swc_ecma_transforms_module 0.187.0", - "swc_ecma_transforms_optimization 0.205.0", - "swc_ecma_transforms_proposal 0.178.0", - "swc_ecma_transforms_react 0.190.0", - "swc_ecma_transforms_typescript 0.195.1", - "swc_ecma_utils", - "swc_ecma_visit", -] - -[[package]] -name = "swc_ecma_transforms" -version = "0.239.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82df2dd8048fe23f1df72acd52bfebf846b3d5a76e048eee32acf9af9bee6a98" -dependencies = [ - "swc_atoms", - "swc_common", - "swc_ecma_ast", - "swc_ecma_transforms_base 0.145.0", - "swc_ecma_transforms_compat 0.171.0", - "swc_ecma_transforms_proposal 0.179.0", - "swc_ecma_utils", - "swc_ecma_visit", -] - -[[package]] -name = "swc_ecma_transforms_base" -version = "0.144.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c0a71579d030e12fd3cfbfc8712c4ce21afc526f2a759903c77d8df61950f5e" -dependencies = [ - "better_scoped_tls", - "bitflags 2.6.0", - "indexmap 2.7.0", - "once_cell", - "phf 0.11.2", - "rustc-hash 1.1.0", - "serde", - "smallvec", - "swc_atoms", - "swc_common", - "swc_ecma_ast", - "swc_ecma_parser", - "swc_ecma_utils", - "swc_ecma_visit", - "tracing", -] - -[[package]] -name = "swc_ecma_transforms_base" -version = "0.145.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65f21494e75d0bd8ef42010b47cabab9caaed8f2207570e809f6f4eb51a710d1" -dependencies = [ - "better_scoped_tls", - "bitflags 2.6.0", - "indexmap 2.7.0", - "once_cell", - "phf 0.11.2", - "rustc-hash 1.1.0", - "serde", - "smallvec", - "swc_atoms", - "swc_common", - "swc_ecma_ast", - "swc_ecma_parser", - "swc_ecma_utils", - "swc_ecma_visit", - "tracing", -] - -[[package]] -name = "swc_ecma_transforms_classes" -version = "0.133.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f37ec04525798a09ce02e52dc15433acee2d86664da0b8ede55bb5cefd95384" -dependencies = [ - "swc_atoms", - "swc_common", - "swc_ecma_ast", - "swc_ecma_transforms_base 0.144.0", - "swc_ecma_utils", - "swc_ecma_visit", -] - -[[package]] -name = "swc_ecma_transforms_classes" -version = "0.134.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c3d884594385bea9405a2e1721151470d9a14d3ceec5dd773c0ca6894791601" -dependencies = [ - "swc_atoms", - "swc_common", - "swc_ecma_ast", - "swc_ecma_transforms_base 0.145.0", - "swc_ecma_utils", - "swc_ecma_visit", -] - -[[package]] -name = "swc_ecma_transforms_compat" -version = "0.170.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bb500b65423646da940e289ad37e7c88332d7194248c33fc63a9e768e104fe5" -dependencies = [ - "arrayvec", - "indexmap 2.7.0", - "is-macro", - "num-bigint", - "serde", - "smallvec", - "swc_atoms", - "swc_common", - "swc_config", - "swc_ecma_ast", - "swc_ecma_compat_bugfixes 0.11.0", - "swc_ecma_compat_common", - "swc_ecma_compat_es2015 0.11.1", - "swc_ecma_compat_es2016 0.11.0", - "swc_ecma_compat_es2017 0.11.1", - "swc_ecma_compat_es2018 0.11.0", - "swc_ecma_compat_es2019 0.11.0", - "swc_ecma_compat_es2020 0.11.0", - "swc_ecma_compat_es2021 0.11.0", - "swc_ecma_compat_es2022 0.11.0", - "swc_ecma_compat_es3 0.11.0", - "swc_ecma_transforms_base 0.144.0", - "swc_ecma_transforms_classes 0.133.0", - "swc_ecma_transforms_macros", - "swc_ecma_utils", - "swc_ecma_visit", - "swc_trace_macro", - "tracing", -] - -[[package]] -name = "swc_ecma_transforms_compat" -version = "0.171.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f23da29c1279b6e0c1ac0df9d0f7fd6c955a141a9770e5a0a2d54292509bcf6" +checksum = "164291b068cca947462d87ede1baf276f69da137db1a0c66059a8aed81b785b2" dependencies = [ "arrayvec", "indexmap 2.7.0", - "is-macro", "num-bigint", + "num_cpus", + "once_cell", + "parking_lot", + "phf 0.11.2", + "radix_fmt", + "regex", + "rustc-hash 1.1.0", + "ryu-js", "serde", - "smallvec", + "serde_json", + "swc_allocator", "swc_atoms", "swc_common", "swc_config", "swc_ecma_ast", - "swc_ecma_compat_bugfixes 0.12.0", - "swc_ecma_compat_common", - "swc_ecma_compat_es2015 0.12.0", - "swc_ecma_compat_es2016 0.12.0", - "swc_ecma_compat_es2017 0.12.0", - "swc_ecma_compat_es2018 0.12.0", - "swc_ecma_compat_es2019 0.12.0", - "swc_ecma_compat_es2020 0.12.0", - "swc_ecma_compat_es2021 0.12.0", - "swc_ecma_compat_es2022 0.12.0", - "swc_ecma_compat_es3 0.12.0", - "swc_ecma_transforms_base 0.145.0", - "swc_ecma_transforms_classes 0.134.0", - "swc_ecma_transforms_macros", + "swc_ecma_codegen", + "swc_ecma_parser", + "swc_ecma_transforms_base", + "swc_ecma_transforms_optimization", + "swc_ecma_usage_analyzer", "swc_ecma_utils", "swc_ecma_visit", - "swc_trace_macro", + "swc_parallel", + "swc_timer", "tracing", ] [[package]] -name = "swc_ecma_transforms_macros" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "500a1dadad1e0e41e417d633b3d6d5de677c9e0d3159b94ba3348436cdb15aab" -dependencies = [ - "proc-macro2", - "quote", - "swc_macros_common", - "syn 2.0.90", -] - -[[package]] -name = "swc_ecma_transforms_module" -version = "0.187.0" +name = "swc_ecma_parser" +version = "6.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc022be297cdc70d5e71720587c7e810401a958577d77830f3108411e73c466d" +checksum = "b92d3a25349d7f612c38d940f09f9c19c7b7aa3bf4d22fbe31ea44fd5354de02" dependencies = [ - "Inflector", - "anyhow", - "bitflags 2.6.0", - "indexmap 2.7.0", - "is-macro", - "path-clean 1.0.1", - "pathdiff", - "regex", + "either", + "new_debug_unreachable", + "num-bigint", + "num-traits", + "phf 0.11.2", "serde", + "smallvec", + "smartstring", + "stacker", "swc_atoms", - "swc_cached", "swc_common", "swc_ecma_ast", - "swc_ecma_loader", - "swc_ecma_parser", - "swc_ecma_transforms_base 0.144.0", - "swc_ecma_utils", - "swc_ecma_visit", "tracing", + "typed-arena", ] [[package]] -name = "swc_ecma_transforms_module" -version = "0.190.0" +name = "swc_ecma_transforms_base" +version = "7.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c4d0255362149854b923125e9910ce0a5405ce6d03fb325c5fdd8e9f13a0845" +checksum = "09fdc36d220bcd51f70b1d78bdd8c1e1a172b4e594c385bdd9614b84a7c0e112" dependencies = [ - "Inflector", - "anyhow", + "better_scoped_tls", "bitflags 2.6.0", "indexmap 2.7.0", - "is-macro", - "path-clean 1.0.1", - "pathdiff", - "regex", + "once_cell", + "phf 0.11.2", + "rustc-hash 1.1.0", "serde", + "smallvec", "swc_atoms", - "swc_cached", "swc_common", "swc_ecma_ast", - "swc_ecma_loader", "swc_ecma_parser", - "swc_ecma_transforms_base 0.145.0", "swc_ecma_utils", "swc_ecma_visit", + "swc_parallel", "tracing", ] [[package]] -name = "swc_ecma_transforms_optimization" -version = "0.205.0" +name = "swc_ecma_transforms_macros" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17446e46b75654901d962251ec4d0063423ee81759a325ed82fcf073308d97ca" +checksum = "6845dfb88569f3e8cd05901505916a8ebe98be3922f94769ca49f84e8ccec8f7" dependencies = [ - "dashmap", - "indexmap 2.7.0", - "once_cell", - "petgraph", - "rustc-hash 1.1.0", - "serde_json", - "swc_atoms", - "swc_common", - "swc_ecma_ast", - "swc_ecma_parser", - "swc_ecma_transforms_base 0.144.0", - "swc_ecma_transforms_macros", - "swc_ecma_utils", - "swc_ecma_visit", - "swc_fast_graph", - "tracing", + "proc-macro2", + "quote", + "swc_macros_common", + "syn 2.0.90", ] [[package]] name = "swc_ecma_transforms_optimization" -version = "0.208.0" +version = "7.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98d8447ea20ef76958a8240feef95743702485a84331e6df5bdbe7e383c87838" +checksum = "5e4232534b28fc57b745e8c709723544e5548af29abaa62281eab427099f611d" dependencies = [ "dashmap", "indexmap 2.7.0", @@ -13078,7 +12183,7 @@ dependencies = [ "swc_common", "swc_ecma_ast", "swc_ecma_parser", - "swc_ecma_transforms_base 0.145.0", + "swc_ecma_transforms_base", "swc_ecma_transforms_macros", "swc_ecma_utils", "swc_ecma_visit", @@ -13086,135 +12191,11 @@ dependencies = [ "tracing", ] -[[package]] -name = "swc_ecma_transforms_proposal" -version = "0.178.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9c7ddb3aae86f19eb9e41b0c62509d8e400c1dc79c0889df98f6df1ab893f3f" -dependencies = [ - "either", - "rustc-hash 1.1.0", - "serde", - "smallvec", - "swc_atoms", - "swc_common", - "swc_ecma_ast", - "swc_ecma_transforms_base 0.144.0", - "swc_ecma_transforms_classes 0.133.0", - "swc_ecma_transforms_macros", - "swc_ecma_utils", - "swc_ecma_visit", -] - -[[package]] -name = "swc_ecma_transforms_proposal" -version = "0.179.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79938ff510fc647febd8c6c3ef4143d099fdad87a223680e632623d056dae2dd" -dependencies = [ - "either", - "rustc-hash 1.1.0", - "serde", - "smallvec", - "swc_atoms", - "swc_common", - "swc_ecma_ast", - "swc_ecma_transforms_base 0.145.0", - "swc_ecma_transforms_classes 0.134.0", - "swc_ecma_transforms_macros", - "swc_ecma_utils", - "swc_ecma_visit", -] - -[[package]] -name = "swc_ecma_transforms_react" -version = "0.190.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3e54a8c87d90812bf69b0f07931bb629111a3f24efe83b9190c3a40a5ebc25e" -dependencies = [ - "base64 0.21.7", - "dashmap", - "indexmap 2.7.0", - "once_cell", - "serde", - "sha1", - "string_enum", - "swc_allocator", - "swc_atoms", - "swc_common", - "swc_config", - "swc_ecma_ast", - "swc_ecma_parser", - "swc_ecma_transforms_base 0.144.0", - "swc_ecma_transforms_macros", - "swc_ecma_utils", - "swc_ecma_visit", -] - -[[package]] -name = "swc_ecma_transforms_react" -version = "0.191.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76c76d8b9792ce51401d38da0fa62158d61f6d80d16d68fe5b03ce4bf5fba383" -dependencies = [ - "base64 0.21.7", - "dashmap", - "indexmap 2.7.0", - "once_cell", - "serde", - "sha1", - "string_enum", - "swc_allocator", - "swc_atoms", - "swc_common", - "swc_config", - "swc_ecma_ast", - "swc_ecma_parser", - "swc_ecma_transforms_base 0.145.0", - "swc_ecma_transforms_macros", - "swc_ecma_utils", - "swc_ecma_visit", -] - -[[package]] -name = "swc_ecma_transforms_typescript" -version = "0.195.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f814b32ec83fde097df19e7346c429825390d156d0015f321f1f6434b6a06c0c" -dependencies = [ - "ryu-js", - "serde", - "swc_atoms", - "swc_common", - "swc_ecma_ast", - "swc_ecma_transforms_base 0.144.0", - "swc_ecma_transforms_react 0.190.0", - "swc_ecma_utils", - "swc_ecma_visit", -] - -[[package]] -name = "swc_ecma_transforms_typescript" -version = "0.198.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15455da4768f97186c40523e83600495210c11825d3a44db43383fd81eace88d" -dependencies = [ - "ryu-js", - "serde", - "swc_atoms", - "swc_common", - "swc_ecma_ast", - "swc_ecma_transforms_base 0.145.0", - "swc_ecma_transforms_react 0.191.0", - "swc_ecma_utils", - "swc_ecma_visit", -] - [[package]] name = "swc_ecma_usage_analyzer" -version = "0.30.3" +version = "7.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c7689421c6a892642c5907fd608c56d982fdef0d6456f9dba3cc418c6ea7e07" +checksum = "15eb86aaa82d7ec4c1a6c3a8a824b1fdbbaace73c3ed81035a1fbbac49f8e0bd" dependencies = [ "indexmap 2.7.0", "rustc-hash 1.1.0", @@ -13229,9 +12210,9 @@ dependencies = [ [[package]] name = "swc_ecma_utils" -version = "0.134.2" +version = "7.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "029eec7dd485923a75b5a45befd04510288870250270292fc2c1b3a9e7547408" +checksum = "1c9d22b4883dc6d6c21a8216bbf5aacedd7f104230b1557367ae126a2ec3a2b5" dependencies = [ "indexmap 2.7.0", "num_cpus", @@ -13242,15 +12223,16 @@ dependencies = [ "swc_common", "swc_ecma_ast", "swc_ecma_visit", + "swc_parallel", "tracing", "unicode-id", ] [[package]] name = "swc_ecma_visit" -version = "0.104.8" +version = "5.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b1c6802e68e51f336e8bc9644e9ff9da75d7da9c1a6247d532f2e908aa33e81" +checksum = "b04c06c1805bda18c27165560f1617a57453feb9fb0638d90839053641af42d4" dependencies = [ "new_debug_unreachable", "num-bigint", @@ -13263,33 +12245,20 @@ dependencies = [ [[package]] name = "swc_eq_ignore_macros" -version = "0.1.4" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63db0adcff29d220c3d151c5b25c0eabe7e32dd936212b84cdaa1392e3130497" +checksum = "e96e15288bf385ab85eb83cff7f9e2d834348da58d0a31b33bdb572e66ee413e" dependencies = [ "proc-macro2", "quote", "syn 2.0.90", ] -[[package]] -name = "swc_error_reporters" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d049e9256abf29d9fc66d3db3ea44b6815a64ad565ce31e117a74ee96478bb3" -dependencies = [ - "anyhow", - "miette", - "once_cell", - "parking_lot", - "swc_common", -] - [[package]] name = "swc_fast_graph" -version = "0.25.0" +version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "357e2c97bb51431d65080f25b436bc4e2fc1a7f64a643bc21a8353e478dc799f" +checksum = "c22e0a0478b1b06610453a97c8371cafa742e371a79aff860ccfbabe1ab160a7" dependencies = [ "indexmap 2.7.0", "petgraph", @@ -13298,41 +12267,23 @@ dependencies = [ ] [[package]] -name = "swc_macros_common" -version = "0.3.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f486687bfb7b5c560868f69ed2d458b880cebc9babebcb67e49f31b55c5bf847" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.90", -] - -[[package]] -name = "swc_node_comments" -version = "0.24.0" +name = "swc_graph_analyzer" +version = "5.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d016ab18b432523b2a3c104ce3aaf7d869db46c0a41477dbfb6201ddc86c1eb0" +checksum = "79b9841af596d2ddb37e56defca81387b60a14863e251cede839d1e349e6209d" dependencies = [ - "dashmap", - "swc_atoms", + "auto_impl", + "petgraph", "swc_common", -] - -[[package]] -name = "swc_timer" -version = "0.25.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b5fb6f8b8b85512aacbb3d7140a828666e0e0b1bcc69bf84000a0cd36306bab" -dependencies = [ + "swc_fast_graph", "tracing", ] [[package]] -name = "swc_trace_macro" -version = "0.1.3" +name = "swc_macros_common" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff9719b6085dd2824fd61938a881937be14b08f95e2d27c64c825a9f65e052ba" +checksum = "a509f56fca05b39ba6c15f3e58636c3924c78347d63853632ed2ffcb6f5a0ac7" dependencies = [ "proc-macro2", "quote", @@ -13340,35 +12291,28 @@ dependencies = [ ] [[package]] -name = "swc_transform_common" -version = "0.1.1" +name = "swc_parallel" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eda3e80e1ad638d3575bc07745a914af13dcb02215098659f864731078271f2c" +checksum = "b7cde1a0f344924be62d01de0c8a98e840feae271b77dc8c1d9d2e340687225c" dependencies = [ - "better_scoped_tls", "once_cell", - "rustc-hash 1.1.0", - "serde", - "serde_json", ] [[package]] -name = "swc_typescript" -version = "0.5.0" +name = "swc_timer" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5d043347b109a8aebfe01aaeada4af322304ea0f54ae8e5721df9afcb9305ca" +checksum = "4db06b46cc832f7cf83c2ce21905fc465d01443a2bdccf63644383e1f5847532" dependencies = [ - "swc_atoms", - "swc_common", - "swc_ecma_ast", - "thiserror 1.0.69", + "tracing", ] [[package]] name = "swc_visit" -version = "0.6.2" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ceb044142ba2719ef9eb3b6b454fce61ab849eb696c34d190f04651955c613d" +checksum = "9138b6a36bbe76dd6753c4c0794f7e26480ea757bee499738bedbbb3ae3ec5f3" dependencies = [ "either", "new_debug_unreachable", @@ -13755,16 +12699,6 @@ dependencies = [ "windows-sys 0.59.0", ] -[[package]] -name = "textwrap" -version = "0.16.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23d434d3f8967a09480fb04132ebe0a3e088c173e6d0ee7897abbdf4eab0f8b9" -dependencies = [ - "unicode-linebreak", - "unicode-width 0.1.14", -] - [[package]] name = "thin-slice" version = "0.1.1" @@ -14596,12 +13530,6 @@ version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" -[[package]] -name = "unicode-linebreak" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f" - [[package]] name = "unicode-normalization" version = "0.1.24" diff --git a/packages/cli-opt/src/js.rs b/packages/cli-opt/src/js.rs index 428e79eb3e..4ab05f98e1 100644 --- a/packages/cli-opt/src/js.rs +++ b/packages/cli-opt/src/js.rs @@ -3,6 +3,8 @@ use std::path::PathBuf; use anyhow::Context; use manganis_core::JsAssetOptions; +use swc_common::errors::Emitter; +use swc_common::errors::Handler; use swc_ecma_minifier::option::{ CompressOptions, ExtraOptions, MangleOptions, MinifyOptions, TopLevelOptions, }; @@ -17,16 +19,49 @@ use swc_common::{ errors::HANDLER, sync::Lrc, FileName, FilePathMapping, Globals, Mark, SourceMap, Span, GLOBALS, }; use swc_ecma_ast::*; -use swc_ecma_codegen::{text_writer::JsWriter, Emitter}; +use swc_ecma_codegen::text_writer::JsWriter; use swc_ecma_loader::{resolvers::node::NodeModulesResolver, TargetEnv}; use swc_ecma_parser::{parse_file_as_module, Syntax}; +struct TracingEmitter; + +impl Emitter for TracingEmitter { + fn emit(&mut self, db: &swc_common::errors::DiagnosticBuilder<'_>) { + match db.level { + swc_common::errors::Level::Bug + | swc_common::errors::Level::Fatal + | swc_common::errors::Level::PhaseFatal + | swc_common::errors::Level::Error => tracing::error!("{}", db.message()), + swc_common::errors::Level::Warning + | swc_common::errors::Level::FailureNote + | swc_common::errors::Level::Cancelled => tracing::warn!("{}", db.message()), + swc_common::errors::Level::Note | swc_common::errors::Level::Help => { + tracing::trace!("{}", db.message()) + } + } + } +} + fn bundle_js_to_writer( file: PathBuf, minify: bool, write_to: &mut impl std::io::Write, ) -> anyhow::Result<()> { let globals = Globals::new(); + let handler = Handler::with_emitter_and_flags(Box::new(TracingEmitter), Default::default()); + GLOBALS.set(&globals, || { + HANDLER.set(&handler, || { + bundle_js_to_writer_inside_handler(&globals, file, minify, write_to) + }) + }) +} + +fn bundle_js_to_writer_inside_handler( + globals: &Globals, + file: PathBuf, + minify: bool, + write_to: &mut impl std::io::Write, +) -> anyhow::Result<()> { let cm = Lrc::new(SourceMap::new(FilePathMapping::empty())); let node_resolver = NodeModulesResolver::new(TargetEnv::Browser, Default::default(), true); let mut bundler = Bundler::new( @@ -53,35 +88,33 @@ fn bundle_js_to_writer( let mut module = bundle.module; if minify { - GLOBALS.set(&globals, || { - module = swc_ecma_minifier::optimize( - std::mem::take(&mut module).into(), - cm.clone(), - None, - None, - &MinifyOptions { - compress: Some(CompressOptions { - top_level: Some(TopLevelOptions { functions: true }), - ..Default::default() - }), - mangle: Some(MangleOptions { - top_level: Some(true), - ..Default::default() - }), + module = swc_ecma_minifier::optimize( + std::mem::take(&mut module).into(), + cm.clone(), + None, + None, + &MinifyOptions { + compress: Some(CompressOptions { + top_level: Some(TopLevelOptions { functions: true }), ..Default::default() - }, - &ExtraOptions { - unresolved_mark: Mark::new(), - top_level_mark: Mark::new(), - mangle_name_cache: None, - }, - ) - .expect_module(); - module.visit_mut_with(&mut fixer(None)); - }) + }), + mangle: Some(MangleOptions { + top_level: Some(true), + ..Default::default() + }), + ..Default::default() + }, + &ExtraOptions { + unresolved_mark: Mark::new(), + top_level_mark: Mark::new(), + mangle_name_cache: None, + }, + ) + .expect_module(); + module.visit_mut_with(&mut fixer(None)); } - let mut emitter = Emitter { + let mut emitter = swc_ecma_codegen::Emitter { cfg: swc_ecma_codegen::Config::default().with_minify(minify), cm: cm.clone(), comments: None, diff --git a/packages/cli/Cargo.toml b/packages/cli/Cargo.toml index 1f523fcd3b..82baa067bf 100644 --- a/packages/cli/Cargo.toml +++ b/packages/cli/Cargo.toml @@ -103,6 +103,7 @@ log = { version = "0.4", features = ["max_level_off", "release_max_level_off"] } # link intercept tempfile = "3.3" +manganis = { workspace = true } manganis-core = { workspace = true } # Extracting data from an executable diff --git a/packages/cli/src/build/bundle.rs b/packages/cli/src/build/bundle.rs index 0fb6c0190a..da89405c59 100644 --- a/packages/cli/src/build/bundle.rs +++ b/packages/cli/src/build/bundle.rs @@ -4,7 +4,7 @@ use crate::{BuildRequest, Platform}; use crate::{Result, TraceSrc}; use anyhow::Context; use dioxus_cli_opt::{process_file_to, AssetManifest}; -use manganis_core::AssetOptions; +use manganis::{AssetOptions, JsAssetOptions}; use rayon::prelude::{IntoParallelRefIterator, ParallelIterator}; use std::collections::HashSet; use std::future::Future; @@ -263,7 +263,7 @@ impl AppBundle { app: BuildArtifacts, server: Option, ) -> Result { - let bundle = Self { app, server, build }; + let mut bundle = Self { app, server, build }; tracing::debug!("Assembling app bundle"); @@ -298,7 +298,7 @@ impl AppBundle { /// For wasm, we'll want to run `wasm-bindgen` to make it a wasm binary along with some other optimizations /// Other platforms we might do some stripping or other optimizations /// Move the executable to the workdir - async fn write_main_executable(&self) -> Result<()> { + async fn write_main_executable(&mut self) -> Result<()> { match self.build.build.platform() { // Run wasm-bindgen on the wasm binary and set its output to be in the bundle folder // Also run wasm-opt on the wasm binary, and sets the index.html since that's also the "executable". @@ -325,7 +325,7 @@ impl AppBundle { Platform::Web => { // Run wasm-bindgen and drop its output into the assets folder under "dioxus" self.build.status_wasm_bindgen_start(); - self.run_wasm_bindgen(&self.app.exe.with_extension("wasm"), &self.build.exe_dir()) + self.run_wasm_bindgen(&self.app.exe.with_extension("wasm")) .await?; // Only run wasm-opt if the feature is enabled @@ -336,7 +336,7 @@ impl AppBundle { // Write the index.html file with the pre-configured contents we got from pre-rendering std::fs::write( self.build.root_dir().join("index.html"), - self.build.prepare_html()?, + self.prepare_html()?, )?; } @@ -470,6 +470,9 @@ impl AppBundle { .await .map_err(|e| anyhow::anyhow!("A task failed while trying to copy assets: {e}"))??; + // Remove the wasm bindgen output directory if it exists + _ = std::fs::remove_dir_all(&self.build.wasm_bindgen_out_dir()); + Ok(()) } @@ -593,15 +596,14 @@ impl AppBundle { None } - pub(crate) async fn run_wasm_bindgen( - &self, - input_path: &Path, - bindgen_outdir: &Path, - ) -> anyhow::Result<()> { + pub(crate) async fn run_wasm_bindgen(&mut self, input_path: &Path) -> anyhow::Result<()> { tracing::debug!(dx_src = ?TraceSrc::Bundle, "Running wasm-bindgen"); let input_path = input_path.to_path_buf(); - let bindgen_outdir = bindgen_outdir.to_path_buf(); + // Make sure the bindgen output directory exists + let bindgen_outdir = self.build.wasm_bindgen_out_dir(); + std::fs::create_dir_all(&bindgen_outdir)?; + let name = self.build.krate.executable_name().to_string(); let keep_debug = // if we're in debug mode, or we're generating debug symbols, keep debug info @@ -632,6 +634,29 @@ impl AppBundle { .await .context("Failed to generate wasm-bindgen bindings")?; + // After running wasm-bindgen, add the js and wasm asset to the manifest + let js_output_path = self.build.wasm_bindgen_js_output_file(); + let wasm_output_path = self.build.wasm_bindgen_wasm_output_file(); + let new_assets = [ + ( + js_output_path, + AssetOptions::Js(JsAssetOptions::new().with_minify(true).with_preload(true)), + ), + (wasm_output_path, AssetOptions::Unknown), + ]; + for (asset_path, options) in new_assets { + let hash = manganis_core::hash::AssetHash::hash_file_contents(&asset_path)?; + let output_path_str = asset_path.to_str().ok_or(anyhow::anyhow!( + "Failed to convert wasm bindgen output path to string" + ))?; + let bundled_asset = manganis::macro_helpers::create_bundled_asset( + output_path_str, + hash.bytes(), + options, + ); + self.app.assets.assets.insert(asset_path, bundled_asset); + } + tracing::debug!(dx_src = ?TraceSrc::Bundle, "wasm-bindgen complete in {:?}", start.elapsed()); Ok(()) diff --git a/packages/cli/src/build/request.rs b/packages/cli/src/build/request.rs index 7cd661e985..e0d134c5e9 100644 --- a/packages/cli/src/build/request.rs +++ b/packages/cli/src/build/request.rs @@ -656,6 +656,25 @@ impl BuildRequest { } } + /// Get the path to the wasm bindgen temporary output folder + pub fn wasm_bindgen_out_dir(&self) -> PathBuf { + self.root_dir().join("wasm-bindgen") + } + + /// Get the path to the wasm bindgen javascript output file + pub fn wasm_bindgen_js_output_file(&self) -> PathBuf { + self.wasm_bindgen_out_dir() + .join(self.krate.executable_name()) + .with_extension("js") + } + + /// Get the path to the wasm bindgen wasm output file + pub fn wasm_bindgen_wasm_output_file(&self) -> PathBuf { + self.wasm_bindgen_out_dir() + .join(format!("{}_bg", self.krate.executable_name())) + .with_extension("wasm") + } + /// returns the path to root build folder. This will be our working directory for the build. /// /// we only add an extension to the folders where it sorta matters that it's named with the extension. diff --git a/packages/cli/src/build/web.rs b/packages/cli/src/build/web.rs index f89d43e7d2..3bc5f9bf4a 100644 --- a/packages/cli/src/build/web.rs +++ b/packages/cli/src/build/web.rs @@ -1,17 +1,19 @@ use dioxus_cli_config::format_base_path_meta_element; +use manganis::AssetOptions; use crate::error::Result; -use crate::BuildRequest; use std::fmt::Write; use std::path::{Path, PathBuf}; +use super::AppBundle; + const DEFAULT_HTML: &str = include_str!("../../assets/web/index.html"); const TOAST_HTML: &str = include_str!("../../assets/web/toast.html"); -impl BuildRequest { +impl AppBundle { pub(crate) fn prepare_html(&self) -> Result { let mut html = { - let crate_root: &Path = &self.krate.crate_dir(); + let crate_root: &Path = &self.build.krate.crate_dir(); let custom_html_file = crate_root.join("index.html"); std::fs::read_to_string(custom_html_file).unwrap_or_else(|_| String::from(DEFAULT_HTML)) }; @@ -25,7 +27,7 @@ impl BuildRequest { // Replace any special placeholders in the HTML with resolved values self.replace_template_placeholders(&mut html); - let title = self.krate.config.web.app.title.clone(); + let title = self.build.krate.config.web.app.title.clone(); replace_or_insert_before("{app_title}", " bool { - !self.build.release + !self.build.build.release } // Inject any resources from the config into the html fn inject_resources(&self, html: &mut String) -> Result<()> { // Collect all resources into a list of styles and scripts - let resources = &self.krate.config.web.resource; + let resources = &self.build.krate.config.web.resource; let mut style_list = resources.style.clone().unwrap_or_default(); let mut script_list = resources.script.clone().unwrap_or_default(); @@ -70,7 +72,7 @@ impl BuildRequest { // Add the base path to the head if this is a debug build if self.is_dev_build() { - if let Some(base_path) = &self.krate.config.web.app.base_path { + if let Some(base_path) = &self.build.krate.config.web.app.base_path { head_resources.push_str(&format_base_path_meta_element(base_path)); } } @@ -83,9 +85,45 @@ impl BuildRequest { } // Inject any resources from manganis into the head - // if let Some(assets) = assets { - // head_resources.push_str(&assets.head()); - // } + for asset in self.app.assets.assets.values() { + let asset_path = asset.bundled_path(); + match asset.options() { + AssetOptions::Css(css_options) => { + if css_options.preloaded() { + head_resources.push_str(&format!( + "" + )) + } + } + AssetOptions::Image(image_options) => { + if image_options.preloaded() { + head_resources.push_str(&format!( + "" + )) + } + } + AssetOptions::Js(js_options) => { + if js_options.preloaded() { + head_resources.push_str(&format!( + "" + )) + } + } + _ => {} + } + } + // Manually inject the wasm file for preloading. WASM currently doesn't support preloading in the manganis asset system + let wasm_source_path = self.build.wasm_bindgen_wasm_output_file(); + let wasm_path = self + .app + .assets + .assets + .get(&wasm_source_path) + .expect("WASM asset should exist in web bundles") + .bundled_path(); + head_resources.push_str(&format!( + "" + )); replace_or_insert_before("{style_include}", " // We can't use a module script here because we need to start the script immediately when streaming - import("/{base_path}/wasm/{app_name}.js").then( + import("/{base_path}/{js_path}").then( ({ default: init }) => { - init("/{base_path}/wasm/{app_name}_bg.wasm").then((wasm) => { + init("/{base_path}/{wasm_path}").then((wasm) => { if (wasm.__wbindgen_start == undefined) { wasm.main(); } @@ -123,22 +161,41 @@ impl BuildRequest { true => html.replace("{DX_TOAST_UTILITIES}", TOAST_HTML), false => html.replace("{DX_TOAST_UTILITIES}", ""), }; - - // And try to insert preload links for the wasm and js files - *html = html.replace( - " - - Self { + Self { + absolute_source_path, + bundled_path, + options, + } + } + /// Get the bundled name of the asset. This identifier cannot be used to read the asset directly pub fn bundled_path(&self) -> &str { self.bundled_path.as_str() diff --git a/packages/manganis/manganis-core/src/hash.rs b/packages/manganis/manganis-core/src/hash.rs new file mode 100644 index 0000000000..a55880b76e --- /dev/null +++ b/packages/manganis/manganis-core/src/hash.rs @@ -0,0 +1,93 @@ +//! Utilities for creating hashed paths to assets in Manganis. This module defines [`AssetHash`] which is used to create a hashed path to an asset in both the CLI and the macro. + +use std::{ + error::Error, + hash::{Hash, Hasher}, + io::Read, + path::{Path, PathBuf}, +}; + +/// An error that can occur when hashing an asset +#[derive(Debug)] +#[non_exhaustive] +pub enum AssetHashError { + /// An io error occurred + IoError { err: std::io::Error, path: PathBuf }, +} + +impl std::fmt::Display for AssetHashError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + AssetHashError::IoError { path, err } => { + write!(f, "Failed to read file: {}; {}", path.display(), err) + } + } + } +} + +impl Error for AssetHashError {} + +/// The hash of an asset +pub struct AssetHash { + /// We use a wrapper type here to hide the exact size of the hash so we can switch to a sha hash in a minor version bump{} + hash: [u8; 8], +} + +impl AssetHash { + /// Create a new asset hash + const fn new(hash: u64) -> Self { + Self { + hash: hash.to_le_bytes(), + } + } + + /// Get the hash bytes + pub const fn bytes(&self) -> &[u8] { + &self.hash + } + + /// Create a new asset hash for a file. The input file to this function should be fully resolved + pub fn hash_file_contents(file_path: &Path) -> Result { + // Create a hasher + let mut hash = std::collections::hash_map::DefaultHasher::new(); + + // If this is a folder, hash the folder contents + if file_path.is_dir() { + let files = std::fs::read_dir(file_path).map_err(|err| AssetHashError::IoError { + err, + path: file_path.to_path_buf(), + })?; + for file in files.flatten() { + let path = file.path(); + Self::hash_file_contents(&path)?.bytes().hash(&mut hash); + } + let hash = hash.finish(); + return Ok(AssetHash::new(hash)); + } + + // Otherwise, open the file to get its contents + let mut file = std::fs::File::open(file_path).map_err(|err| AssetHashError::IoError { + err, + path: file_path.to_path_buf(), + })?; + + // We add a hash to the end of the file so it is invalidated when the bundled version of the file changes + // The hash includes the file contents, the options, and the version of manganis. From the macro, we just + // know the file contents, so we only include that hash + let mut buffer = [0; 8192]; + loop { + let read = file + .read(&mut buffer) + .map_err(|err| AssetHashError::IoError { + err: err.into(), + path: file_path.to_path_buf(), + })?; + if read == 0 { + break; + } + hash.write(&buffer[..read]); + } + + Ok(AssetHash::new(hash.finish())) + } +} diff --git a/packages/manganis/manganis-core/src/lib.rs b/packages/manganis/manganis-core/src/lib.rs index b3dddf836b..52e6ac80b2 100644 --- a/packages/manganis/manganis-core/src/lib.rs +++ b/packages/manganis/manganis-core/src/lib.rs @@ -17,3 +17,5 @@ mod asset; pub use asset::*; pub mod linker; + +pub mod hash; diff --git a/packages/manganis/manganis-macro/src/asset.rs b/packages/manganis/manganis-macro/src/asset.rs index 5774c37d4c..1cea783a5c 100644 --- a/packages/manganis/manganis-macro/src/asset.rs +++ b/packages/manganis/manganis-macro/src/asset.rs @@ -1,16 +1,36 @@ +use manganis_core::hash::AssetHash; use proc_macro2::TokenStream as TokenStream2; use quote::{quote, ToTokens, TokenStreamExt}; -use std::{ - hash::Hasher, - io::Read, - path::{Path, PathBuf}, -}; +use std::path::PathBuf; use syn::{ parse::{Parse, ParseStream}, LitStr, Token, }; -fn resolve_path(raw: &str) -> Result { +#[derive(Debug)] +pub(crate) enum AssetParseError { + AssetDoesntExist { path: PathBuf }, + InvalidPath { path: PathBuf }, +} + +impl std::fmt::Display for AssetParseError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + AssetParseError::AssetDoesntExist { path } => { + write!(f, "Asset at {} doesn't exist", path.display()) + } + AssetParseError::InvalidPath { path } => { + write!( + f, + "Asset path {} is invalid. Make sure the asset exists within this crate.", + path.display() + ) + } + } + } +} + +pub fn resolve_path(raw: &str) -> Result { // Get the location of the root of the crate which is where all assets are relative to // // IE @@ -52,75 +72,6 @@ fn resolve_path(raw: &str) -> Result { Ok(path) } -fn hash_file_contents(file_path: &Path) -> Result { - // Create a hasher - let mut hash = std::collections::hash_map::DefaultHasher::new(); - - // If this is a folder, hash the folder contents - if file_path.is_dir() { - let files = std::fs::read_dir(file_path).map_err(|err| AssetParseError::IoError { - err, - path: file_path.to_path_buf(), - })?; - for file in files.flatten() { - let path = file.path(); - hash_file_contents(&path)?; - } - return Ok(hash.finish()); - } - - // Otherwise, open the file to get its contents - let mut file = std::fs::File::open(file_path).map_err(|err| AssetParseError::IoError { - err, - path: file_path.to_path_buf(), - })?; - - // We add a hash to the end of the file so it is invalidated when the bundled version of the file changes - // The hash includes the file contents, the options, and the version of manganis. From the macro, we just - // know the file contents, so we only include that hash - let mut buffer = [0; 8192]; - loop { - let read = file - .read(&mut buffer) - .map_err(AssetParseError::FailedToReadAsset)?; - if read == 0 { - break; - } - hash.write(&buffer[..read]); - } - - Ok(hash.finish()) -} - -#[derive(Debug)] -pub(crate) enum AssetParseError { - AssetDoesntExist { path: PathBuf }, - IoError { err: std::io::Error, path: PathBuf }, - InvalidPath { path: PathBuf }, - FailedToReadAsset(std::io::Error), -} - -impl std::fmt::Display for AssetParseError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - AssetParseError::AssetDoesntExist { path } => { - write!(f, "Asset at {} doesn't exist", path.display()) - } - AssetParseError::IoError { path, err } => { - write!(f, "Failed to read file: {}; {}", path.display(), err) - } - AssetParseError::InvalidPath { path } => { - write!( - f, - "Asset path {} is invalid. Make sure the asset exists within this crate.", - path.display() - ) - } - AssetParseError::FailedToReadAsset(err) => write!(f, "Failed to read asset: {}", err), - } - } -} - pub struct AssetParser { /// The span of the source string path_span: proc_macro2::Span, @@ -188,7 +139,7 @@ impl ToTokens for AssetParser { let mut asset_str = proc_macro2::Literal::string(&asset_str); asset_str.set_span(self.path_span); - let hash = match hash_file_contents(asset) { + let hash = match AssetHash::hash_file_contents(asset) { Ok(hash) => hash, Err(err) => { let err = err.to_string(); @@ -197,15 +148,17 @@ impl ToTokens for AssetParser { } }; + let hash = hash.bytes(); + // Generate the link section for the asset // The link section includes the source path and the output path of the asset let link_section = crate::generate_link_section(quote!(__ASSET)); // generate the asset::new method to deprecate the `./assets/blah.css` syntax let constructor = if asset.is_relative() { - quote::quote! { new_relative } + quote::quote! { create_bundled_asset_relative } } else { - quote::quote! { new } + quote::quote! { create_bundled_asset } }; let options = if self.options.is_empty() { @@ -217,22 +170,19 @@ impl ToTokens for AssetParser { tokens.extend(quote! { { // We keep a hash of the contents of the asset for cache busting - const __ASSET_HASH: u64 = #hash; + const __ASSET_HASH: &[u8] = &[#(#hash),*]; // The source is used by the CLI to copy the asset const __ASSET_SOURCE_PATH: &'static str = #asset_str; // The options give the CLI info about how to process the asset // Note: into_asset_options is not a trait, so we cannot accept the options directly // in the constructor. Stable rust doesn't have support for constant functions in traits const __ASSET_OPTIONS: manganis::AssetOptions = #options.into_asset_options(); - // We calculate the bundled path from the hash and any transformations done by the options - // This is the final path that the asset will be written to - const __ASSET_BUNDLED_PATH: manganis::macro_helpers::const_serialize::ConstStr = manganis::macro_helpers::generate_unique_path(__ASSET_SOURCE_PATH, __ASSET_HASH, &__ASSET_OPTIONS); // Get the reference to the string that was generated. We cannot return &'static str from // generate_unique_path because it would return a reference to data generated in the function const __ASSET_BUNDLED_PATH_STR: &'static str = __ASSET_BUNDLED_PATH.as_str(); // Create the asset that the crate will use. This is used both in the return value and // added to the linker for the bundler to copy later - const __ASSET: manganis::BundledAsset = manganis::BundledAsset::#constructor(__ASSET_SOURCE_PATH, __ASSET_BUNDLED_PATH_STR, __ASSET_OPTIONS); + const __ASSET: manganis::BundledAsset = manganis::macro_helpers::#constructor(__ASSET_SOURCE_PATH, __ASSET_HASH, __ASSET_OPTIONS); #link_section diff --git a/packages/manganis/manganis/src/macro_helpers.rs b/packages/manganis/manganis/src/macro_helpers.rs index 26a27b2450..5e824b261e 100644 --- a/packages/manganis/manganis/src/macro_helpers.rs +++ b/packages/manganis/manganis/src/macro_helpers.rs @@ -4,11 +4,45 @@ use manganis_core::{AssetOptions, BundledAsset}; use crate::hash::ConstHasher; +/// Create a bundled asset from the input path, the content hash, and the asset options +pub const fn create_bundled_asset( + input_path: &str, + content_hash: &[u8], + asset_config: AssetOptions, +) -> BundledAsset { + let hashed_path = generate_unique_path_with_byte_hash(input_path, content_hash, &asset_config); + BundledAsset::new_from_const(ConstStr::new(input_path), hashed_path, asset_config) +} + +/// Create a bundled asset from the input path, the content hash, and the asset options with a relative asset deprecation warning +/// +/// This method is deprecated and will be removed in a future release. +#[deprecated( + note = "Relative asset!() paths are not supported. Use a path like `/assets/myfile.png` instead of `./assets/myfile.png`" +)] +pub const fn create_bundled_asset_relative( + input_path: &str, + content_hash: &[u8], + asset_config: AssetOptions, +) -> BundledAsset { + create_bundled_asset(input_path, content_hash, asset_config) +} + /// Format the input path with a hash to create an unique output path for the macro in the form `{input_path}-{hash}.{extension}` pub const fn generate_unique_path( input_path: &str, content_hash: u64, asset_config: &AssetOptions, +) -> ConstStr { + let byte_hash = content_hash.to_le_bytes(); + generate_unique_path_with_byte_hash(input_path, &byte_hash, asset_config) +} + +/// Format the input path with a hash to create an unique output path for the macro in the form `{input_path}-{hash}.{extension}` +const fn generate_unique_path_with_byte_hash( + input_path: &str, + content_hash: &[u8], + asset_config: &AssetOptions, ) -> ConstStr { // Format the unique path with the format `{input_path}-{hash}.{extension}` // Start with the input path @@ -43,7 +77,7 @@ pub const fn generate_unique_path( // Hash the contents along with the asset config to create a unique hash for the asset // When this hash changes, the client needs to re-fetch the asset let mut hasher = ConstHasher::new(); - hasher = hasher.write(&content_hash.to_le_bytes()); + hasher = hasher.write(&content_hash); hasher = hasher.hash_by_bytes(asset_config); let hash = hasher.finish(); From 8a4aaa004921b6667ea60b29b71f158f143427e7 Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Thu, 9 Jan 2025 13:11:49 -0600 Subject: [PATCH 03/18] Less aggressive default compression settings --- packages/cli-opt/src/js.rs | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/packages/cli-opt/src/js.rs b/packages/cli-opt/src/js.rs index 4ab05f98e1..d898be47c0 100644 --- a/packages/cli-opt/src/js.rs +++ b/packages/cli-opt/src/js.rs @@ -94,14 +94,9 @@ fn bundle_js_to_writer_inside_handler( None, None, &MinifyOptions { - compress: Some(CompressOptions { - top_level: Some(TopLevelOptions { functions: true }), - ..Default::default() - }), - mangle: Some(MangleOptions { - top_level: Some(true), - ..Default::default() - }), + rename: true, + compress: Some(CompressOptions::default()), + mangle: None, ..Default::default() }, &ExtraOptions { From 2418c47289f470deebb1b49388323e19e75be9a6 Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Thu, 9 Jan 2025 13:12:00 -0600 Subject: [PATCH 04/18] Fix preload crossorigin --- packages/cli/src/build/bundle.rs | 4 ++-- packages/cli/src/build/web.rs | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/cli/src/build/bundle.rs b/packages/cli/src/build/bundle.rs index da89405c59..f70896246a 100644 --- a/packages/cli/src/build/bundle.rs +++ b/packages/cli/src/build/bundle.rs @@ -553,9 +553,9 @@ impl AppBundle { .krate .should_pre_compress_web_assets(self.build.build.release); - let bindgen_dir = self.build.exe_dir(); + let asset_dir = self.build.asset_dir(); tokio::task::spawn_blocking(move || { - crate::fastfs::pre_compress_folder(&bindgen_dir, pre_compress) + crate::fastfs::pre_compress_folder(&asset_dir, pre_compress) }) .await .unwrap()?; diff --git a/packages/cli/src/build/web.rs b/packages/cli/src/build/web.rs index 3bc5f9bf4a..d3d0cda9de 100644 --- a/packages/cli/src/build/web.rs +++ b/packages/cli/src/build/web.rs @@ -91,21 +91,21 @@ impl AppBundle { AssetOptions::Css(css_options) => { if css_options.preloaded() { head_resources.push_str(&format!( - "" + "" )) } } AssetOptions::Image(image_options) => { if image_options.preloaded() { head_resources.push_str(&format!( - "" + "" )) } } AssetOptions::Js(js_options) => { if js_options.preloaded() { head_resources.push_str(&format!( - "" + "" )) } } @@ -122,7 +122,7 @@ impl AppBundle { .expect("WASM asset should exist in web bundles") .bundled_path(); head_resources.push_str(&format!( - "" + "" )); replace_or_insert_before("{style_include}", " Date: Thu, 9 Jan 2025 13:40:43 -0600 Subject: [PATCH 05/18] Fix manganis macro --- packages/manganis/manganis-macro/src/asset.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/manganis/manganis-macro/src/asset.rs b/packages/manganis/manganis-macro/src/asset.rs index 1cea783a5c..7bbcd0fe23 100644 --- a/packages/manganis/manganis-macro/src/asset.rs +++ b/packages/manganis/manganis-macro/src/asset.rs @@ -177,9 +177,6 @@ impl ToTokens for AssetParser { // Note: into_asset_options is not a trait, so we cannot accept the options directly // in the constructor. Stable rust doesn't have support for constant functions in traits const __ASSET_OPTIONS: manganis::AssetOptions = #options.into_asset_options(); - // Get the reference to the string that was generated. We cannot return &'static str from - // generate_unique_path because it would return a reference to data generated in the function - const __ASSET_BUNDLED_PATH_STR: &'static str = __ASSET_BUNDLED_PATH.as_str(); // Create the asset that the crate will use. This is used both in the return value and // added to the linker for the bundler to copy later const __ASSET: manganis::BundledAsset = manganis::macro_helpers::#constructor(__ASSET_SOURCE_PATH, __ASSET_HASH, __ASSET_OPTIONS); From 94e38cdb161a3f69f6b7875e53f887b319a9e6ec Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Thu, 9 Jan 2025 14:13:35 -0600 Subject: [PATCH 06/18] enable aggressive caching in the fullstack asset server --- packages/fullstack/src/server/mod.rs | 34 +++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/packages/fullstack/src/server/mod.rs b/packages/fullstack/src/server/mod.rs index a5993838e3..5a6142c4ce 100644 --- a/packages/fullstack/src/server/mod.rs +++ b/packages/fullstack/src/server/mod.rs @@ -61,15 +61,18 @@ pub mod launch; pub(crate) type ContextProviders = Arc Box + Send + Sync + 'static>>>; -use axum::routing::*; use axum::{ body::{self, Body}, extract::State, http::{Request, Response, StatusCode}, response::IntoResponse, }; +use axum::{routing::*, ServiceExt}; use dioxus_lib::prelude::{Element, VirtualDom}; use http::header::*; +use tower::util::MapResponse; +use tower::ServiceExt as _; +use tower_http::services::fs::ServeFileSystemResponseBody; use std::sync::Arc; @@ -234,10 +237,18 @@ where .collect::>() .join("/"); let route = format!("/{}", route); + // Asset paths are hashed, so we can cache the response on the client side forever. If the + // asset changes, the hash in the path will also change and the client will refetch it. if path.is_dir() { - self = self.nest_service(&route, ServeDir::new(path).precompressed_br()); + self = self.nest_service( + &route, + cache_response_forever(ServeDir::new(path).precompressed_br()), + ); } else { - self = self.nest_service(&route, ServeFile::new(path).precompressed_br()); + self = self.nest_service( + &route, + cache_response_forever(ServeFile::new(path).precompressed_br()), + ); } } @@ -276,6 +287,23 @@ where } } +fn cache_response_forever< + S: ServiceExt, Response = Response>, +>( + service: S, +) -> MapResponse< + S, + fn(Response) -> Response, +> { + service.map_response(|mut response: Response| { + response.headers_mut().insert( + CACHE_CONTROL, + HeaderValue::from_static("public, max-age=31536000, immutable"), + ); + response + }) +} + fn apply_request_parts_to_response( headers: hyper::header::HeaderMap, response: &mut axum::response::Response, From f014b18334d389b65180b5d6cc806c71bfbed4f4 Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Thu, 9 Jan 2025 14:15:09 -0600 Subject: [PATCH 07/18] fix clippy --- packages/cli-opt/src/js.rs | 4 +--- packages/fullstack/src/server/mod.rs | 10 ++++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/cli-opt/src/js.rs b/packages/cli-opt/src/js.rs index d898be47c0..742a064ccc 100644 --- a/packages/cli-opt/src/js.rs +++ b/packages/cli-opt/src/js.rs @@ -5,9 +5,7 @@ use anyhow::Context; use manganis_core::JsAssetOptions; use swc_common::errors::Emitter; use swc_common::errors::Handler; -use swc_ecma_minifier::option::{ - CompressOptions, ExtraOptions, MangleOptions, MinifyOptions, TopLevelOptions, -}; +use swc_ecma_minifier::option::{CompressOptions, ExtraOptions, MinifyOptions}; use swc_ecma_transforms_base::fixer::fixer; use swc_ecma_visit::VisitMutWith; diff --git a/packages/fullstack/src/server/mod.rs b/packages/fullstack/src/server/mod.rs index 5a6142c4ce..314c366d86 100644 --- a/packages/fullstack/src/server/mod.rs +++ b/packages/fullstack/src/server/mod.rs @@ -287,14 +287,16 @@ where } } +type MappedAxumService = MapResponse< + S, + fn(Response) -> Response, +>; + fn cache_response_forever< S: ServiceExt, Response = Response>, >( service: S, -) -> MapResponse< - S, - fn(Response) -> Response, -> { +) -> MappedAxumService { service.map_response(|mut response: Response| { response.headers_mut().insert( CACHE_CONTROL, From 96038e2563ca3f61793080b852bcd7f831c551b2 Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Thu, 9 Jan 2025 14:22:17 -0600 Subject: [PATCH 08/18] final clean up --- packages/manganis/manganis-core/src/hash.rs | 5 +++-- packages/manganis/manganis-macro/src/asset.rs | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/manganis/manganis-core/src/hash.rs b/packages/manganis/manganis-core/src/hash.rs index a55880b76e..9d36ff3841 100644 --- a/packages/manganis/manganis-core/src/hash.rs +++ b/packages/manganis/manganis-core/src/hash.rs @@ -27,9 +27,10 @@ impl std::fmt::Display for AssetHashError { impl Error for AssetHashError {} -/// The hash of an asset +/// The opaque hash type manganis uses to identify assets. Each time an asset or asset options change, this hash will +/// change. This hash is included in the URL of the bundled asset for cache busting. pub struct AssetHash { - /// We use a wrapper type here to hide the exact size of the hash so we can switch to a sha hash in a minor version bump{} + /// We use a wrapper type here to hide the exact size of the hash so we can switch to a sha hash in a minor version bump hash: [u8; 8], } diff --git a/packages/manganis/manganis-macro/src/asset.rs b/packages/manganis/manganis-macro/src/asset.rs index 7bbcd0fe23..4cf95dedc0 100644 --- a/packages/manganis/manganis-macro/src/asset.rs +++ b/packages/manganis/manganis-macro/src/asset.rs @@ -30,7 +30,7 @@ impl std::fmt::Display for AssetParseError { } } -pub fn resolve_path(raw: &str) -> Result { +fn resolve_path(raw: &str) -> Result { // Get the location of the root of the crate which is where all assets are relative to // // IE From 1b680b7611b8c9e504a1a5427bf5642baa9b9cdb Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Thu, 9 Jan 2025 14:50:32 -0600 Subject: [PATCH 09/18] bump cli min rust version --- .github/workflows/main.yml | 24 ++++++++++++------------ .github/workflows/publish.yml | 2 +- packages/cli/Cargo.toml | 2 +- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index a6fd31d9ee..cecf7b9a7f 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -48,7 +48,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: dtolnay/rust-toolchain@1.79.0 + - uses: dtolnay/rust-toolchain@1.84.0 - uses: Swatinem/rust-cache@v2 with: cache-all-crates: "true" @@ -77,7 +77,7 @@ jobs: swap-storage: false - run: sudo apt-get update - run: sudo apt install libwebkit2gtk-4.1-dev libgtk-3-dev libayatana-appindicator3-dev libxdo-dev - - uses: dtolnay/rust-toolchain@1.79.0 + - uses: dtolnay/rust-toolchain@1.84.0 with: components: rustfmt, clippy - uses: Swatinem/rust-cache@v2 @@ -100,7 +100,7 @@ jobs: swap-storage: false - run: sudo apt-get update - run: sudo apt install libwebkit2gtk-4.1-dev libgtk-3-dev libayatana-appindicator3-dev libxdo-dev - - uses: dtolnay/rust-toolchain@1.79.0 + - uses: dtolnay/rust-toolchain@1.84.0 with: components: rustfmt, clippy - uses: Swatinem/rust-cache@v2 @@ -115,7 +115,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: dtolnay/rust-toolchain@1.79.0 + - uses: dtolnay/rust-toolchain@1.84.0 with: components: rustfmt - uses: Swatinem/rust-cache@v2 @@ -156,7 +156,7 @@ jobs: - uses: actions/checkout@v4 - run: sudo apt-get update - run: sudo apt install libwebkit2gtk-4.1-dev libgtk-3-dev libayatana-appindicator3-dev libxdo-dev - - uses: dtolnay/rust-toolchain@1.79.0 + - uses: dtolnay/rust-toolchain@1.84.0 - uses: Swatinem/rust-cache@v2 with: cache-all-crates: "true" @@ -170,7 +170,7 @@ jobs: - uses: actions/checkout@v4 - run: sudo apt-get update - run: sudo apt install libwebkit2gtk-4.1-dev libgtk-3-dev libayatana-appindicator3-dev - - uses: dtolnay/rust-toolchain@1.79.0 + - uses: dtolnay/rust-toolchain@1.84.0 with: components: rustfmt, clippy - uses: Swatinem/rust-cache@v2 @@ -247,7 +247,7 @@ jobs: - { target: aarch64-apple-darwin, os: macos-latest, - toolchain: "1.79.0", + toolchain: "1.84.0", cross: false, command: "test", args: "--all --tests", @@ -255,7 +255,7 @@ jobs: - { target: x86_64-apple-darwin, os: macos-13, - toolchain: "1.79.0", + toolchain: "1.84.0", cross: false, command: "test", args: "--all --tests", @@ -263,7 +263,7 @@ jobs: - { target: aarch64-apple-ios, os: macos-latest, - toolchain: "1.79.0", + toolchain: "1.84.0", cross: false, command: "build", args: "--package dioxus-mobile", @@ -271,7 +271,7 @@ jobs: - { target: aarch64-linux-android, os: ubuntu-latest, - toolchain: "1.79.0", + toolchain: "1.84.0", cross: true, command: "build", args: "--package dioxus-mobile", @@ -327,7 +327,7 @@ jobs: run: | Copy-Item -Path "${{ github.workspace }}" -Destination "${{ env.UV_WORKSPACE }}" -Recurse - - uses: dtolnay/rust-toolchain@1.79.0 + - uses: dtolnay/rust-toolchain@1.84.0 with: components: rustfmt, clippy - uses: Swatinem/rust-cache@v2 @@ -360,7 +360,7 @@ jobs: # runs-on: ubuntu-latest # steps: # - uses: actions/checkout@v4 - # - uses: dtolnay/rust-toolchain@1.79.0 + # - uses: dtolnay/rust-toolchain@1.84.0 # - uses: Swatinem/rust-cache@v2 # with: # cache-all-crates: "true" diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 11fbbe8b59..09d660686f 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -76,7 +76,7 @@ jobs: - name: Install stable uses: dtolnay/rust-toolchain@master with: - toolchain: "1.79.0" + toolchain: "1.84.0" targets: ${{ matrix.platform.target }} - uses: Swatinem/rust-cache@v2 diff --git a/packages/cli/Cargo.toml b/packages/cli/Cargo.toml index 82baa067bf..33e1dfe8ce 100644 --- a/packages/cli/Cargo.toml +++ b/packages/cli/Cargo.toml @@ -7,7 +7,7 @@ description = "CLI for building fullstack web, desktop, and mobile apps with a s repository = "https://github.com/DioxusLabs/dioxus/" license = "MIT OR Apache-2.0" keywords = ["mobile", "gui", "cli", "dioxus", "wasm"] -rust-version = "1.79.0" +rust-version = "1.81.0" [dependencies] dioxus-autofmt = { workspace = true } From 768776675958c9d55052205ffbdc4f6aaba889e6 Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Thu, 9 Jan 2025 14:55:10 -0600 Subject: [PATCH 10/18] fix clippy --- packages/cli-opt/src/js.rs | 4 ++-- packages/cli/src/build/bundle.rs | 2 +- packages/manganis/manganis-core/src/hash.rs | 2 +- packages/manganis/manganis/src/macro_helpers.rs | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/cli-opt/src/js.rs b/packages/cli-opt/src/js.rs index 742a064ccc..8322ab19c8 100644 --- a/packages/cli-opt/src/js.rs +++ b/packages/cli-opt/src/js.rs @@ -63,7 +63,7 @@ fn bundle_js_to_writer_inside_handler( let cm = Lrc::new(SourceMap::new(FilePathMapping::empty())); let node_resolver = NodeModulesResolver::new(TargetEnv::Browser, Default::default(), true); let mut bundler = Bundler::new( - &globals, + globals, cm.clone(), PathLoader { cm: cm.clone() }, node_resolver, @@ -141,7 +141,7 @@ impl Load for PathLoader { &mut Vec::new(), ) .map_err(|err| { - let message = err.into_diagnostic(&handler).message(); + let message = err.into_diagnostic(handler).message(); anyhow::anyhow!("{}", message) }) .context("Failed to parse javascript") diff --git a/packages/cli/src/build/bundle.rs b/packages/cli/src/build/bundle.rs index f70896246a..bc2bf2f1bb 100644 --- a/packages/cli/src/build/bundle.rs +++ b/packages/cli/src/build/bundle.rs @@ -471,7 +471,7 @@ impl AppBundle { .map_err(|e| anyhow::anyhow!("A task failed while trying to copy assets: {e}"))??; // Remove the wasm bindgen output directory if it exists - _ = std::fs::remove_dir_all(&self.build.wasm_bindgen_out_dir()); + _ = std::fs::remove_dir_all(self.build.wasm_bindgen_out_dir()); Ok(()) } diff --git a/packages/manganis/manganis-core/src/hash.rs b/packages/manganis/manganis-core/src/hash.rs index 9d36ff3841..3609d3d220 100644 --- a/packages/manganis/manganis-core/src/hash.rs +++ b/packages/manganis/manganis-core/src/hash.rs @@ -80,7 +80,7 @@ impl AssetHash { let read = file .read(&mut buffer) .map_err(|err| AssetHashError::IoError { - err: err.into(), + err, path: file_path.to_path_buf(), })?; if read == 0 { diff --git a/packages/manganis/manganis/src/macro_helpers.rs b/packages/manganis/manganis/src/macro_helpers.rs index 5e824b261e..8da971fa5f 100644 --- a/packages/manganis/manganis/src/macro_helpers.rs +++ b/packages/manganis/manganis/src/macro_helpers.rs @@ -77,7 +77,7 @@ const fn generate_unique_path_with_byte_hash( // Hash the contents along with the asset config to create a unique hash for the asset // When this hash changes, the client needs to re-fetch the asset let mut hasher = ConstHasher::new(); - hasher = hasher.write(&content_hash); + hasher = hasher.write(content_hash); hasher = hasher.hash_by_bytes(asset_config); let hash = hasher.finish(); From 80f67b6834fb5145913e66e8b9df79eb9ceb3666 Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Thu, 9 Jan 2025 15:02:18 -0600 Subject: [PATCH 11/18] fix new version clippy lints --- packages/desktop/src/app.rs | 1 + packages/desktop/src/webview.rs | 1 + packages/liveview/src/history.rs | 4 ++-- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/desktop/src/app.rs b/packages/desktop/src/app.rs index d41f552506..43d2fe8f25 100644 --- a/packages/desktop/src/app.rs +++ b/packages/desktop/src/app.rs @@ -551,6 +551,7 @@ pub fn hide_app_window(window: &wry::WebView) { // back to the app. `NSApplication::hide:` has the correct behaviour use objc::runtime::Object; use objc::{msg_send, sel, sel_impl}; + #[allow(unexpected_cfgs)] objc::rc::autoreleasepool(|| unsafe { let app: *mut Object = msg_send![objc::class!(NSApplication), sharedApplication]; let nil = std::ptr::null_mut::(); diff --git a/packages/desktop/src/webview.rs b/packages/desktop/src/webview.rs index f155bb9021..ee024bbe61 100644 --- a/packages/desktop/src/webview.rs +++ b/packages/desktop/src/webview.rs @@ -202,6 +202,7 @@ impl WebviewInstance { unsafe { let window: id = window.ns_window() as id; + #[allow(unexpected_cfgs)] let _: () = msg_send![window, setCollectionBehavior: NSWindowCollectionBehavior::NSWindowCollectionBehaviorManaged]; } } diff --git a/packages/liveview/src/history.rs b/packages/liveview/src/history.rs index aed8fcfc7f..20805e812f 100644 --- a/packages/liveview/src/history.rs +++ b/packages/liveview/src/history.rs @@ -320,7 +320,7 @@ impl History for LiveviewHistory { visited_indices .iter() .position(|&rhs| timeline.current_index == rhs) - .map_or(false, |index| { + .is_some_and(|index| { index > 0 && visited_indices[index - 1] == timeline.current_index - 1 }) } @@ -332,7 +332,7 @@ impl History for LiveviewHistory { visited_indices .iter() .rposition(|&rhs| timeline.current_index == rhs) - .map_or(false, |index| { + .is_some_and(|index| { index < visited_indices.len() - 1 && visited_indices[index + 1] == timeline.current_index + 1 }) From c47606989565b5b2e5a9e4ba9ed2d9670c498fc7 Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Thu, 9 Jan 2025 15:15:07 -0600 Subject: [PATCH 12/18] update nix lock --- flake.lock | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/flake.lock b/flake.lock index 2b411256e5..cca696a85e 100644 --- a/flake.lock +++ b/flake.lock @@ -5,11 +5,11 @@ "nixpkgs-lib": "nixpkgs-lib" }, "locked": { - "lastModified": 1722555600, - "narHash": "sha256-XOQkdLafnb/p9ij77byFQjDf5m5QYl9b2REiVClC+x4=", + "lastModified": 1736143030, + "narHash": "sha256-+hu54pAoLDEZT9pjHlqL9DNzWz0NbUn8NEAHP7PQPzU=", "owner": "hercules-ci", "repo": "flake-parts", - "rev": "8471fe90ad337a8074e957b69ca4d0089218391d", + "rev": "b905f6fc23a9051a6e1b741e1438dbfc0634c6de", "type": "github" }, "original": { @@ -20,11 +20,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1724395761, - "narHash": "sha256-zRkDV/nbrnp3Y8oCADf5ETl1sDrdmAW6/bBVJ8EbIdQ=", + "lastModified": 1736241350, + "narHash": "sha256-CHd7yhaDigUuJyDeX0SADbTM9FXfiWaeNyY34FL1wQU=", "owner": "nixos", "repo": "nixpkgs", - "rev": "ae815cee91b417be55d43781eb4b73ae1ecc396c", + "rev": "8c9fd3e564728e90829ee7dbac6edc972971cd0f", "type": "github" }, "original": { @@ -36,23 +36,23 @@ }, "nixpkgs-lib": { "locked": { - "lastModified": 1722555339, - "narHash": "sha256-uFf2QeW7eAHlYXuDktm9c25OxOyCoUOQmh5SZ9amE5Q=", + "lastModified": 1735774519, + "narHash": "sha256-CewEm1o2eVAnoqb6Ml+Qi9Gg/EfNAxbRx1lANGVyoLI=", "type": "tarball", - "url": "https://github.com/NixOS/nixpkgs/archive/a5d394176e64ab29c852d03346c1fc9b0b7d33eb.tar.gz" + "url": "https://github.com/NixOS/nixpkgs/archive/e9b51731911566bbf7e4895475a87fe06961de0b.tar.gz" }, "original": { "type": "tarball", - "url": "https://github.com/NixOS/nixpkgs/archive/a5d394176e64ab29c852d03346c1fc9b0b7d33eb.tar.gz" + "url": "https://github.com/NixOS/nixpkgs/archive/e9b51731911566bbf7e4895475a87fe06961de0b.tar.gz" } }, "nixpkgs_2": { "locked": { - "lastModified": 1718428119, - "narHash": "sha256-WdWDpNaq6u1IPtxtYHHWpl5BmabtpmLnMAx0RdJ/vo8=", + "lastModified": 1728538411, + "narHash": "sha256-f0SBJz1eZ2yOuKUr5CA9BHULGXVSn6miBuUWdTyhUhU=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "e6cea36f83499eb4e9cd184c8a8e823296b50ad5", + "rev": "b69de56fac8c2b6f8fd27f2eca01dcda8e0a4221", "type": "github" }, "original": { @@ -75,11 +75,11 @@ "nixpkgs": "nixpkgs_2" }, "locked": { - "lastModified": 1724638882, - "narHash": "sha256-ap2jIQi/FuUHR6HCht6ASWhoz8EiB99XmI8Esot38VE=", + "lastModified": 1736438724, + "narHash": "sha256-m0CFbWVKtXsAr5OBgWNwR8Uam/jkPIjWgJkdH9DY46M=", "owner": "oxalica", "repo": "rust-overlay", - "rev": "19b70f147b9c67a759e35824b241f1ed92e46694", + "rev": "15897cf5835bb95aa002b42c22dc61079c28f7c8", "type": "github" }, "original": { From e8280052e2661f841dae4129e23e78df8cf3a8fe Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Mon, 13 Jan 2025 17:30:17 -0600 Subject: [PATCH 13/18] Fix asset optimization caching when the CLI is interrupted --- packages/cli-opt/src/file.rs | 48 +++++++++++----- packages/cli-opt/src/folder.rs | 5 +- packages/cli-opt/src/js.rs | 100 ++++++++++++++++++++------------- 3 files changed, 99 insertions(+), 54 deletions(-) diff --git a/packages/cli-opt/src/file.rs b/packages/cli-opt/src/file.rs index 8ef22f3c7d..254a822436 100644 --- a/packages/cli-opt/src/file.rs +++ b/packages/cli-opt/src/file.rs @@ -1,6 +1,6 @@ use anyhow::Context; use manganis_core::{AssetOptions, CssAssetOptions, ImageAssetOptions, JsAssetOptions}; -use std::path::Path; +use std::{ffi::OsStr, path::Path}; use crate::css::process_scss; @@ -14,6 +14,16 @@ pub fn process_file_to( options: &AssetOptions, source: &Path, output_path: &Path, +) -> anyhow::Result<()> { + process_file_to_with_options(options, source, output_path, false) +} + +/// Process a specific file asset with additional options +pub(crate) fn process_file_to_with_options( + options: &AssetOptions, + source: &Path, + output_path: &Path, + in_folder: bool, ) -> anyhow::Result<()> { // If the file already exists, then we must have a file with the same hash // already. The hash has the file contents and options, so if we find a file @@ -26,56 +36,68 @@ pub fn process_file_to( std::fs::create_dir_all(parent)?; } } + + // Processing can be slow. Write to a temporary file first and then rename it to the final output path. If everything + // goes well. Without this, the user could quit in the middle of processing and the file will look complete to the + // caching system even though it is empty. + let mut partial_ext = output_path.extension().unwrap_or_default().to_os_string(); + partial_ext.push(OsStr::new(".partial")); + let temp_output_path = output_path.with_extension(&partial_ext); + let temp_output_path = &temp_output_path; + match options { AssetOptions::Unknown => match source.extension().map(|e| e.to_string_lossy()).as_deref() { Some("css") => { - process_css(&CssAssetOptions::new(), source, output_path)?; + process_css(&CssAssetOptions::new(), source, temp_output_path)?; } Some("scss" | "sass") => { - process_scss(&CssAssetOptions::new(), source, output_path)?; + process_scss(&CssAssetOptions::new(), source, temp_output_path)?; } Some("js") => { - process_js(&JsAssetOptions::new(), source, output_path)?; + process_js(&JsAssetOptions::new(), source, temp_output_path, !in_folder)?; } Some("json") => { - process_json(source, output_path)?; + process_json(source, temp_output_path)?; } Some("jpg" | "jpeg" | "png" | "webp" | "avif") => { - process_image(&ImageAssetOptions::new(), source, output_path)?; + process_image(&ImageAssetOptions::new(), source, temp_output_path)?; } Some(_) | None => { if source.is_dir() { - process_folder(source, output_path)?; + process_folder(source, temp_output_path)?; } else { let source_file = std::fs::File::open(source)?; let mut reader = std::io::BufReader::new(source_file); - let output_file = std::fs::File::create(output_path)?; + let output_file = std::fs::File::create(temp_output_path)?; let mut writer = std::io::BufWriter::new(output_file); std::io::copy(&mut reader, &mut writer).with_context(|| { format!( "Failed to write file to output location: {}", - output_path.display() + temp_output_path.display() ) })?; } } }, AssetOptions::Css(options) => { - process_css(options, source, output_path)?; + process_css(options, source, temp_output_path)?; } AssetOptions::Js(options) => { - process_js(options, source, output_path)?; + process_js(options, source, temp_output_path, !in_folder)?; } AssetOptions::Image(options) => { - process_image(options, source, output_path)?; + process_image(options, source, temp_output_path)?; } AssetOptions::Folder(_) => { - process_folder(source, output_path)?; + process_folder(source, temp_output_path)?; } _ => { tracing::warn!("Unknown asset options: {:?}", options); } } + // If everything was successful, rename the temp file to the final output path + std::fs::rename(temp_output_path, output_path)?; + Ok(()) } diff --git a/packages/cli-opt/src/folder.rs b/packages/cli-opt/src/folder.rs index 699f6d64d8..8873565260 100644 --- a/packages/cli-opt/src/folder.rs +++ b/packages/cli-opt/src/folder.rs @@ -2,7 +2,7 @@ use std::path::Path; use rayon::iter::{IntoParallelRefIterator, ParallelIterator}; -use super::file::process_file_to; +use crate::file::process_file_to_with_options; /// Process a folder, optimizing and copying all assets into the output folder pub fn process_folder(source: &Path, output_folder: &Path) -> anyhow::Result<()> { @@ -32,10 +32,11 @@ pub fn process_folder(source: &Path, output_folder: &Path) -> anyhow::Result<()> /// Optimize a file without changing any of its contents significantly (e.g. by changing the extension) fn process_file_minimal(input_path: &Path, output_path: &Path) -> anyhow::Result<()> { - process_file_to( + process_file_to_with_options( &manganis_core::AssetOptions::Unknown, input_path, output_path, + true, )?; Ok(()) } diff --git a/packages/cli-opt/src/js.rs b/packages/cli-opt/src/js.rs index 8322ab19c8..dcc1c960b6 100644 --- a/packages/cli-opt/src/js.rs +++ b/packages/cli-opt/src/js.rs @@ -5,7 +5,10 @@ use anyhow::Context; use manganis_core::JsAssetOptions; use swc_common::errors::Emitter; use swc_common::errors::Handler; +use swc_common::input::SourceFileInput; use swc_ecma_minifier::option::{CompressOptions, ExtraOptions, MinifyOptions}; +use swc_ecma_parser::lexer::Lexer; +use swc_ecma_parser::Parser; use swc_ecma_transforms_base::fixer::fixer; use swc_ecma_visit::VisitMutWith; @@ -42,6 +45,7 @@ impl Emitter for TracingEmitter { fn bundle_js_to_writer( file: PathBuf, + bundle: bool, minify: bool, write_to: &mut impl std::io::Write, ) -> anyhow::Result<()> { @@ -49,7 +53,7 @@ fn bundle_js_to_writer( let handler = Handler::with_emitter_and_flags(Box::new(TracingEmitter), Default::default()); GLOBALS.set(&globals, || { HANDLER.set(&handler, || { - bundle_js_to_writer_inside_handler(&globals, file, minify, write_to) + bundle_js_to_writer_inside_handler(&globals, file, bundle, minify, write_to) }) }) } @@ -57,34 +61,54 @@ fn bundle_js_to_writer( fn bundle_js_to_writer_inside_handler( globals: &Globals, file: PathBuf, + bundle: bool, minify: bool, write_to: &mut impl std::io::Write, ) -> anyhow::Result<()> { let cm = Lrc::new(SourceMap::new(FilePathMapping::empty())); - let node_resolver = NodeModulesResolver::new(TargetEnv::Browser, Default::default(), true); - let mut bundler = Bundler::new( - globals, - cm.clone(), - PathLoader { cm: cm.clone() }, - node_resolver, - Config { - require: true, - ..Default::default() - }, - Box::new(Hook), - ); - let mut entries = HashMap::default(); - entries.insert("main".to_string(), FileName::Real(file)); - - let mut bundles = bundler - .bundle(entries) - .context("failed to bundle javascript with swc")?; - // Since we only inserted one entry, there should only be one bundle in the output - let bundle = bundles - .pop() - .ok_or_else(|| anyhow::anyhow!("swc did not output any bundles"))?; - - let mut module = bundle.module; + let mut module = if bundle { + let node_resolver = NodeModulesResolver::new(TargetEnv::Browser, Default::default(), true); + let mut bundler = Bundler::new( + globals, + cm.clone(), + PathLoader { cm: cm.clone() }, + node_resolver, + Config { + require: true, + ..Default::default() + }, + Box::new(Hook), + ); + let mut entries = HashMap::default(); + entries.insert("main".to_string(), FileName::Real(file)); + + let mut bundles = bundler + .bundle(entries) + .context("failed to bundle javascript with swc")?; + // Since we only inserted one entry, there should only be one bundle in the output + let bundle = bundles + .pop() + .ok_or_else(|| anyhow::anyhow!("swc did not output any bundles"))?; + bundle.module + } else { + let fm = cm.load_file(Path::new(&file)).expect("Failed to load file"); + + let lexer = Lexer::new( + Default::default(), + Default::default(), + SourceFileInput::from(&*fm), + None, + ); + let mut parser = Parser::new_from(lexer); + + parser.parse_module().map_err(|err| { + HANDLER.with(|handler| { + let message = err.into_diagnostic(handler).message(); + anyhow::anyhow!("{}", message) + }) + })? + }; + if minify { module = swc_ecma_minifier::optimize( std::mem::take(&mut module).into(), @@ -198,24 +222,22 @@ pub(crate) fn process_js( js_options: &JsAssetOptions, source: &Path, output_path: &Path, + bundle: bool, ) -> anyhow::Result<()> { - let mut writer = std::io::BufWriter::new(std::fs::File::create(output_path)?); + let mut writer = std::io::BufWriter::new(std::fs::File::create(&output_path)?); if js_options.minified() { - match bundle_js_to_writer(source.to_path_buf(), true, &mut writer) { - Ok(_) => return Ok(()), - Err(err) => { - tracing::error!("Failed to minify js. Falling back to non-minified: {err}"); - } + if let Err(err) = bundle_js_to_writer(source.to_path_buf(), bundle, true, &mut writer) { + tracing::error!("Failed to minify js. Falling back to non-minified: {err}"); } + } else { + let mut source_file = std::fs::File::open(source)?; + std::io::copy(&mut source_file, &mut writer).with_context(|| { + format!( + "Failed to write js to output location: {}", + output_path.display() + ) + })?; } - let mut source_file = std::fs::File::open(source)?; - std::io::copy(&mut source_file, &mut writer).with_context(|| { - format!( - "Failed to write js to output location: {}", - output_path.display() - ) - })?; - Ok(()) } From ea960382dd0c709f814c5cb69df60213774a78c0 Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Tue, 14 Jan 2025 09:33:24 -0600 Subject: [PATCH 14/18] fix optimization with monaco editor --- packages/cli-opt/src/js.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/cli-opt/src/js.rs b/packages/cli-opt/src/js.rs index dcc1c960b6..f32f89a388 100644 --- a/packages/cli-opt/src/js.rs +++ b/packages/cli-opt/src/js.rs @@ -6,6 +6,7 @@ use manganis_core::JsAssetOptions; use swc_common::errors::Emitter; use swc_common::errors::Handler; use swc_common::input::SourceFileInput; +use swc_ecma_minifier::option::MangleOptions; use swc_ecma_minifier::option::{CompressOptions, ExtraOptions, MinifyOptions}; use swc_ecma_parser::lexer::Lexer; use swc_ecma_parser::Parser; @@ -117,7 +118,7 @@ fn bundle_js_to_writer_inside_handler( None, &MinifyOptions { rename: true, - compress: Some(CompressOptions::default()), + compress: None, mangle: None, ..Default::default() }, From eebb2c0e7a0bdc62dd17e7cc50a100762b132a2b Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Tue, 14 Jan 2025 10:09:44 -0600 Subject: [PATCH 15/18] Add a playwright test to check cli optimizations --- Cargo.lock | 11 ++++++ Cargo.toml | 1 + packages/cli-opt/src/js.rs | 3 +- packages/cli/src/build/bundle.rs | 28 ++++++++++++--- packages/cli/src/build/request.rs | 5 +++ packages/cli/src/cli/mod.rs | 2 +- .../playwright-tests/cli-optimization.spec.js | 11 ++++++ .../cli-optimization/.gitignore | 3 ++ .../cli-optimization/Cargo.toml | 15 ++++++++ .../cli-optimization/build.rs | 14 ++++++++ .../cli-optimization/src/main.rs | 34 +++++++++++++++++++ .../playwright-tests/playwright.config.js | 10 ++++++ 12 files changed, 129 insertions(+), 8 deletions(-) create mode 100644 packages/playwright-tests/cli-optimization.spec.js create mode 100644 packages/playwright-tests/cli-optimization/.gitignore create mode 100644 packages/playwright-tests/cli-optimization/Cargo.toml create mode 100644 packages/playwright-tests/cli-optimization/build.rs create mode 100644 packages/playwright-tests/cli-optimization/src/main.rs diff --git a/Cargo.lock b/Cargo.lock index 6c37e43717..a8d33089dd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3595,6 +3595,16 @@ dependencies = [ "tracing", ] +[[package]] +name = "dioxus-cli-optimization-test" +version = "0.0.1" +dependencies = [ + "dioxus", + "flate2", + "reqwest 0.12.9", + "tar", +] + [[package]] name = "dioxus-config-macro" version = "0.6.1" @@ -10192,6 +10202,7 @@ dependencies = [ "base64 0.22.1", "bytes", "encoding_rs", + "futures-channel", "futures-core", "futures-util", "h2 0.4.7", diff --git a/Cargo.toml b/Cargo.toml index 980e9c5852..a9b8bbe3f4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -100,6 +100,7 @@ members = [ "packages/playwright-tests/fullstack-mounted", "packages/playwright-tests/suspense-carousel", "packages/playwright-tests/nested-suspense", + "packages/playwright-tests/cli-optimization", ] [workspace.package] diff --git a/packages/cli-opt/src/js.rs b/packages/cli-opt/src/js.rs index f32f89a388..60a08ec4e7 100644 --- a/packages/cli-opt/src/js.rs +++ b/packages/cli-opt/src/js.rs @@ -6,8 +6,7 @@ use manganis_core::JsAssetOptions; use swc_common::errors::Emitter; use swc_common::errors::Handler; use swc_common::input::SourceFileInput; -use swc_ecma_minifier::option::MangleOptions; -use swc_ecma_minifier::option::{CompressOptions, ExtraOptions, MinifyOptions}; +use swc_ecma_minifier::option::{ExtraOptions, MinifyOptions}; use swc_ecma_parser::lexer::Lexer; use swc_ecma_parser::Parser; use swc_ecma_transforms_base::fixer::fixer; diff --git a/packages/cli/src/build/bundle.rs b/packages/cli/src/build/bundle.rs index 21d0c9ebbf..150a0d8c63 100644 --- a/packages/cli/src/build/bundle.rs +++ b/packages/cli/src/build/bundle.rs @@ -383,29 +383,41 @@ impl AppBundle { // First, clear the asset dir of any files that don't exist in the new manifest _ = tokio::fs::create_dir_all(&asset_dir).await; // Create a set of all the paths that new files will be bundled to - let bundled_output_paths: HashSet<_> = self + let mut keep_bundled_output_paths: HashSet<_> = self .app .assets .assets .values() .map(|a| asset_dir.join(a.bundled_path())) .collect(); + // The CLI creates a .version file in the asset dir to keep track of what version of the optimizer + // the asset was processed. If that version doesn't match the CLI version, we need to re-optimize + // all assets. + let version_file = self.build.asset_optimizer_version_file(); + let clear_cache = std::fs::read_to_string(&version_file) + .ok() + .filter(|s| s == crate::VERSION.as_str()) + .is_none(); + if clear_cache { + keep_bundled_output_paths.clear(); + } + // one possible implementation of walking a directory only visiting files fn remove_old_assets<'a>( path: &'a Path, - bundled_output_paths: &'a HashSet, + keep_bundled_output_paths: &'a HashSet, ) -> Pin> + Send + 'a>> { Box::pin(async move { // If this asset is in the manifest, we don't need to remove it let canon_path = dunce::canonicalize(path)?; - if bundled_output_paths.contains(canon_path.as_path()) { + if keep_bundled_output_paths.contains(canon_path.as_path()) { return Ok(()); } // Otherwise, if it is a directory, we need to walk it and remove child files if path.is_dir() { for entry in std::fs::read_dir(path)?.flatten() { let path = entry.path(); - remove_old_assets(&path, bundled_output_paths).await?; + remove_old_assets(&path, keep_bundled_output_paths).await?; } if path.read_dir()?.next().is_none() { // If the directory is empty, remove it @@ -420,7 +432,7 @@ impl AppBundle { } tracing::debug!("Removing old assets"); - remove_old_assets(&asset_dir, &bundled_output_paths).await?; + remove_old_assets(&asset_dir, &keep_bundled_output_paths).await?; // todo(jon): we also want to eventually include options for each asset's optimization and compression, which we currently aren't let mut assets_to_transfer = vec![]; @@ -477,6 +489,12 @@ impl AppBundle { // Remove the wasm bindgen output directory if it exists _ = std::fs::remove_dir_all(self.build.wasm_bindgen_out_dir()); + // Write the version file so we know what version of the optimizer we used + std::fs::write( + self.build.asset_optimizer_version_file(), + crate::VERSION.as_str(), + )?; + Ok(()) } diff --git a/packages/cli/src/build/request.rs b/packages/cli/src/build/request.rs index e0d134c5e9..6183429d63 100644 --- a/packages/cli/src/build/request.rs +++ b/packages/cli/src/build/request.rs @@ -737,6 +737,11 @@ impl BuildRequest { } } + /// Get the path to the asset optimizer version file + pub fn asset_optimizer_version_file(&self) -> PathBuf { + self.platform_dir().join(".cli-version") + } + pub fn platform_exe_name(&self) -> String { match self.build.platform() { Platform::MacOS => self.krate.executable_name().to_string(), diff --git a/packages/cli/src/cli/mod.rs b/packages/cli/src/cli/mod.rs index cdd36a09ad..02d362b71d 100644 --- a/packages/cli/src/cli/mod.rs +++ b/packages/cli/src/cli/mod.rs @@ -110,7 +110,7 @@ impl Display for Commands { } } -static VERSION: Lazy = Lazy::new(|| { +pub(crate) static VERSION: Lazy = Lazy::new(|| { format!( "{} ({})", crate::dx_build_info::PKG_VERSION, diff --git a/packages/playwright-tests/cli-optimization.spec.js b/packages/playwright-tests/cli-optimization.spec.js new file mode 100644 index 0000000000..a4678bff93 --- /dev/null +++ b/packages/playwright-tests/cli-optimization.spec.js @@ -0,0 +1,11 @@ +// @ts-check +const { test, expect } = require("@playwright/test"); + +test("optimized scripts run", async ({ page }) => { + await page.goto("http://localhost:8989"); + + // Expect the page to load the script after optimizations have been applied. The script + // should add an editor to the page that shows a main function + const main = page.locator("#main"); + await expect(main).toContainText("hi"); +}); diff --git a/packages/playwright-tests/cli-optimization/.gitignore b/packages/playwright-tests/cli-optimization/.gitignore new file mode 100644 index 0000000000..613fd2f892 --- /dev/null +++ b/packages/playwright-tests/cli-optimization/.gitignore @@ -0,0 +1,3 @@ +dist +target +monaco-editor-0.52.2 \ No newline at end of file diff --git a/packages/playwright-tests/cli-optimization/Cargo.toml b/packages/playwright-tests/cli-optimization/Cargo.toml new file mode 100644 index 0000000000..b26db777ed --- /dev/null +++ b/packages/playwright-tests/cli-optimization/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "dioxus-cli-optimization-test" +version = "0.0.1" +edition = "2021" +description = "Playwright test for Dioxus CLI optimization" +license = "MIT OR Apache-2.0" +publish = false + +[dependencies] +dioxus = { workspace = true, features = ["web"]} + +[build-dependencies] +reqwest = { workspace = true, features = ["blocking"] } +flate2 = "1.0.35" +tar = "0.4.43" diff --git a/packages/playwright-tests/cli-optimization/build.rs b/packages/playwright-tests/cli-optimization/build.rs new file mode 100644 index 0000000000..788ed1ed69 --- /dev/null +++ b/packages/playwright-tests/cli-optimization/build.rs @@ -0,0 +1,14 @@ +use std::path::PathBuf; + +fn main() { + // If the monaco editor folder doesn't exist, download it + let monaco_path = PathBuf::from("monaco-editor-0.52.2"); + if monaco_path.exists() { + return; + } + + let url = "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.52.2.tgz"; + let bytes = reqwest::blocking::get(url).unwrap().bytes().unwrap(); + let mut archive = tar::Archive::new(flate2::read::GzDecoder::new(bytes.as_ref())); + archive.unpack(&monaco_path).unwrap(); +} diff --git a/packages/playwright-tests/cli-optimization/src/main.rs b/packages/playwright-tests/cli-optimization/src/main.rs new file mode 100644 index 0000000000..32cecf8792 --- /dev/null +++ b/packages/playwright-tests/cli-optimization/src/main.rs @@ -0,0 +1,34 @@ +// This test checks the CLI optimizes assets correctly without breaking them + +use dioxus::prelude::*; + +const MONACO_FOLDER: Asset = asset!("/monaco-editor-0.52.2/package/min/vs"); + +fn main() { + dioxus::launch(App); +} + +#[component] +fn App() -> Element { + let script = format!("(() => {{ + require.config({{ paths: {{ vs: '{MONACO_FOLDER}' }} }}); + + require(['vs/editor/editor.main'], () => {{ + var model = monaco.editor.createModel('fn main() {{\\n\\tprintln!(\\\"hi\\\")\\n}}', 'rust'); + var editor = monaco.editor.create(document.getElementById('editor')); + editor.setModel(model); + }}) +}})()"); + rsx! { + div { + id: "editor", + width: "100vw", + height: "100vw", + } + // Monaco script + script { + src: "{MONACO_FOLDER}/loader.js", + "onload": script + } + } +} diff --git a/packages/playwright-tests/playwright.config.js b/packages/playwright-tests/playwright.config.js index 7eaa94619c..130e95fdfa 100644 --- a/packages/playwright-tests/playwright.config.js +++ b/packages/playwright-tests/playwright.config.js @@ -138,5 +138,15 @@ module.exports = defineConfig({ reuseExistingServer: !process.env.CI, stdout: "pipe", }, + { + cwd: path.join(process.cwd(), "cli-optimization"), + // Remove the cache folder for the cli-optimization build to force a full cache reset + command: + 'cargo run --package dioxus-cli --release -- serve --addr "127.0.0.1" --port 8989', + port: 8989, + timeout: 50 * 60 * 1000, + reuseExistingServer: !process.env.CI, + stdout: "pipe", + }, ], }); From 2146574e92bb210d107ee828ebb7baa38a7843da Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Tue, 14 Jan 2025 10:21:01 -0600 Subject: [PATCH 16/18] fix clippy --- packages/cli-opt/src/js.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cli-opt/src/js.rs b/packages/cli-opt/src/js.rs index 60a08ec4e7..d928b84b82 100644 --- a/packages/cli-opt/src/js.rs +++ b/packages/cli-opt/src/js.rs @@ -224,7 +224,7 @@ pub(crate) fn process_js( output_path: &Path, bundle: bool, ) -> anyhow::Result<()> { - let mut writer = std::io::BufWriter::new(std::fs::File::create(&output_path)?); + let mut writer = std::io::BufWriter::new(std::fs::File::create(output_path)?); if js_options.minified() { if let Err(err) = bundle_js_to_writer(source.to_path_buf(), bundle, true, &mut writer) { tracing::error!("Failed to minify js. Falling back to non-minified: {err}"); From d85e428ba39931f53c3a3085ceb06b3a4978bc6a Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Fri, 17 Jan 2025 08:41:12 -0600 Subject: [PATCH 17/18] fix merge conflicts --- packages/cli/src/build/web.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/cli/src/build/web.rs b/packages/cli/src/build/web.rs index 28e10ea259..a3fae3c889 100644 --- a/packages/cli/src/build/web.rs +++ b/packages/cli/src/build/web.rs @@ -212,12 +212,14 @@ impl AppBundle { // The path is actually a web path which is relative to the root of the website let path = path.strip_prefix("/").unwrap_or(path); let asset_dir_path = self + .build .krate .legacy_asset_dir() .map(|dir| dir.join(path).canonicalize()); if let Some(Ok(absolute_path)) = asset_dir_path { - let absolute_crate_root = self.krate.crate_dir().canonicalize().unwrap(); + let absolute_crate_root = + self.build.krate.crate_dir().canonicalize().unwrap(); PathBuf::from("./") .join(absolute_path.strip_prefix(absolute_crate_root).unwrap()) } else { From 5fd2beb2e0e02e8ff039f6c669463349a70016dd Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Tue, 21 Jan 2025 16:53:55 -0600 Subject: [PATCH 18/18] revert server caching changes --- packages/fullstack/src/server/mod.rs | 36 +++------------------------- 1 file changed, 3 insertions(+), 33 deletions(-) diff --git a/packages/fullstack/src/server/mod.rs b/packages/fullstack/src/server/mod.rs index 314c366d86..a5993838e3 100644 --- a/packages/fullstack/src/server/mod.rs +++ b/packages/fullstack/src/server/mod.rs @@ -61,18 +61,15 @@ pub mod launch; pub(crate) type ContextProviders = Arc Box + Send + Sync + 'static>>>; +use axum::routing::*; use axum::{ body::{self, Body}, extract::State, http::{Request, Response, StatusCode}, response::IntoResponse, }; -use axum::{routing::*, ServiceExt}; use dioxus_lib::prelude::{Element, VirtualDom}; use http::header::*; -use tower::util::MapResponse; -use tower::ServiceExt as _; -use tower_http::services::fs::ServeFileSystemResponseBody; use std::sync::Arc; @@ -237,18 +234,10 @@ where .collect::>() .join("/"); let route = format!("/{}", route); - // Asset paths are hashed, so we can cache the response on the client side forever. If the - // asset changes, the hash in the path will also change and the client will refetch it. if path.is_dir() { - self = self.nest_service( - &route, - cache_response_forever(ServeDir::new(path).precompressed_br()), - ); + self = self.nest_service(&route, ServeDir::new(path).precompressed_br()); } else { - self = self.nest_service( - &route, - cache_response_forever(ServeFile::new(path).precompressed_br()), - ); + self = self.nest_service(&route, ServeFile::new(path).precompressed_br()); } } @@ -287,25 +276,6 @@ where } } -type MappedAxumService = MapResponse< - S, - fn(Response) -> Response, ->; - -fn cache_response_forever< - S: ServiceExt, Response = Response>, ->( - service: S, -) -> MappedAxumService { - service.map_response(|mut response: Response| { - response.headers_mut().insert( - CACHE_CONTROL, - HeaderValue::from_static("public, max-age=31536000, immutable"), - ); - response - }) -} - fn apply_request_parts_to_response( headers: hyper::header::HeaderMap, response: &mut axum::response::Response,