Skip to content

Commit 1e0793b

Browse files
feat(core): fallback to file system for AssetResolver::get, closes #8411 (#10357)
* feat(core): fallback to file system for AssetResolver::get, closes #8411 Ports #10356 to v2 * fix test --------- Co-authored-by: Chip Reed <chip@chip.sh>
1 parent d033326 commit 1e0793b

6 files changed

Lines changed: 80 additions & 0 deletions

File tree

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"tauri": patch:enhance
3+
"tauri-codegen": patch:enhance
4+
---
5+
6+
Enhance `AssetResolver::get` in development mode by reading distDir directly as a fallback to the embedded assets.

core/tauri-codegen/src/context.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -483,6 +483,15 @@ pub fn context_codegen(data: ContextData) -> EmbeddedAssetsResult<TokenStream> {
483483
quote!(::std::option::Option::None)
484484
};
485485

486+
let maybe_config_parent_setter = if dev {
487+
let config_parent = config_parent.to_string_lossy();
488+
quote!({
489+
context.with_config_parent(#config_parent);
490+
})
491+
} else {
492+
quote!()
493+
};
494+
486495
Ok(quote!({
487496
#[allow(unused_mut, clippy::let_and_return)]
488497
let mut context = #root::Context::new(
@@ -496,7 +505,10 @@ pub fn context_codegen(data: ContextData) -> EmbeddedAssetsResult<TokenStream> {
496505
#runtime_authority,
497506
#plugin_global_api_script
498507
);
508+
499509
#with_tray_icon_code
510+
#maybe_config_parent_setter
511+
500512
context
501513
}))
502514
}

core/tauri/src/app.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,45 @@ pub struct AssetResolver<R: Runtime> {
269269

270270
impl<R: Runtime> AssetResolver<R> {
271271
/// Gets the app asset associated with the given path.
272+
///
273+
/// Resolves to the embedded asset that is part of the app
274+
/// in dev when [`devPath`](https://tauri.app/v1/api/config/#buildconfig.devpath) points to a folder in your filesystem
275+
/// or in production when [`distDir`](https://tauri.app/v1/api/config/#buildconfig.distdir)
276+
/// points to your frontend assets.
277+
///
278+
/// Fallbacks to reading the asset from the [distDir] folder so the behavior is consistent in development.
279+
/// Note that the dist directory must exist so you might need to build your frontend assets first.
272280
pub fn get(&self, path: String) -> Option<Asset> {
281+
#[cfg(dev)]
282+
{
283+
// on dev if the devPath is a path to a directory we have the embedded assets
284+
// so we can use get_asset() directly
285+
// we only fallback to reading from distDir directly if we're using an external URL (which is likely)
286+
if let (Some(_), Some(crate::utils::config::FrontendDist::Directory(dist_path))) = (
287+
&self.manager.config().build.dev_url,
288+
&self.manager.config().build.frontend_dist,
289+
) {
290+
let asset_path = std::path::PathBuf::from(&path)
291+
.components()
292+
.filter(|c| !matches!(c, std::path::Component::RootDir))
293+
.collect::<std::path::PathBuf>();
294+
295+
let asset_path = self
296+
.manager
297+
.config_parent()
298+
.map(|p| p.join(dist_path).join(&asset_path))
299+
.unwrap_or_else(|| dist_path.join(&asset_path));
300+
return std::fs::read(asset_path).ok().map(|bytes| {
301+
let mime_type = crate::utils::mime_type::MimeType::parse(&bytes, &path);
302+
Asset {
303+
bytes,
304+
mime_type,
305+
csp_header: None,
306+
}
307+
});
308+
}
309+
}
310+
273311
self.manager.get_asset(path).ok()
274312
}
275313

core/tauri/src/lib.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,8 @@ impl<R: Runtime> Assets<R> for EmbeddedAssets {
379379
#[tauri_macros::default_runtime(Wry, wry)]
380380
pub struct Context<R: Runtime> {
381381
pub(crate) config: Config,
382+
#[cfg(dev)]
383+
pub(crate) config_parent: Option<std::path::PathBuf>,
382384
/// Asset provider.
383385
pub assets: Box<dyn Assets<R>>,
384386
pub(crate) default_window_icon: Option<image::Image<'static>>,
@@ -507,6 +509,8 @@ impl<R: Runtime> Context<R> {
507509
) -> Self {
508510
Self {
509511
config,
512+
#[cfg(dev)]
513+
config_parent: None,
510514
assets,
511515
default_window_icon,
512516
app_icon,
@@ -519,6 +523,14 @@ impl<R: Runtime> Context<R> {
519523
plugin_global_api_scripts,
520524
}
521525
}
526+
527+
#[cfg(dev)]
528+
#[doc(hidden)]
529+
pub fn with_config_parent(&mut self, config_parent: impl AsRef<std::path::Path>) {
530+
self
531+
.config_parent
532+
.replace(config_parent.as_ref().to_owned());
533+
}
522534
}
523535

524536
// TODO: expand these docs

core/tauri/src/manager/mod.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,8 @@ pub struct AppManager<R: Runtime> {
179179
pub listeners: Listeners,
180180
pub state: Arc<StateManager>,
181181
pub config: Config,
182+
#[cfg(dev)]
183+
pub config_parent: Option<std::path::PathBuf>,
182184
pub assets: Box<dyn Assets<R>>,
183185

184186
pub app_icon: Option<Vec<u8>>,
@@ -278,6 +280,8 @@ impl<R: Runtime> AppManager<R> {
278280
listeners: Listeners::default(),
279281
state: Arc::new(state),
280282
config: context.config,
283+
#[cfg(dev)]
284+
config_parent: context.config_parent,
281285
assets: context.assets,
282286
app_icon: context.app_icon,
283287
package_info: context.package_info,
@@ -458,6 +462,11 @@ impl<R: Runtime> AppManager<R> {
458462
&self.config
459463
}
460464

465+
#[cfg(dev)]
466+
pub fn config_parent(&self) -> Option<&std::path::PathBuf> {
467+
self.config_parent.as_ref()
468+
}
469+
461470
pub fn package_info(&self) -> &PackageInfo {
462471
&self.package_info
463472
}

core/tauri/src/test/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,9 @@ pub fn mock_context<R: Runtime, A: Assets<R>>(assets: A) -> crate::Context<R> {
135135
pattern: Pattern::Brownfield,
136136
runtime_authority: RuntimeAuthority::new(Default::default(), Resolved::default()),
137137
plugin_global_api_scripts: None,
138+
139+
#[cfg(dev)]
140+
config_parent: None,
138141
}
139142
}
140143

0 commit comments

Comments
 (0)