cli icon indicating copy to clipboard operation
cli copied to clipboard

Use asset catalog for ios images

Open janicduplessis opened this issue 5 years ago • 6 comments

Summary:

Generates an asset catalog for images on iOS. This allows Xcode to compile it and enables app thinning for RN assets. App thinning will re-bundle the app for each phone so it only includes asset with the right scale.

Presentation about features of asset catalog: https://developer.apple.com/videos/play/wwdc2018/227/

RN PR: https://github.com/facebook/react-native/pull/30129

TODO: Add tests

The approach used is to add assets to a new asset catalog (RNAssets.xcassets). Assets inside the catalog should be gitignored, but the catalog is not. Assets are then added to the catalog at build time, by copying the assets files over and generating a Contents.json file containing info about the asset files. It generates the following directory structure:

ios/myapp/RNAssets.xcassets/
├── folder_folder_myasset.imageset/
│   ├── folder_folder_myasset.png
│   ├── [email protected]
│   ├── [email protected]
│   └── Contents.json

Since the asset catalog is included in the project, it will be compiled to the app Assets.car file which also includes app icons and other image assets in the project.

Asset names need to be unique. To do so we can reuse the method that generates identifiers for android. It uses the full path and replaces / with _.

Asset catalog only works for image files (png, jpeg) so other type of assets will be copied to the bundle as they were before.

Test Plan:

App size

App thinning using iPhone 11

78 png assets, most @2x + @3x, some @1x. Optimized using imageOptim.

Before

bundle: 244kb (741kb on disk) with app thinning: same

After

bundle: 572kb (same on disk) with app thinning: 223kb (same on disk)

Savings: -8.6% (-70% size on disk)

Perf

I made a very non scientific perf measurement of the time it takes to load images by using the following code in RCTLocalAssetImageLoader:

  CFTimeInterval startTime = CACurrentMediaTime();
  UIImage *image = RCTImageFromLocalAssetURL(imageURL);
  CFTimeInterval endTime = CACurrentMediaTime();

Before:

2020-10-07 17:34:08.170162-0400 RNTester[23328:250133] Total Runtime: 3.77165 ms
2020-10-07 17:34:08.171354-0400 RNTester[23328:250133] Total Runtime: 0.034476 ms
2020-10-07 17:34:08.171936-0400 RNTester[23328:250133] Total Runtime: 0.028146 ms
2020-10-07 17:34:08.172646-0400 RNTester[23328:250133] Total Runtime: 0.020793 ms
2020-10-07 17:34:08.174401-0400 RNTester[23328:250133] Total Runtime: 1.44229 ms
2020-10-07 17:34:08.176638-0400 RNTester[23328:250133] Total Runtime: 1.61112 ms
2020-10-07 17:34:08.178917-0400 RNTester[23328:250133] Total Runtime: 1.74392 ms
2020-10-07 17:34:08.180993-0400 RNTester[23328:250133] Total Runtime: 1.45095 ms
2020-10-07 17:34:08.183014-0400 RNTester[23328:250133] Total Runtime: 1.37922 ms
2020-10-07 17:34:08.183732-0400 RNTester[23328:250133] Total Runtime: 0.023126 ms
2020-10-07 17:34:08.184234-0400 RNTester[23328:250133] Total Runtime: 0.032449 ms
2020-10-07 17:34:08.186550-0400 RNTester[23328:250133] Total Runtime: 1.89425 ms
2020-10-07 17:34:08.224563-0400 RNTester[23328:250133] Total Runtime: 0.02623 ms
2020-10-07 17:34:08.224966-0400 RNTester[23328:250133] Total Runtime: 0.02604 ms
2020-10-07 17:34:08.225391-0400 RNTester[23328:250133] Total Runtime: 0.018282 ms
2020-10-07 17:34:08.225842-0400 RNTester[23328:250133] Total Runtime: 0.018324 ms
2020-10-07 17:34:08.226111-0400 RNTester[23328:250133] Total Runtime: 0.019051 ms
2020-10-07 17:34:08.226694-0400 RNTester[23328:250133] Total Runtime: 0.017643 ms
2020-10-07 17:34:08.227014-0400 RNTester[23328:250133] Total Runtime: 0.021447 ms
2020-10-07 17:34:08.227277-0400 RNTester[23328:250133] Total Runtime: 0.015657 ms
2020-10-07 17:34:08.227590-0400 RNTester[23328:250133] Total Runtime: 0.026723 ms
2020-10-07 17:34:08.227929-0400 RNTester[23328:250133] Total Runtime: 0.024189 ms
2020-10-07 17:34:08.312865-0400 RNTester[23328:250133] Total Runtime: 0.020008 ms
2020-10-07 17:34:08.313697-0400 RNTester[23328:250133] Total Runtime: 0.018272 ms
2020-10-07 17:34:08.314180-0400 RNTester[23328:250133] Total Runtime: 0.025033 ms
2020-10-07 17:34:08.314510-0400 RNTester[23328:250133] Total Runtime: 0.016217 ms
2020-10-07 17:34:08.315019-0400 RNTester[23328:250133] Total Runtime: 0.031122 ms
2020-10-07 17:34:08.315371-0400 RNTester[23328:250133] Total Runtime: 0.017915 ms
2020-10-07 17:34:08.315783-0400 RNTester[23328:250133] Total Runtime: 0.030815 ms
2020-10-07 17:34:08.316205-0400 RNTester[23328:250133] Total Runtime: 0.016171 ms
2020-10-07 17:34:08.316545-0400 RNTester[23328:250133] Total Runtime: 0.025192 ms
2020-10-07 17:34:08.316946-0400 RNTester[23328:250133] Total Runtime: 0.0167 ms
2020-10-07 17:34:08.350158-0400 RNTester[23328:250133] Total Runtime: 0.020946 ms

After:

2020-10-07 17:22:59.815553-0400 RNTester[22204:235614] Total Runtime: 4.11902 ms
2020-10-07 17:22:59.816775-0400 RNTester[22204:235614] Total Runtime: 0.653395 ms
2020-10-07 17:22:59.817578-0400 RNTester[22204:235614] Total Runtime: 0.397396 ms
2020-10-07 17:22:59.817887-0400 RNTester[22204:235614] Total Runtime: 0.01817 ms
2020-10-07 17:22:59.818151-0400 RNTester[22204:235614] Total Runtime: 0.015587 ms
2020-10-07 17:22:59.818438-0400 RNTester[22204:235614] Total Runtime: 0.022809 ms
2020-10-07 17:22:59.819156-0400 RNTester[22204:235614] Total Runtime: 0.41775 ms
2020-10-07 17:22:59.820426-0400 RNTester[22204:235614] Total Runtime: 0.140738 ms
2020-10-07 17:22:59.820916-0400 RNTester[22204:235614] Total Runtime: 0.016283 ms
2020-10-07 17:22:59.821543-0400 RNTester[22204:235614] Total Runtime: 0.390289 ms
2020-10-07 17:22:59.822019-0400 RNTester[22204:235614] Total Runtime: 0.1233 ms
2020-10-07 17:22:59.822425-0400 RNTester[22204:235614] Total Runtime: 0.01571 ms
2020-10-07 17:22:59.927458-0400 RNTester[22204:235614] Total Runtime: 0.017485 ms
2020-10-07 17:22:59.927761-0400 RNTester[22204:235614] Total Runtime: 0.01476 ms
2020-10-07 17:22:59.928044-0400 RNTester[22204:235614] Total Runtime: 0.014643 ms
2020-10-07 17:22:59.928332-0400 RNTester[22204:235614] Total Runtime: 0.020834 ms
2020-10-07 17:22:59.929043-0400 RNTester[22204:235614] Total Runtime: 0.017327 ms
2020-10-07 17:22:59.929435-0400 RNTester[22204:235614] Total Runtime: 0.016083 ms
2020-10-07 17:22:59.929762-0400 RNTester[22204:235614] Total Runtime: 0.016492 ms
2020-10-07 17:22:59.930003-0400 RNTester[22204:235614] Total Runtime: 0.018148 ms
2020-10-07 17:22:59.930359-0400 RNTester[22204:235614] Total Runtime: 0.015464 ms
2020-10-07 17:22:59.930640-0400 RNTester[22204:235614] Total Runtime: 0.014644 ms
2020-10-07 17:23:00.002843-0400 RNTester[22204:235614] Total Runtime: 0.020554 ms
2020-10-07 17:23:00.003652-0400 RNTester[22204:235614] Total Runtime: 0.020173 ms
2020-10-07 17:23:00.004073-0400 RNTester[22204:235614] Total Runtime: 0.026731 ms
2020-10-07 17:23:00.004519-0400 RNTester[22204:235614] Total Runtime: 0.02401 ms
2020-10-07 17:23:00.004987-0400 RNTester[22204:235614] Total Runtime: 0.031735 ms
2020-10-07 17:23:00.005772-0400 RNTester[22204:235614] Total Runtime: 0.01752 ms
2020-10-07 17:23:00.006220-0400 RNTester[22204:235614] Total Runtime: 0.025094 ms
2020-10-07 17:23:00.006590-0400 RNTester[22204:235614] Total Runtime: 0.033377 ms
2020-10-07 17:23:00.007082-0400 RNTester[22204:235614] Total Runtime: 0.0197 ms
2020-10-07 17:23:00.007715-0400 RNTester[22204:235614] Total Runtime: 0.015651 ms
2020-10-07 17:23:00.048960-0400 RNTester[22204:235614] Total Runtime: 0.018624 ms

One thing that is interesting is that all assets seems to be only loaded once from the file system. Before we could see multiple calls over 1ms, while with asset catalog only the first load is over 1ms.

janicduplessis avatar Oct 07 '20 06:10 janicduplessis

Interesting! Looking forward to adding some tests :)

thymikee avatar Oct 07 '20 13:10 thymikee

@thymikee Thanks for having a look! Going to work on the RN part of the PR and come back to make the improvements you suggested.

janicduplessis avatar Oct 07 '20 18:10 janicduplessis

Thank you @janicduplessis for sending this over! Been following this discussion on Discord as well, this looks really exciting. Waiting for the updates on the RN side.

grabbou avatar Nov 03 '20 07:11 grabbou

@grabbou @thymikee There has been some progress on the RN side, would it be possible to get this merged and published so we can finalize testing this on RN side? This is fully backwards compatible since it has the same behaviour as before if the new CLI option is not passed so this should be safe.

See https://github.com/facebook/react-native/pull/30129#issuecomment-1269325180

janicduplessis avatar Oct 12 '22 06:10 janicduplessis

cc @adamTrz

kelset avatar Oct 12 '22 09:10 kelset

this PR should be merged first?

Correct 👍

cortinico avatar Oct 14 '22 18:10 cortinico

Hi everyone! Any update on this PR? :D

cipolleschi avatar Oct 17 '22 13:10 cipolleschi