You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Currently assets always are given a file name with the /assets/ prefix. It would be convenient to be able to specify a root location to use in the packager. For example, using ~/<build_id> would let us package a JavaScript bundle to use assets that live elsewhere on the file system.
The code that decides which one to use lives here, however it's an implementation detail and it might change (for example if we switch to Xcode's asset catalogs instead).
If I understand correctly, AppHub will download images and put it somewhere on device, and you'd like to make resolution mechanism to be more configurable to be able to load those images instead of pre-bundled ones?
Hey @frantic, yep exactly. Ideally we would like to tell the image loader mechanism where to load images at run time (this is what the swizzle that I linked does). If this is not supported explicitly by RN, then we would like to be able to configure the packager to create a JSBundle which references assets stored on the file system.
I'd rather have a way to configure it from the native side. JS code shouldn't be concerned at all about where the images is actually coming from. Also it will be simpler, because you don't have to regenerate bundles for specific use cases (e.g. whenever app is using AppHub or not).
@nicklockwood any ideas how we can make image loading subsystem more customizable?
Also would like to bring @mkonicek into the discussion here for the Android side (realize you're already occupied with my other patch :))
Right now we have to transform our user's Android JS bundles to reference file:// assets, but it would be nice to have the asset loading mechanism be customizable at run time.
I'm not sure I understand the problem. Is it that you want to be able to globally configure where a relative image path is relative to, so that you can switch the location of the assets folder without changing the JS?
On Android, image paths are transformed by the packager to a flat hierarchy when bundling the APK and stored in the res/drawable folder in the APK. (The flat hierarchy is a requirement as Android doesn't support subfolders in res/drawable.)
Another option might be to invent a new URL scheme like "image://" to use for all your images, and then substitute that with "file://someRootPath/", either on the native or JS side.
On the native side you could do it by creating a custom RCTURLRequestHandler module for that scheme. On the JS side you'd probably need to modify resolveAssetSource.js.
I think getPathInArchive returns a string like "assets_awesomemodule_icon" and that gets passed to native. Wouldn't it be sufficient to customize the native side to make it load all images from a known folder instead of the Android resources (res/drawable)?
@nicklockwood I'm not sure I understand. The overall hope is that our users can use images normally: <Image source={require('./foo.png')} /> but have this evaluate at runtime to file://someRootPath/foo.png where someRootPath might change between different executions of the app (after updates).
@mkonicek Would certainly work if we could customize the native side (ReactImageView) -- though if there was a hook in JS we could maybe find a solution that works on both iOS and Android? Currently ReactImageView does in fact work with file:// urls.
As far as I know, it's not possible to replace Android resources at runtime.
@nicklockwood good to know about RCTURLRequestHandler! Seems like on iOS we can change uri returned by resolveAssetSource to image://... and have a custom handler that would know how to deal with that (by default load from app's bundle). The question is – can third party library override existing bridge module (with the one that would handle image:// differently and allow loading from different location)?
@mkonicek regarding Android I talked to @natthu and he mentioned that Fresco should be able to load images from files instead of using Android's resource manager.
Having thought about this some more, I don't think that a custom protocol is the write way to go for this after all.
I think a simpler approach is going to be to pass an "assetsRoot" param to JS when the bridge initializes, and then resolveAssetSource.js can prepend that path to the local asset uri it puts in the imageSource.
The advantages of this are: It's cross platform; we don't need to mess with the [RCTConvert NSURL:] method (which is static, so would involve messy globals variable); and the same solution can be applied easily to other asset types like sounds, or anything else we want to support in the future.
This isue was only partially fixed as it only works for iOS. I have a PR out that implements the same-ish behaviour on Android - If JSBundle was loaded from the assets folder, load images from the built-in resources. Else, load images from the same folder as the JS bundle.
[UPDATE]: NVM figure it out by reading the unit test for this. Just had to create a folder named drawable-mdpi inside the folder where the js bundle is located.
I still have a question if this is documented anywhere.
Thanks
Hey, was this issue fixed?
I was trying to put images that I use in my bundle via "require" in the same custom folder where I place the js bundle in the android FS but had no luck on loading the images.
Is there any documentation on how should I name the files?
Activity
frantic commentedon Oct 26, 2015
Hey @arbesfeld, as of 0.14rc, assets are either
The code that decides which one to use lives here, however it's an implementation detail and it might change (for example if we switch to Xcode's asset catalogs instead).
If I understand correctly, AppHub will download images and put it somewhere on device, and you'd like to make resolution mechanism to be more configurable to be able to load those images instead of pre-bundled ones?
arbesfeld commentedon Oct 26, 2015
Hey @frantic, yep exactly. Ideally we would like to tell the image loader mechanism where to load images at run time (this is what the swizzle that I linked does). If this is not supported explicitly by RN, then we would like to be able to configure the packager to create a JSBundle which references assets stored on the file system.
I think this line: https://github.com/facebook/react-native/blob/master/packager/react-packager/src/Bundler/index.js#L298 is where the
/assetspath is hard coded into the bundler. If we could change this prefix that would allow us to create a JS bundle that refers to external assets.frantic commentedon Oct 26, 2015
I'd rather have a way to configure it from the native side. JS code shouldn't be concerned at all about where the images is actually coming from. Also it will be simpler, because you don't have to regenerate bundles for specific use cases (e.g. whenever app is using AppHub or not).
@nicklockwood any ideas how we can make image loading subsystem more customizable?
arbesfeld commentedon Oct 26, 2015
Also would like to bring @mkonicek into the discussion here for the Android side (realize you're already occupied with my other patch :))
Right now we have to transform our user's Android JS bundles to reference
file://assets, but it would be nice to have the asset loading mechanism be customizable at run time.nicklockwood commentedon Oct 27, 2015
I'm not sure I understand the problem. Is it that you want to be able to globally configure where a relative image path is relative to, so that you can switch the location of the assets folder without changing the JS?
mkonicek commentedon Oct 27, 2015
On Android, image paths are transformed by the packager to a flat hierarchy when bundling the APK and stored in the
res/drawablefolder in the APK. (The flat hierarchy is a requirement as Android doesn't support subfolders inres/drawable.)The loading from
/drawableis inReactImageView.@arbesfeld Do I understand it correctly that you want to customize
ReactImageViewto load images from somewhere in the file system?cc @foghina
arbesfeld commentedon Oct 27, 2015
@nicklockwood @mkonicek Yep, exactly. We'd like to customize where assets are loaded from without having to change the compiled JS.
Any hooks that would let us modify getPathInArchive (either that one method or the whole file) at runtime would probably suffice for this use case.
nicklockwood commentedon Oct 27, 2015
Another option might be to invent a new URL scheme like "image://" to use for all your images, and then substitute that with "file://someRootPath/", either on the native or JS side.
On the native side you could do it by creating a custom
RCTURLRequestHandlermodule for that scheme. On the JS side you'd probably need to modifyresolveAssetSource.js.mkonicek commentedon Oct 27, 2015
I think
getPathInArchivereturns a string like "assets_awesomemodule_icon" and that gets passed to native. Wouldn't it be sufficient to customize the native side to make it load all images from a known folder instead of the Android resources (res/drawable)?mkonicek commentedon Oct 27, 2015
Or can you simply replace the Android resources (res/drawable) at runtime?
arbesfeld commentedon Oct 27, 2015
@nicklockwood I'm not sure I understand. The overall hope is that our users can use images normally:
<Image source={require('./foo.png')} />but have this evaluate at runtime tofile://someRootPath/foo.pngwheresomeRootPathmight change between different executions of the app (after updates).@mkonicek Would certainly work if we could customize the native side (
ReactImageView) -- though if there was a hook in JS we could maybe find a solution that works on both iOS and Android? CurrentlyReactImageViewdoes in fact work withfile://urls.As far as I know, it's not possible to replace Android resources at runtime.
frantic commentedon Oct 28, 2015
@nicklockwood good to know about
RCTURLRequestHandler! Seems like on iOS we can changeurireturned byresolveAssetSourcetoimage://...and have a custom handler that would know how to deal with that (by default load from app's bundle). The question is – can third party library override existing bridge module (with the one that would handleimage://differently and allow loading from different location)?@mkonicek regarding Android I talked to @natthu and he mentioned that Fresco should be able to load images from files instead of using Android's resource manager.
frantic commentedon Oct 28, 2015
also cc @zahanm
nicklockwood commentedon Oct 28, 2015
Yes, you can create new handlers for existing protocols and assign them a higher priority.
zahanm commentedon Nov 2, 2015
Interesting, yes lets talk about the custom protocol approach if it works cross-platform.
frantic commentedon Nov 3, 2015
I'll give it a spin. We would have to figure something on Android side at some point (@foghina)
nicklockwood commentedon Nov 3, 2015
Having thought about this some more, I don't think that a custom protocol is the write way to go for this after all.
I think a simpler approach is going to be to pass an "assetsRoot" param to JS when the bridge initializes, and then resolveAssetSource.js can prepend that path to the local asset uri it puts in the imageSource.
The advantages of this are: It's cross platform; we don't need to mess with the
[RCTConvert NSURL:]method (which is static, so would involve messy globals variable); and the same solution can be applied easily to other asset types like sounds, or anything else we want to support in the future.frantic commentedon Nov 4, 2015
Just submitted an internal diff to make sure we always load images from the same folder as we load
main.jsbundleLoad assets from same folder as JS bundle
Load assets from same folder as JS bundle
geof90 commentedon Dec 3, 2015
This isue was only partially fixed as it only works for iOS. I have a PR out that implements the same-ish behaviour on Android - If JSBundle was loaded from the assets folder, load images from the built-in resources. Else, load images from the same folder as the JS bundle.
Load assets from same folder as JS bundle
Load assets from same folder as JSbundle (Android)
ciceroneves commentedon Sep 18, 2017
[UPDATE]: NVM figure it out by reading the unit test for this. Just had to create a folder named drawable-mdpi inside the folder where the js bundle is located.
I still have a question if this is documented anywhere.
Thanks
Hey, was this issue fixed?
I was trying to put images that I use in my bundle via "require" in the same custom folder where I place the js bundle in the android FS but had no luck on loading the images.
Is there any documentation on how should I name the files?