expo: Expo vector icons are not loading up and is producing "3000ms timeout exceeded" loops on Brave Browser
Summary
Upon closer investigation, it has to do with node_module/fontfaceobserver not loading or failing to load from multiple requests resulting in Expo Vector Icons not showing up.
Managed or bare workflow? If you have ios/ or android/ directories in your project, the answer is bare!
bare
What platform(s) does this occur on?
Web
SDK Version (managed workflow only)
No response
Environment
Expo CLI 4.3.2 environment info: System: OS: Windows 10 10.0.19042 Binaries: Node: 12.18.3 - C:\Program Files\nodejs\node.EXE npm: 6.14.6 - C:\Program Files\nodejs\npm.CMD IDEs: Android Studio: Version 4.1.0.0 AI-201.8743.12.41.6858069 npmPackages: expo: ~40.0.0 => 40.0.1 react: 16.13.1 => 16.13.1 react-dom: 16.13.1 => 16.13.1 react-native: ^0.64.0 => 0.64.0 react-native-web: ^0.15.0 => 0.15.0 Expo Workflow: bare
Reproducible demo or steps to reproduce from a blank project
Refreshing the web browser will either Load the icon or produce an “Error: 3000ms timeout exceeded” loop with a bunch of requests from bundle.js.map. Most likely it will produce the error.
I think it is the same issue with #5935. I am using Brave Browser in debugging.
all Expo Vector Icon would either show up or not at all.
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Reactions: 1
- Comments: 41 (6 by maintainers)
Commits related to this issue
- Gracefully handle font observer failure and extend timeout (#22954) # Why Fixes https://github.com/expo/expo/issues/12382 # How The font observer can time out and throw an uncaught exception... — committed to expo/expo by bradjones1 a year ago
- fix: upgrade expo-font Maybe related https://github.com/expo/expo/issues/12382 — committed to hyochan/UncleHyo by hyochan 7 months ago
Issue still present
My two cents as someone who has faced this and used expo vector icons: if you aren’t deep into using
@expo/vector-icons, I recommend not using it if you want to target Web. Instead, use a package that usesreact-native-svg-based icons under the hood.I’ve faced so many issues with this package on Web, so I thought I’d share. It isn’t necessary for an icon set to be a single font. The SVG approach works great and doesn’t have any of the issues with loaders and assets.
If you want to use any of the existing icon sets, you can use SVGr to convert a folder of SVGs into a React Native icon package.
I turned Hero Icons and Iconic into React Native SVG packages with this approach. You can see the script I used in those repos to generate your own icon packs if you’d like. It’s easy to fork and implement.
I know it isn’t a solution to this thread, but figured I’d save someone else the time. (I’m in too deep to remove Expo’s icons, but I get OP’s error everyday on our Sentry on Web, and I wish I could get rid of the package.)
Not stale, still relevant.
Does Expo-Font 11.5.0 have any compatibility issues with Expo 49?
@SleeplessByte
Thanks, great info!
Right, the strange thing though is:
I’m not a fan of introducing arbitrary delays and retries so I will stick to images until this is fixed. I like the idea of switching to
FontFace.load.Thanks for the icon images link, very useful!
After hours of fruitless investigation, I’ve decided to use a workaround of just extracting out the font icons I need into images and using those instead. It’s cumbersome and inflexible, but I also noticed that
MaterialCommunityIcons.ttfwas 1.1MB, so I get the side benefit of less network consumption.label:and changing the color with-fill:Not stale, still relevant.
@findhumane you can find all the icons (as SVG and PNG) on http://materialdesignicons.com/, because that’s what the Material Community Icons font is.
I also read your investigation. It’s really not that complex, but I can support your findings with source code, as I’ve posted before (in this thread).
The package used is
fontfaceobserver, which is imported here:https://github.com/expo/expo/blob/master/packages/expo-font/src/ExpoFontLoader.web.ts#LL2C27-L2C43
…and called here:
https://github.com/expo/expo/blob/master/packages/expo-font/src/ExpoFontLoader.web.ts#L92
As you can see no arguments are passed. In this case, no timeout is given and it will use the default timeout of 3 seconds, as declared here:
https://github.com/bramstein/fontfaceobserver/blob/master/src/observer.js#LL195C51-L195C51
After 3 seconds, it aborts the request.
That’s really it.
You can find previous explorations of the code base here: https://github.com/expo/expo/issues/12382#issuecomment-812946025
And the fix: https://github.com/expo/expo/issues/12382#issuecomment-829338711
I’ve been using a patch to retry automatically for the past 2 years and that works well. I recommend you do the same.
I just hit this issue where icons intermittently fail to load and it’s much stranger than just a simple server-side or network slow-down. Below is a Wireshark capture from the client. The browser (192.168.1.251) sends a request for
/fonts/MaterialCommunityIcons.ttfat 03:05:34.986 (frame 1488) and then, about 4 milliseconds later, the browser sends a TLS Close Notify (frame 1489) and then tears down its half of the socket with a FIN/ACK (frame 1490). Meanwhile, the server (143.198.245.8), in parallel, dutifully responds with a successful HTTP 304 about 40 milliseconds later (frame 1500). In the Firefox network inspector, this request shows as “No response” so it seems this request was canceled by the browser for some reason. Presumably, since the client had already given up on the request, it sends a RST packet for good measure to make sure the server knows it’s not interested in this socket anymore (frame 1502).All of this happens within dozens of milliseconds.
My code right before the call to
Font.loadAsyncprints a timestamp:So the font loading started only about 800ms before the request for that font. So I don’t see any reason why the client should have canceled the request. This is well before the 3000ms timeout error which happens about 2.5 seconds later:
So the first issue is that the font loader seems to be mysteriously canceling its own request for no obvious reason well before the timeout and with the server trying to send a successful response.
At first, I was thinking might be due to scheduling delays, but the seeming canceling of the request well before the timeout seems like a functional issue rather than a timing or scheduling issue.
Then, there is another request for
MaterialCommunityIcons.ttf, although I’m not sure where this is coming from. There are other “Error: 3000ms timeout exceeded” console messages (with characteristically ambiguous stack traces) although from “Uncaught (in promise)” which means it’s not from my directFont.loadAsynccall but must be coming from somewhere else.In any case, that call doesn’t have the TLS Close or RST and succeeds quickly:
I also see the Firefox network panel showing this second request and this time it looks like a healthy response.
On the server-side, everything looks normal for both requests:
Nevertheless, those icons never did load in my app, so the second issue is that a successful loading of the icons may still not show them in the app.
I’ll add some retry loops but I’m worried this will be fruitless because even a successful response didn’t load the icons.
I think this also exposes the long-standing, systemic issue in Expo (and the JS community in general) that these sorts of issues are incredibly hard to create a standalone reproduction for and might depend on various external factors. This might be a good use case to explore alternative diagnostic capabilities of dynamically-enabled debug logging statements that us users of Expo can enable in our apps to help investigate these sorts of issues (e.g. a log statement when the font loader decides to cancel the request, etc.).