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 #30129

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

janicduplessis
Copy link
Contributor

@janicduplessis janicduplessis commented Oct 7, 2020

Summary

Use an asset catalog for images on iOS. See related PR in the CLI for the code that generates it react-native-community/cli#1290.

Changelog:

[iOS] [Added] - Use asset catalog for ios images

Test Plan

See react-native-community/cli#1290

Test on RN Tester

  1. Add to root package.json and yarn install
  "resolutions": {
    "@react-native-community/cli-plugin-metro": "janicduplessis/react-native-cli#react-native-community-cli-plugin-metro-v9.1.3-test.0-gitpkg"
  },
  1. PRODUCTION=1 yarn setup-ios-jsc in packages/rn-tester

  2. In Xcode, product -> scheme -> edit scheme -> change Build Configuration to Release.

  3. Build and check that local images are working.

image

@facebook-github-bot facebook-github-bot added CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. Contributor A React Native contributor. labels Oct 7, 2020
@pull-bot
Copy link

pull-bot commented Oct 7, 2020

Warnings
⚠️ 🔒 package.json - Changes were made to package.json. This will require a manual import by a Facebook employee.

Generated by 🚫 dangerJS against 1c7e31b

@react-native-bot react-native-bot added Platform: iOS iOS applications. Type: Enhancement A new feature or enhancement of an existing feature. labels Oct 7, 2020
@analysis-bot
Copy link

analysis-bot commented Oct 7, 2020

Platform Engine Arch Size (bytes) Diff
ios - universal n/a --

Base commit: 950ea91
Branch: main

@analysis-bot
Copy link

analysis-bot commented Oct 7, 2020

Platform Engine Arch Size (bytes) Diff
android hermes arm64-v8a 8,895,039 +1
android hermes armeabi-v7a 7,943,587 +2
android hermes x86 9,292,924 +1
android hermes x86_64 9,194,442 -2
android jsc arm64-v8a 9,482,023 +0
android jsc armeabi-v7a 8,423,567 +0
android jsc x86 9,466,043 -1
android jsc x86_64 9,780,275 +2

Base commit: c27e9e6
Branch: main

@thymikee
Copy link
Contributor

@janicduplessis I haven't dived deep into assets stuff on the CLI side and here, but maybe you have a better overview on this. Now that assets logic is scoped under @react-native/assets package, maybe we could reuse it on the CLI side? We should strive to reuse everything that's possible to avoid these weird syncing situations (this is not the first time).

@janicduplessis
Copy link
Contributor Author

@thymikee This already uses the shared code in the assets package and updates it (just rename a method since it is now used on iOS too).

@janicduplessis
Copy link
Contributor Author

@sota000 Any interest on landing this? I've been using this in my fork for a long time and is stable.

@grabbou
Copy link
Contributor

grabbou commented Feb 15, 2022

It would be great to have a status on this one, there's an outstanding PR in the CLI too.

@kelset
Copy link
Contributor

kelset commented Feb 15, 2022

One think I'd guess would be fixing the conflicts, but yeah also would be great to get some internal 👍/👎 if it's even worth

@janicduplessis janicduplessis marked this pull request as ready for review October 3, 2022 23:47
@facebook-github-bot facebook-github-bot added the Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team. label Oct 4, 2022
@cortinico
Copy link
Contributor

@janicduplessis can we rebase + fix the conflicts here?

@janicduplessis janicduplessis force-pushed the assets-catalog branch 2 times, most recently from 050a242 to f527b5e Compare October 4, 2022 18:49
@janicduplessis
Copy link
Contributor Author

Ok I rebased this and tested again in RN tester. I added instructions on how to do so in the Test Plan. It does require the CLI patched with react-native-community/cli#1290 to work.

I think the main part that is tricky with this is if the app template is not properly updated or for some reason an older version of the cli is used it will break. For the old cli version case it is actually not that bad since the build will error because of invalid parameter --asset-catalog-dest. If the template project is not properly configured then assets won't show in release mode only.

I think it is still fine to move forward, but might want to make sure to document the change to make sure templates are updated properly. The main 2 things that need updating is to create the RNAssets.xcassets catalog and to reorder build scripts so that JS bundle is built before Copy Bundle Resources. For new projects and automated updates that should be fine, but might not be obvious for someone updating manually.

@cipolleschi
Copy link
Contributor

/rebase

@facebook-github-bot
Copy link
Contributor

@cipolleschi has imported this pull request. If you are a Meta employee, you can view this diff on Phabricator.

@cipolleschi
Copy link
Contributor

Weird, this PR makes the template tests fail... Basically, the CLI is not able to create a RN app... Is it expected because it requires react-native-community/cli#1290 ?

@janicduplessis
Copy link
Contributor Author

Oh I see the problem, the template yarn install fails because of error Couldn't find any versions for "@react-native/assets" that matches "1.1.0". Not sure what would be best to handle updating the @react-native/assets package. It is basically just renaming a function since we use it on iOS too now.

@janicduplessis
Copy link
Contributor Author

We might also have build issue later for ios release build since it does require the cli patch

Copy link
Contributor

@cortinico cortinico left a comment

Choose a reason for hiding this comment

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

There is a packages/react-native-codegen/react-native-codegen-0.0.5.tgz that needs to go 👍

@@ -1,6 +1,6 @@
{
"name": "@react-native/assets",
"version": "1.0.0",
"version": "1.1.0",
Copy link
Contributor

Choose a reason for hiding this comment

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

This would require a npm publish of this package OR the use of Verdaccio (which we already have for template tests).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This might also conflict with #34572. Maybe not all template tests use verdaccio currently? Do I need to make some changes for it to pickup the assets package?

Maybe the simplest way would be to just revert the change to the assets package and can land it later as it is not really needed as all it does is rename a function.

Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe the simplest way would be to just revert the change to the assets package and can land it later as it is not really needed as all it does is rename a function.

If possible, let's revert it. We're in the process of migrating our repo to be a proper monorepo and let's try to limit the changes to those packages to only the necessary ones 👍

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok I reverted the change, let's see how CI goes.

@janicduplessis
Copy link
Contributor Author

@javache Thanks for reviewing this. I've reimplemented the logic to convert from the file url to the asset catalog name in objc and made it so it falls back to using the current bundle url logic if the image doesn't exist in the catalog. It will also log a warning.

I've tested that the Image example works with and without an asset catalog (by not passing the asset catalog arg to the CLI). This also makes sure old way to include assets work too and doesn't log a warning.

@pull-bot
Copy link

PR build artifact for 64f025a is ready.
To use, download tarball from "Artifacts" tab in this CircleCI job then run yarn add <path to tarball> in your React Native project.

@pull-bot
Copy link

PR build artifact for 64f025a is ready.
To use, download tarball from "Artifacts" tab in this CircleCI job then run yarn add <path to tarball> in your React Native project.

@pull-bot
Copy link

PR build artifact for 6a1a87a is ready.
To use, download tarball from "Artifacts" tab in this CircleCI job then run yarn add <path to tarball> in your React Native project.

@pull-bot
Copy link

PR build artifact for 6a1a87a is ready.
To use, download tarball from "Artifacts" tab in this CircleCI job then run yarn add <path to tarball> in your React Native project.

@facebook-github-bot
Copy link
Contributor

@cipolleschi has imported this pull request. If you are a Meta employee, you can view this diff on Phabricator.

Comment on lines 759 to 782
// Remove extension
path = [path stringByDeletingPathExtension];

// Remove scale suffix
path = [RCTAssetURLScaleRegex() stringByReplacingMatchesInString:path
options:0
range:NSMakeRange(0, [path length])
withTemplate:@""];

path = [path lowercaseString];

// Encode folder structure in file name
path = [path stringByReplacingOccurrencesOfString:@"/" withString:@"_"];

// Remove illegal chars
path = [RCTAssetURLCharactersRegex() stringByReplacingMatchesInString:path
options:0
range:NSMakeRange(0, [path length])
withTemplate:@""];

// Remove "assets_" prefix
if ([path hasPrefix:@"assets_"]) {
path = [path substringFromIndex:@"assets_".length];
}
Copy link
Member

@javache javache Nov 10, 2022

Choose a reason for hiding this comment

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

This is a really important code path that will be used by any image loaded in RN. Can we optimize it further?

E.g. rather than mutating the string multiple times, could you have a single regular expression that captures in a subgroup the relevant information so we don't have to write it multiple times, like this https://regex101.com/r/6Lqxoc/1

Comment on lines 751 to 782
NSString *__nullable RCTAssetCatalogNameForURL(NSURL *__nullable URL)
{
NSString *path = RCTBundlePathForURL(URL);
// Packager assets always start with assets/
if (path == nil || ![path hasPrefix:@"assets/"]) {
return nil;
}

// Remove extension
path = [path stringByDeletingPathExtension];

// Remove scale suffix
path = [RCTAssetURLScaleRegex() stringByReplacingMatchesInString:path
options:0
range:NSMakeRange(0, [path length])
withTemplate:@""];

path = [path lowercaseString];

// Encode folder structure in file name
path = [path stringByReplacingOccurrencesOfString:@"/" withString:@"_"];

// Remove illegal chars
path = [RCTAssetURLCharactersRegex() stringByReplacingMatchesInString:path
options:0
range:NSMakeRange(0, [path length])
withTemplate:@""];

// Remove "assets_" prefix
if ([path hasPrefix:@"assets_"]) {
path = [path substringFromIndex:@"assets_".length];
}
Copy link
Member

Choose a reason for hiding this comment

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

Is there any documentation by Apple on how asset catalog assets are named that we could reference here as a comment?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This logic is based on how we name the assets when we create the catalog in the rn cli (https://github.com/react-native-community/cli/blob/main/packages/cli-plugin-metro/src/commands/bundle/assetPathUtils.ts#L67). The logic is the same as we use for android, which i know has a lot of limitations about how assets have to be named.

regex = [NSRegularExpression regularExpressionWithPattern:@"[^a-z0-9_]" options:0 error:nil];
});
return regex;
}
Copy link
Member

Choose a reason for hiding this comment

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

Instead of a regular expression, could you use a NSCharacterSet for this?

return image;
} else {
RCTLogWarn(
@"Image %@ not found in the asset catalog. Make sure your app template is updated correctly.", catalogName);
Copy link
Member

@javache javache Nov 10, 2022

Choose a reason for hiding this comment

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

Is there a link to documentation we could provide here?

I'm worried that this warns and then just continues executing, so the warning will likely be ignored.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think we could provide a link to the release notes where it explains this change. However this doesn’t exists yet so I guess it could be added later?

@cipolleschi
Copy link
Contributor

@janicduplessis, there are a couple of comments by @javache that should be addressed. Could you take care of it, please? 🙏

@janicduplessis
Copy link
Contributor Author

Yes, haven’t had the time to address those yet. I should be able to in the next week or so.

@cipolleschi
Copy link
Contributor

/rebase

@cipolleschi
Copy link
Contributor

/rebase

@facebook-github-bot
Copy link
Contributor

@cipolleschi has imported this pull request. If you are a Meta employee, you can view this diff on Phabricator.

facebook-github-bot pushed a commit that referenced this pull request Dec 12, 2023
Summary:
There is currently an error when building in release on iOS when using asset catalogs (experimental feature that is partially merged #30129)

This was probably incorrectly migrated from the community cli repo. `.imageset` is actually folders so it needs to be removed with `{recursive: true, force: true}`. I also renamed the variable `files` which is confusing since its folders.

## Changelog:

[IOS] [FIXED] - Fix cleanAssetCatalog error

Pull Request resolved: #41865

Test Plan: Tested in an app that uses asset catalogs

Reviewed By: NickGerleman

Differential Revision: D52032258

Pulled By: huntie

fbshipit-source-id: 1dc0ca09e0da0d514b03d7d72707bdcaef03301d
Othinn pushed a commit to Othinn/react-native that referenced this pull request Jan 9, 2024
Summary:
There is currently an error when building in release on iOS when using asset catalogs (experimental feature that is partially merged facebook#30129)

This was probably incorrectly migrated from the community cli repo. `.imageset` is actually folders so it needs to be removed with `{recursive: true, force: true}`. I also renamed the variable `files` which is confusing since its folders.

## Changelog:

[IOS] [FIXED] - Fix cleanAssetCatalog error

Pull Request resolved: facebook#41865

Test Plan: Tested in an app that uses asset catalogs

Reviewed By: NickGerleman

Differential Revision: D52032258

Pulled By: huntie

fbshipit-source-id: 1dc0ca09e0da0d514b03d7d72707bdcaef03301d
Copy link

github-actions bot commented Feb 1, 2024

This PR is stale because it has been open 180 days with no activity. Remove stale label or comment or this will be closed in 7 days.

@github-actions github-actions bot added the Stale There has been a lack of activity on this issue and it may be closed soon. label Feb 1, 2024
@janicduplessis
Copy link
Contributor Author

I will one day find time to finish this :)

@github-actions github-actions bot removed the Stale There has been a lack of activity on this issue and it may be closed soon. label Feb 4, 2024
@cortinico cortinico added the Never gets stale Prevent those issues and PRs from getting stale label Feb 4, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. Contributor A React Native contributor. Needs: React Native Team Attention Never gets stale Prevent those issues and PRs from getting stale Platform: iOS iOS applications. Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team. Type: Enhancement A new feature or enhancement of an existing feature.
Projects
None yet
Development

Successfully merging this pull request may close these issues.