Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use asset catalog for ios images #1290

Merged
merged 1 commit into from
Oct 17, 2022

Conversation

janicduplessis
Copy link
Contributor

@janicduplessis janicduplessis commented Oct 7, 2020

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: facebook/react-native#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
│   ├── folder_folder_myasset@2x.png
│   ├── folder_folder_myasset@3x.png
│   └── 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.

@thymikee thymikee requested a review from grabbou October 7, 2020 13:48
await Promise.all(
imageSet.files.map(async (file) => {
const dest = path.join(imageSet.basePath, file.name);
await fs.copyFile(file.src, dest);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we have a copyFiles utility, maybe worth reuse it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

copyFiles copies all files in a directory so I don't think it could work here where we just want to copy specific files.

@thymikee
Copy link
Member

thymikee commented Oct 7, 2020

Interesting! Looking forward to adding some tests :)

@janicduplessis
Copy link
Contributor Author

@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.

@grabbou
Copy link
Member

grabbou commented Nov 3, 2020

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.

@janicduplessis janicduplessis modified the milestone: ijjm.-pio, Jan 4, 2022
@janicduplessis
Copy link
Contributor Author

@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 facebook/react-native#30129 (comment)

@kelset
Copy link
Member

kelset commented Oct 12, 2022

cc @adamTrz

Copy link
Collaborator

@adamTrz adamTrz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lgtm!
@janicduplessis - if I read conversation from facebook/react-native#30129 correctly, this PR should be merged first?

@cortinico
Copy link
Member

this PR should be merged first?

Correct 👍

@cipolleschi
Copy link
Contributor

cipolleschi commented Oct 17, 2022

Hi everyone! Any update on this PR? :D

@adamTrz adamTrz merged commit b15a964 into react-native-community:main Oct 17, 2022
@janicduplessis janicduplessis deleted the assets-catalog branch October 17, 2022 14:05
thymikee pushed a commit that referenced this pull request Oct 17, 2022
facebook-github-bot pushed a commit to facebook/react-native that referenced this pull request Oct 19, 2022
Summary:
A super small PR to bump CLI to latest available of the 9.x stream, to make available in main the asset image fix (react-native-community/cli#1290) and to be able to cherry pick it back in 0.70 branch.

## Changelog

<!-- Help reviewers and the release process by writing your own changelog entry. For an example, see:
https://reactnative.dev/contributing/changelogs-in-pull-requests
-->

[General] [Changed] - bump CLI to 9.2.1

Pull Request resolved: #35022

Test Plan: CI is green

Reviewed By: dmytrorykun

Differential Revision: D40507344

Pulled By: huntie

fbshipit-source-id: 7c3753e9df154eb5835f021cdfe1b476499afb9a
dmytrorykun pushed a commit to facebook/react-native that referenced this pull request Oct 19, 2022
Summary:
A super small PR to bump CLI to latest available of the 9.x stream, to make available in main the asset image fix (react-native-community/cli#1290) and to be able to cherry pick it back in 0.70 branch.

<!-- Help reviewers and the release process by writing your own changelog entry. For an example, see:
https://reactnative.dev/contributing/changelogs-in-pull-requests
-->

[General] [Changed] - bump CLI to 9.2.1

Pull Request resolved: #35022

Test Plan: CI is green

Reviewed By: dmytrorykun

Differential Revision: D40507344

Pulled By: huntie

fbshipit-source-id: 7c3753e9df154eb5835f021cdfe1b476499afb9a
brentvatne pushed a commit to expo/react-native that referenced this pull request Oct 28, 2022
Summary:
A super small PR to bump CLI to latest available of the 9.x stream, to make available in main the asset image fix (react-native-community/cli#1290) and to be able to cherry pick it back in 0.70 branch.

<!-- Help reviewers and the release process by writing your own changelog entry. For an example, see:
https://reactnative.dev/contributing/changelogs-in-pull-requests
-->

[General] [Changed] - bump CLI to 9.2.1

Pull Request resolved: facebook#35022

Test Plan: CI is green

Reviewed By: dmytrorykun

Differential Revision: D40507344

Pulled By: huntie

fbshipit-source-id: 7c3753e9df154eb5835f021cdfe1b476499afb9a
OlimpiaZurek pushed a commit to OlimpiaZurek/react-native that referenced this pull request May 22, 2023
Summary:
A super small PR to bump CLI to latest available of the 9.x stream, to make available in main the asset image fix (react-native-community/cli#1290) and to be able to cherry pick it back in 0.70 branch.

## Changelog

<!-- Help reviewers and the release process by writing your own changelog entry. For an example, see:
https://reactnative.dev/contributing/changelogs-in-pull-requests
-->

[General] [Changed] - bump CLI to 9.2.1

Pull Request resolved: facebook#35022

Test Plan: CI is green

Reviewed By: dmytrorykun

Differential Revision: D40507344

Pulled By: huntie

fbshipit-source-id: 7c3753e9df154eb5835f021cdfe1b476499afb9a
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants