Skip to content

Commit e73b08f

Browse files
committed
Document new asset system
1 parent 3a8f9e1 commit e73b08f

File tree

2 files changed

+60
-35
lines changed

2 files changed

+60
-35
lines changed

docs/Image.md renamed to docs/Images.md

Lines changed: 59 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,79 @@
1-
## Static Resources
1+
---
2+
id: images
3+
title: Images
4+
layout: docs
5+
category: Guides
6+
permalink: docs/images.html
7+
next: gesture-responder-system
8+
---
29

3-
Over the course of a project, it is not uncommon to add and remove many images and accidentally end up shipping images you are no longer using in the app. In order to fight this, we need to find a way to know statically which images are being used in the app. To do that, we introduced a marker on require. The only allowed way to refer to an image in the bundle is to literally write `require('image!name-of-the-asset')` in the source.
10+
## Static Image Resources
11+
12+
As of 0.14 release, React Native provides a unified way of managing images in your iOS and Android apps. To add a static image to your app, place it somewhere in your source code tree and reference it like this:
413

514
```javascript
6-
// GOOD
7-
<Image source={require('image!my-icon')} />
15+
<Image source={require('./my-icon.png')} />
16+
```
817

9-
// BAD
10-
var icon = this.props.active ? 'my-icon-active' : 'my-icon-inactive';
11-
<Image source={require('image!' + icon)} />
18+
The image name is resolved the same way JS modules are resolved. In the example above the packager will look for `my-icon.png` in the same folder as the component that requires it. Also if you have `my-icon.ios.png` and `my-icon.android.png`, the packager will pick the file depending on the platform you are running on.
1219

13-
// GOOD
14-
var icon = this.props.active ? require('image!my-icon-active') : require('image!my-icon-inactive');
15-
<Image source={icon} />
20+
You can also use `@2x`, `@3x`, etc. suffix in the file name to provide images for different screen densities. For example, if you have the following file structure:
21+
22+
```
23+
.
24+
├── button.js
25+
└── img
26+
27+
1628
```
1729

18-
When your entire codebase respects this convention, you're able to do interesting things like automatically packaging the assets that are being used in your app. Note that in the current form, nothing is enforced, but it will be in the future.
30+
And `button.js` code contains
1931

20-
### Adding Static Resources to your iOS App using Images.xcassets
32+
```javascript
33+
<Image source={require('./img/check.png')} />
34+
```
2135

22-
![](/react-native/img/StaticImageAssets.png)
36+
Packager will bundle and serve the image corresponding to device's screen density, e.g. on iPhone 5s `check@2x.png` will be used, on Nexus 5 – `[email protected]`. If there is no image matching the screen density, the closest best option will be selected.
2337

24-
> **NOTE**: App build required for new resources
25-
>
26-
> Any time you add a new resource to `Images.xcassets` you will need to re-build your app through Xcode before you can use it - a reload from within the simulator is not enough.
38+
Here are some benefits that you get:
2739

28-
*This process is currently being improved, a much better workflow will be available shortly.*
40+
1. Same system on iOS and Android.
41+
2. Images live in the same folder as your JS code. Components are self-contained.
42+
3. No global namespace, i.e. you don't have worry about name collisions.
43+
4. Only the images that are actually used will be packaged into your app.
44+
5. Adding and changing images doesn't require app recompilation, just refresh the simulator as you normally do.
45+
6. The packager knows the image dimensions, no need to duplicate it in the code.
46+
7. Images can be distributed via [npm](https://www.npmjs.com/) packages.
2947

30-
> **NOTE**: PNG images are required when loading with `require('image!my-icon')`
31-
>
32-
> At this time, only PNG images are supported in iOS. There is an [issue](https://github.com/facebook/react-native/issues/646) that is currently addressing this bug. In the meantime a quick fix is to rename your files to my-icon.png or to use the `uri` property like: `source={{ uri: 'my-icon' }}` instead of `require()`.
48+
Note that in order for this to work, the image name in `require` has to be known statically.
3349

34-
### Adding Static Resources to your Android app
50+
```javascript
51+
// GOOD
52+
<Image source={require('./my-icon.png')} />
3553

36-
Add your images as [bitmap drawables](http://developer.android.com/guide/topics/resources/drawable-resource.html#Bitmap) to the android project (`<yourapp>/android/app/src/main/res`). To provide different resolutions of your assets, check out [using configuration qualifiers](http://developer.android.com/guide/practices/screens_support.html#qualifiers). Normally, you will want to put your assets in the following directories (create them under `res` if they don't exist):
54+
// BAD
55+
var icon = this.props.active ? 'my-icon-active' : 'my-icon-inactive';
56+
<Image source={require('./' + icon + '.png')} />
3757

38-
* `drawable-mdpi` (1x)
39-
* `drawable-hdpi` (1.5x)
40-
* `drawable-xhdpi` (2x)
41-
* `drawable-xxhdpi` (3x)
58+
// GOOD
59+
var icon = this.props.active ? require('./my-icon-active.png') : require('./my-icon-inactive.png');
60+
<Image source={icon} />
61+
```
4262

43-
If you're missing a resolution for your asset, Android will take the next best thing and resize it for you.
63+
NOTE: This system relies on build hooks for [Xcode](https://github.com/facebook/react-native/pull/3523) and [Gradle](https://github.com/facebook/react-native/commit/9dc036d2b99e6233297c55a3490bfc308e34e75f) that are included in new projects generated with `react-native init`. If you generated your projects before that, you'll have to manually add them to your projects to use the new images asset system.
64+
65+
## Images From Hybrid App's Resources
66+
67+
If you are building a hybrid app (some UIs in React Native, some UIs in platform code) you can still use images that are already bundled into the app (via Xcode asset catalogs or Android drawable folder):
68+
69+
```javascript
70+
<Image source={{uri: 'app_icon'}} style={{width: 40, height: 40}} />
71+
```
4472

45-
> **NOTE**: App build required for new resources
46-
>
47-
> Any time you add a new resource to your drawables you will need to re-build your app by running `react-native run-android` before you can use it - reloading the JS is not enough.
73+
Note that this approach provides no safety checks. It's up to you to guarantee that those images are available in the application. Also you have to specify image dimensions manually.
4874

49-
*This process is currently being improved, a much better workflow will be available shortly.*
5075

51-
## Network Resources
76+
## Network Images
5277

5378
Many of the images you will display in your app will not be available at compile time, or you will want to load some dynamically to keep the binary size down. Unlike with static resources, *you will need to manually specify the dimensions of your image.*
5479

@@ -61,7 +86,7 @@ Many of the images you will display in your app will not be available at compile
6186
<Image source={{uri: 'https://facebook.github.io/react/img/logo_og.png'}} />
6287
```
6388

64-
## Local Filesystem Resources
89+
## Local Filesystem Images
6590

6691
See [CameraRoll](/react-native/docs/cameraroll.html) for an example of
6792
using local resources that are outside of `Images.xcassets`.
@@ -90,7 +115,7 @@ In React Native, one interesting decision is that the `src` attribute is named `
90115
<Image source={{uri: 'something.jpg'}} />
91116
```
92117

93-
On the infrastructure side, the reason is that it allows us to attach metadata to this object. For example if you are using `require('image!icon')`, then we add an `isStatic` attribute to flag it as a local file (don't rely on this fact, it's likely to change in the future!). This is also future proofing, for example we may want to support sprites at some point, instead of outputting `{uri: ...}`, we can output `{uri: ..., crop: {left: 10, top: 50, width: 20, height: 40}}` and transparently support spriting on all the existing call sites.
118+
On the infrastructure side, the reason is that it allows us to attach metadata to this object. For example if you are using `require('./my-icon.png')`, then we add information about its actual location and size (don't rely on this fact, it might change in the future!). This is also future proofing, for example we may want to support sprites at some point, instead of outputting `{uri: ...}`, we can output `{uri: ..., crop: {left: 10, top: 50, width: 20, height: 40}}` and transparently support spriting on all the existing call sites.
94119

95120
On the user side, this lets you annotate the object with useful attributes such as the dimension of the image in order to compute the size it's going to be displayed in. Feel free to use it as your data structure to store more information about your image.
96121

docs/Style.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ title: Style
44
layout: docs
55
category: Guides
66
permalink: docs/style.html
7-
next: gesture-responder-system
7+
next: images
88
---
99

1010
React Native doesn't implement CSS but instead relies on JavaScript to let you style your application. This has been a controversial decision and you can read through those slides for the rationale behind it.

0 commit comments

Comments
 (0)