Przeglądaj źródła

Fix extremely slow dev builds caused by embedding + compressing assets at compile time (#1395)

William 4 lat temu
rodzic
commit
0d3e2c5542

+ 5 - 0
core/tauri-codegen/src/context.rs

@@ -24,6 +24,7 @@ pub fn context_codegen(data: ContextData) -> Result<TokenStream, EmbeddedAssetsE
   let assets = EmbeddedAssets::new(&dist_dir)?;
 
   // handle default window icons for Windows targets
+  #[cfg(not(debug_assertions))]
   let default_window_icon = if cfg!(windows) {
     let icon_path = config_parent.join("icons/icon.ico").display().to_string();
     quote!(Some(include_bytes!(#icon_path)))
@@ -31,6 +32,10 @@ pub fn context_codegen(data: ContextData) -> Result<TokenStream, EmbeddedAssetsE
     quote!(None)
   };
 
+  // in development builds, don't use an icon as it slows down cargo check
+  #[cfg(debug_assertions)]
+  let default_window_icon = quote!(None);
+
   // double braces are purposeful to force the code into a block expression
   Ok(quote! {{
     use ::tauri::api::private::{OnceCell, AsTauriContext};

+ 9 - 0
core/tauri-codegen/src/embedded_assets.rs

@@ -51,6 +51,7 @@ pub enum EmbeddedAssetsError {
 pub struct EmbeddedAssets(HashMap<AssetKey, (String, Vec<u8>)>);
 
 impl EmbeddedAssets {
+  #[cfg(not(debug_assertions))]
   /// Compress a directory of assets, ready to be generated into a [`tauri_api::assets::Assets`].
   pub fn new(path: &Path) -> Result<Self, EmbeddedAssetsError> {
     WalkDir::new(&path)
@@ -73,6 +74,14 @@ impl EmbeddedAssets {
       .map(Self)
   }
 
+  #[cfg(debug_assertions)]
+  /// A dummy EmbeddedAssets for use during development builds.
+  /// Compressing + including the bytes of assets during development takes a long time.
+  /// On development builds, assets will simply be resolved & fetched from the configured dist folder.
+  pub fn new(_: &Path) -> Result<Self, EmbeddedAssetsError> {
+    Ok(EmbeddedAssets(HashMap::new()))
+  }
+
   /// Use highest compression level for release, the fastest one for everything else
   fn compression_level() -> i32 {
     match var("PROFILE").as_ref().map(String::as_str) {

+ 40 - 12
tauri/src/app/utils.rs

@@ -196,8 +196,11 @@ pub(super) fn build_webview<A: ApplicationExt + 'static>(
           }
         }
       });
-    let assets = context.assets;
     let bundle_identifier = context.config.tauri.bundle.identifier.clone();
+    #[cfg(debug_assertions)]
+    let dist_dir = std::path::PathBuf::from(context.config.build.dist_dir.clone());
+    #[cfg(not(debug_assertions))]
+    let assets = context.assets;
     let custom_protocol = CustomProtocol {
       name: "tauri".into(),
       handler: Box::new(move |path| {
@@ -215,17 +218,42 @@ pub(super) fn build_webview<A: ApplicationExt + 'static>(
           path.chars().skip(1).collect::<String>()
         };
 
-        let asset_response = assets
-          .get(&path)
-          .ok_or(crate::Error::AssetNotFound(path))
-          .map(Cow::into_owned);
-        match asset_response {
-          Ok(asset) => Ok(asset),
-          Err(e) => {
-            #[cfg(debug_assertions)]
-            eprintln!("{:?}", e); // TODO log::error!
-            Err(e)
-          }
+        // In development builds, resolve, read and directly serve assets in the configured dist folder.
+        #[cfg(debug_assertions)]
+        {
+          dist_dir
+            .canonicalize()
+            .or_else(|_| Err(crate::Error::AssetNotFound(path.clone())))
+            .and_then(|pathbuf| {
+              pathbuf
+                .join(path.clone())
+                .canonicalize()
+                .or_else(|_| Err(crate::Error::AssetNotFound(path.clone())))
+                .and_then(|pathbuf| {
+
+                  if pathbuf.is_file() && pathbuf.starts_with(&dist_dir) {
+                    match std::fs::read(pathbuf) {
+                      Ok(asset) => return Ok(asset),
+                      Err(e) => {
+                        #[cfg(debug_assertions)]
+                        eprintln!("Error reading asset from dist: {:?}", e); // TODO log::error!
+                      }
+                    }
+                  }
+
+                  Err(crate::Error::AssetNotFound(path))
+
+                })
+            })
+        }
+
+        // In release builds, fetch + serve decompressed embedded assets.
+        #[cfg(not(debug_assertions))]
+        {
+          assets
+            .get(&path)
+            .ok_or(crate::Error::AssetNotFound(path))
+            .map(Cow::into_owned)
         }
       }),
     };