Skip to content

Conversation

@iangmaia
Copy link
Contributor

@iangmaia iangmaia commented Jul 8, 2025

Fixes AINFRA-888
Related: p1751876745034679-slack-CC7L49W13

Description

Redundant SPM Dependencies

After the work to consolidate Swift packages such as #15651, we've noticed a substantial increase in app size.

After an investigation, I've noticed the extensions increased quite a bit between app versions:

Purely based on the extensions code and their imports, it seemed that a couple of dependencies declared in Package.swift were redundant. After removing the dependencies, I wasn't able, though, to generate regular development builds, as seen on Buildkite.

I then figured that the file MarkOrderAsReadUseCase.swift was being included in the NotificationService extension, and the extension depended on the Yosemite framework.
There was already logic to conditionally import Yosemite with canImport(Yosemite), but it seems canImport doesn't work with SPM libraries (see related discussion), and perhaps that's the reason why the dependency had to be added. I then removed the dependency but had to introduce the flag NOTIFICATION_EXTENSION.

There are alternatives to this approach, but they would be a bit more involved (like extracting the MarkOrderAsRead functionality entirely to the notification extension), but for now I went for an approach requiring minimal changes.

After removing those dependencies, I've noticed a reasonable decrease in the extensions' .appex file sizes, which should be reflected in the final app size.

Strip Debug Symbols During Copy

In addition to that, I've noticed we had the project flag COPY_PHASE_STRIP set to NO even for release builds (the default is YES). This should impact the frameworks we include in the app (such as StripeTerminal which unstripped is around 41MB alone). About COPY_PHASE_STRIP:

Strip Debug Symbols During Copy
Specifies whether binary files that are copied during the build, such as in a Copy Bundle Resources or Copy Files build phase, should be stripped of debugging symbols. It does not cause the linked product of a target to be stripped—use STRIP_INSTALLED_PRODUCT for that.

Note

Please note that these updates are non-exhaustive and probably there are still ways to further optimize the SPM setup and dependency graph.

Testing information

We should check the prototype builds are still fine, particularly the extensions.
We need also make sure the extensions are working fine in other releases in the regular cycle (Beta, Release).


  • I have considered if this change warrants user-facing release notes and have added them to RELEASE-NOTES.txt if necessary.

@iangmaia iangmaia self-assigned this Jul 8, 2025
@iangmaia iangmaia added the type: enhancement A request for an enhancement. label Jul 8, 2025
@dangermattic
Copy link
Collaborator

dangermattic commented Jul 8, 2025

2 Warnings
⚠️ Modules/Package.swift was changed without updating its corresponding Package.resolved. Please resolve the Swift packages as appropriate to your project setup (e.g. in Xcode or by running swift package resolve).
⚠️ This PR is assigned to the milestone 22.8. This milestone is due in less than 2 days.
Please make sure to get it merged by then or assign it to a milestone with a later deadline.

Generated by 🚫 Danger

@wpmobilebot
Copy link
Collaborator

wpmobilebot commented Jul 8, 2025

App Icon📲 You can test the changes from this Pull Request in WooCommerce iOS Prototype by scanning the QR code below to install the corresponding build.

App NameWooCommerce iOS Prototype
Build Numberpr15884-3e2b347
Version22.7
Bundle IDcom.automattic.alpha.woocommerce
Commit3e2b347
Installation URL13in0a7jr6ud8
Automatticians: You can use our internal self-serve MC tool to give yourself access to those builds if needed.

@iangmaia iangmaia marked this pull request as ready for review July 8, 2025 19:42
@iangmaia iangmaia requested a review from iamgabrielma July 8, 2025 19:44
@iangmaia iangmaia added this to the 22.8 milestone Jul 8, 2025
@iamgabrielma iamgabrielma self-assigned this Jul 9, 2025
@iamgabrielma
Copy link
Contributor

iamgabrielma commented Jul 9, 2025

Thanks for working on this Ian!

I ran the app and did general smoke testing and found no issues, I've also specifically tested notifications and the usages of MarkOrderAsReadUseCase:

  • Simulator iPhone 16 - iOS 18.3.1
  • Physical iPhone 14 - iOS 17.7.1
  • Physical iPad Pro 3rd gen - iPadOS 17.6.1

@joshheald @itsmeichigo since you have Apple watches, would you mind to try and run the app and play around with it (trigger an order notification as well, see if there's any problem when marking it as read), see if we have any trouble? One would be enough 👍

I then figured that the file MarkOrderAsReadUseCase.swift was being included in the NotificationService extension, and it depended on the Yosemite framework.
There was already logic to conditionally import Yosemite with canImport(Yosemite), but it seems canImport doesn't work with SPM libraries (see related discussion), so I had to introduce the flag NOTIFICATION_EXTENSION.

Very interesting, this seems to be related or a side-effect from a separate issue: WOOMOB-772. in here we found that the watch version of the app requires this conditional module imports because skips the usage of Yosemite, so I wonder if once we remove this requirement (there's a task to check if we can simply duplicate the code for these 3 files that are currently shared) we'll see further reduction in the app size since there would also be less repetition of dynamic frameworks being bundled with the binary when not needed 🤔

In addition to that, I've noticed we had the project flag COPY_PHASE_STRIP set to NO even for release builds (the default is YES). This should impact the frameworks we include in the app (such as StripeTerminal which unstripped is around 41MB alone). About COPY_PHASE_STRIP:

Nice, from this issue on Stripe's repo, I wonder if we'll see an additional ~20MB save just by doing this. No way of really knowing until the build goes through app release, right?

I'll wait until we've tested with watch before approving!

@iangmaia
Copy link
Contributor Author

iangmaia commented Jul 9, 2025

this seems to be related or a side-effect from a separate issue: WOOMOB-772. in here we found that the watch version of the app requires this conditional module imports because skips the usage of Yosemite, so I wonder if once we remove this requirement (there's a task to check if we can simply duplicate the code for these 3 files that are currently shared) we'll see further reduction in the app size since there would also be less repetition of dynamic frameworks being bundled with the binary when not needed 🤔

Indeed, definitely related. But I don't think there are more app targets including the Yosemite library; still, a further breakdown will make the code nicer (it's a bit annoying that there are extensions depending on classes outside of its target, though luckily it doesn't seem to happen a lot?).

from this issue on Stripe's repo, I wonder if we'll see an additional ~20MB save just by doing this. No way of really knowing until the build goes through app release, right?

It will definitely make it decrease as well as other Frameworks. I tested it by creating an Archive and comparing the size of the content inside the archive (which is still pre-thinning and uncompressed). That way, the extensions were ~18MB smaller, the Frameworks folder ~6MB smaller. The total .app went from 274MB to 250MB.

Also, please note that these changes were non-exhaustive, there are probably still ways to further optimize the SPM setup and dependency graph.

I'll wait until we've tested with watch before approving!

Thank you! 🙇

@itsmeichigo
Copy link
Contributor

would you mind to try and run the app and play around with it (trigger an order notification as well, see if there's any problem when marking it as read), see if we have any trouble? One would be enough 👍

I tested with the prototype build and the watch app works for me (no crashes). I didn't receive any notification on either the phone or the watch - I hope it's an issue with the alpha build and not from the changes in this PR.

@iamgabrielma
Copy link
Contributor

I tested with the prototype build and the watch app works for me (no crashes). I didn't receive any notification on either the phone or the watch - I hope it's an issue with the alpha build and not from the changes in this PR.

Thanks for testing! Notifications should be unaffected. I did had troubles to receive them until I realized that my test site was not connected to Jetpack, then I started to receive them again. Perhaps that's the issue in your end as well?

I'll approve this one for the moment since the changes seem to cause no new crashes in the watch 👍

@iangmaia iangmaia merged commit 56cffaf into trunk Jul 10, 2025
19 checks passed
@iangmaia iangmaia deleted the iangmaia/optimize-setup-app-size branch July 10, 2025 11:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

type: enhancement A request for an enhancement.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants