@@ -7,6 +7,7 @@ use quote::{quote, ToTokens, TokenStreamExt};
77use sha2:: { Digest , Sha256 } ;
88use std:: {
99 collections:: HashMap ,
10+ fmt:: Write ,
1011 fs:: File ,
1112 path:: { Path , PathBuf } ,
1213} ;
@@ -15,12 +16,12 @@ use tauri_utils::config::PatternKind;
1516use thiserror:: Error ;
1617use walkdir:: { DirEntry , WalkDir } ;
1718
19+ #[ cfg( feature = "compression" ) ]
20+ use brotli:: enc:: backward_references:: BrotliEncoderParams ;
21+
1822/// The subdirectory inside the target directory we want to place assets.
1923const TARGET_PATH : & str = "tauri-codegen-assets" ;
2024
21- /// The minimum size needed for the hasher to use multiple threads.
22- const MULTI_HASH_SIZE_LIMIT : usize = 131_072 ; // 128KiB
23-
2425/// (key, (original filepath, compressed bytes))
2526type Asset = ( AssetKey , ( PathBuf , PathBuf ) ) ;
2627
@@ -40,6 +41,9 @@ pub enum EmbeddedAssetsError {
4041 error : std:: io:: Error ,
4142 } ,
4243
44+ #[ error( "failed to create hex from bytes because {0}" ) ]
45+ Hex ( std:: fmt:: Error ) ,
46+
4347 #[ error( "invalid prefix {prefix} used while including path {path}" ) ]
4448 PrefixInvalid { prefix : PathBuf , path : PathBuf } ,
4549
@@ -182,7 +186,7 @@ pub struct AssetOptions {
182186 pub ( crate ) csp : bool ,
183187 pub ( crate ) pattern : PatternKind ,
184188 pub ( crate ) freeze_prototype : bool ,
185- #[ cfg( any ( feature = "isolation" , feature = "__isolation-docs" ) ) ]
189+ #[ cfg( feature = "isolation" ) ]
186190 pub ( crate ) isolation_schema : String ,
187191}
188192
@@ -193,7 +197,7 @@ impl AssetOptions {
193197 csp : false ,
194198 pattern,
195199 freeze_prototype : false ,
196- #[ cfg( any ( feature = "isolation" , feature = "__isolation-docs" ) ) ]
200+ #[ cfg( feature = "isolation" ) ]
197201 isolation_schema : format ! ( "isolation-{}" , uuid:: Uuid :: new_v4( ) ) ,
198202 }
199203 }
@@ -246,13 +250,19 @@ impl EmbeddedAssets {
246250
247251 /// Use highest compression level for release, the fastest one for everything else
248252 #[ cfg( feature = "compression" ) ]
249- fn compression_level ( ) -> i32 {
250- let levels = zstd:: compression_level_range ( ) ;
253+ fn compression_settings ( ) -> BrotliEncoderParams {
254+ let mut settings = BrotliEncoderParams :: default ( ) ;
255+
256+ // the following compression levels are hand-picked and are not min-maxed.
257+ // they have a good balance of runtime vs size for the respective profile goals.
258+ // see the "brotli" section of this comment https://github.com/tauri-apps/tauri/issues/3571#issuecomment-1054847558
251259 if cfg ! ( debug_assertions) {
252- * levels . start ( )
260+ settings . quality = 2
253261 } else {
254- * levels . end ( )
262+ settings . quality = 9
255263 }
264+
265+ settings
256266 }
257267
258268 /// Compress a file and spit out the information in a [`HashMap`] friendly form.
@@ -291,20 +301,24 @@ impl EmbeddedAssets {
291301
292302 // get a hash of the input - allows for caching existing files
293303 let hash = {
294- let mut hasher = blake3:: Hasher :: new ( ) ;
295- if input. len ( ) < MULTI_HASH_SIZE_LIMIT {
296- hasher. update ( & input) ;
297- } else {
298- hasher. update_rayon ( & input) ;
304+ let mut hasher = crate :: vendor:: blake3_reference:: Hasher :: default ( ) ;
305+ hasher. update ( & input) ;
306+
307+ let mut bytes = [ 0u8 ; 32 ] ;
308+ hasher. finalize ( & mut bytes) ;
309+
310+ let mut hex = String :: with_capacity ( 2 * bytes. len ( ) ) ;
311+ for b in bytes {
312+ write ! ( hex, "{:02x}" , b) . map_err ( EmbeddedAssetsError :: Hex ) ?;
299313 }
300- hasher . finalize ( ) . to_hex ( )
314+ hex
301315 } ;
302316
303317 // use the content hash to determine filename, keep extensions that exist
304318 let out_path = if let Some ( ext) = path. extension ( ) . and_then ( |e| e. to_str ( ) ) {
305319 out_dir. join ( format ! ( "{}.{}" , hash, ext) )
306320 } else {
307- out_dir. join ( hash. to_string ( ) )
321+ out_dir. join ( hash)
308322 } ;
309323
310324 // only compress and write to the file if it doesn't already exist.
@@ -328,13 +342,16 @@ impl EmbeddedAssets {
328342 }
329343
330344 #[ cfg( feature = "compression" ) ]
331- // entirely write input to the output file path with compression
332- zstd:: stream:: copy_encode ( & * input, out_file, Self :: compression_level ( ) ) . map_err ( |error| {
333- EmbeddedAssetsError :: AssetWrite {
334- path : path. to_owned ( ) ,
335- error,
336- }
337- } ) ?;
345+ {
346+ let mut input = std:: io:: Cursor :: new ( input) ;
347+ // entirely write input to the output file path with compression
348+ brotli:: BrotliCompress ( & mut input, & mut out_file, & Self :: compression_settings ( ) ) . map_err (
349+ |error| EmbeddedAssetsError :: AssetWrite {
350+ path : path. to_owned ( ) ,
351+ error,
352+ } ,
353+ ) ?;
354+ }
338355 }
339356
340357 Ok ( ( key, ( path. into ( ) , out_path) ) )
0 commit comments