Feat/precompile fonts
Description
I came across this X.com thread: https://x.com/aleqsio/status/1968273285239734405 and I read through the expo font docs: https://docs.expo.dev/versions/latest/sdk/font/
The reason: speed up initial app checks by removing the fontLoad check on iOS and Android.
Based off everything I've read, there is no way to do this on web so I tried to account for that on the PR. Maybe someone from expo can shed some light on this, but the docs don't mention web on the config plugin.
- Issues: #2995
Screenshots
It appears to be working on all three platforms.
Android:
iOS:
Web:
Checklist
- [x] I have manually tested this, including by generating a new app locally (see docs).
Also I apologize, I somehow back tracked a release ci PR.. my bad. Idk how to undo that part.
Hear me out @coolsoftwaretyler / @frankcalise, I feel like the Activity / Suspense boundary mentioned above feels like it doesn't include preloading other things like auth, i18n, navigation state, etc.. It sort of doesn't seem as fluid to me with the other things we are trying to check before displaying the splash screen. What if we did something like this and introduced a new hook that handled this for us and we just call it with some notes?
@ChristopherGabba - I think that's a good point. It's simpler and fits in with the rest of the hook-based loading, IMO. Do you want to push up a commit with that so we can evaluate?
Okay @coolsoftwaretyler / @jamonholmgren,
I think I found a clean approach that allows you to only have to handle the fonts in one place for ios, android, and web.
Basically:
- Drag the font files into
assets/fonts. - Update the imports in the
typography.ts. - Run
npx expo prebuild
By moving the expo-fonts plugin to app.config.ts, we can dynamically bring the files in from typography.ts and we don't have to duplicate it in multiple places. Let me know your thoughts.
I did build this on ios, android, and web and the fonts were present on all of them, but you may double check me again.
One last comment is that is that I placed the new useCustomFonts hook in the typography. Personally I feel like this makes sense to have it in once place, but it could be in its own useCustomFonts hook file.
I'll take another look soon. Thanks @ChristopherGabba!
Okay @coolsoftwaretyler, great comments. I actually figured out a way to rename the files and make all the platforms line up on the file imports! Seems to work great!
Check it out and let me know what else you think is needed.
Looks great, @ChristopherGabba - will you please rebase and fix the conflict? I think we're good after that.
Did I do it? haha never rebased before.
Looks like you merged instead of rebasing (here's the difference). That's OK though, we don't have a super active main branch, and if you resolved conflicts through the GitHub UI, that's what they usually do by default anyway.
Awesome! I've been experimenting with different fonts on import and there's definitely some insistency between different fonts. There may be some fonts where we need to use Platform.select still. Montserrat is one of those where on iOS, the weight is not in the font name.
Can you run an iOS build on your end and make sure it's correctly working?
Hey @ChristopherGabba - can you say more about the inconsistency you're seeing? Maybe post a couple screenshots? I don't think we use Montserrat here.
@coolsoftwaretyler No, I'm just using Monserrat in my personal app, but I have to differentiate between the iOS and android platforms for that particular font.
Note how I'm importing them all with numbers, but the way to reference them still requires me to differentiate.
For some reason, SpaceGrotesk with numbers just works for both without Platform.select. I don't fully understand why because when I go to the info.plist for my app, they show up as numbers. But they literally do not render on iOS unless I use the Platform.select..
Whoa I just figured it out, do not merge this. By following the rules of hooks, I masked the error:
export const useCustomFonts = (): [boolean, Error | null] => {
const [areFontsLoaded, fontError] = useFonts(customFontsToLoad)
if (Platform.OS === "web") {
return [areFontsLoaded, fontError]
}
// On native, fonts are precompiled and ready
return [true, null]
}
This was dynamically loading the font every time regardless and masking the fact that my config plugin wasn't working. I'll fix it, give me a minute.
There we go, now its consistent with mine, you do need to use Platform.select on ios I was wrong, when I fixed the hook per your recommendation, it was dynamically loading the fonts all over again every time.
Ah that makes sense! I'll take another look sometime this week or next. Good catch and thanks for the fix.
Just want to applaud both of you, you are great engineers! Thanks for the guidance, and good team work!
I made the changes suggested by Frank as well, and that lined out the Platforms and removed Platform.select. I also added a console.warn in the config plugin function just to warn the developer if for some reason the fonts are detected in the folder. I also removed the .ttf, didn't realize there were other types!
The updates look good! Thanks for doing this.
I'll try and get to pulling down the branch and testing the changes later today.
Sounds good! Hopefully it all works!