My app locks up while i am preloading emojis on th...
# compose-web
a
My app locks up while i am preloading emojis on the web. This results in a 2 second freeze (nothing is interactive and the app is unresponsive). The font is Noto Colored Emoji and it's 25mb. is this expected or a bug? Am i missing some option to load this async?
i
processing 25mb of data on web.. yeah, ultimately it's going to block.
a
why does it need to block?
i
because it's web and it only has 1 thread
a typical font is ~100x smaller than what you're trying to load
font loading in html (css) is async but for compose it's going to have to process those symbols at some point and I have to assume for a font size that big they are either extremely numerous or massive and neither is going to be easy to handle
a
got it. thanks Ian will check if browsers expose some specific api for this to be loaded off the main thread
or ultimately find some slimmer emoji font to use
i
I would guess that font has an extremely large number characters/symbols which is the issue.
a
embedding a full emoji font into a website is way too expensive for most cases (even with async loading), which is why e.g. facebook and twitter just load pngs/svgs of emojis on demand, a much more manageable approach
interesting 2
t
I took the ttf file from https://github.com/JetBrains/compose-multiplatform-core/pull/1400/files which is 6.92mb. Didn't find any missing emoji
a
Seems like an old version of the font
latest look like this
😬 1
v
In my case - I simply do not block the app's rendering until the fonts are preloaded. If you diligently followed the preloading advice, it probably told you to do something like:
if (preloaded) { App() }
. So, I just skip the
if
- works just fine, but leave the preloading itself in a
LaunchedEffect
. Of course, if an emoji needs to be shown while still not loaded - it will be shown as
[]
. In my case though Emojis are not something that the user would normally immediately get to see somewhere in the app, so it's not a problem
a
I simply do not block the app's rendering until the fonts are preloaded
you can't. that's what we are discussing. the app freezes during preloading large sized fonts because js is single threaded
o
a browser performs the
fetch
operation asynchronously - it doesn't block the main thread. Otherwise slow internet would make the websites and apps unusable. I'd suggest to try profiling the app - https://developer.chrome.com/docs/devtools/performance#record and find what blocks the thread.
a
it's not the fetching. the blocking happens during
fontFamilyResolver.preload(fontFamily)
is called with a large font (in this case the emojis 25mb)
o
got it. that makes sense
👍 1
a
same thing with large image decoding, the ui just has to block
1
o
could you please report it here https://youtrack.jetbrains.com/issues/CMP ? so we plan it at some point
a
sure. will do when i get the chance
v
I'm not really seeing how: "you can't". As my suggestion is to completely stop this part:
fontFamilyResolver.preload()
up until the point your app is initialized w/o said font. And only then start loading the font and call
preload()
. I just checked and my web app literally loads, a user can interact with it and only afterwards does the
NotoColorEmoji
font start to load 🤔 this is what I was suggesting.
a
@Vidmantas Kerbelis what you are suggesting is how to optimize the UX of your app in order to have the best possible app initialization, by loading fonts only when you need it. what we are discussing is that the moment right after you call
.preload()
your app will block if you ask it to load a large file. you cannot work around this (the app is unresponsive until .preload() returns)
v
Ahh, ok. Got it.
👍 1