Is there any way to track renders in your app while still using plain components? I'd like to use it for performance monitoring and testing to make sure that renders are in the correct ballpark during updates.
In the development mode, you can visualize how components mount, update, and unmount, using the performance tools in supported browsers. For example:
To do this in Chrome:
Load your app with ?react_perf in the query string (for example,
http://localhost:3000/?react_perf).
Open the Chrome DevTools Performance tab and press Record.
Perform the actions you want to profile. Don't record more than 20
seconds or Chrome might hang.
Stop recording.
React events will be grouped under the User Timing label.
Note that the numbers are relative so components will render faster
in production. Still, this should help you realize when unrelated UI
gets updated by mistake, and how deep and how often your UI updates
occur.
Related
I want to find tools and technics about how to measure JS thread performance problems in production. I know how to do it in dev mode, for example, I can detect rerenders with https://github.com/welldone-software/why-did-you-render or use Flipper and React Dev tools. However, in production, we can come across slow devices and functionality which works fine on developer's phones or emulators can be slow.
How do you do with it? Maybe we can use something from the native world for IOS and Android.
I found an interesting solution - react-native-performance
It allows measuring:
App startup render time
Navigation render time
Screen re-render time
and send this data to analytics systems https://shopify.github.io/react-native-performance/docs/reporting
Also, it is possible to turn on/off it with feature flag.
Context
A game shipped as a progressive web app which has timers (setTimeout, setInterval) and websocket connections to get real-time communication.
What is happening
Everything is fine as long as the user stays in the app. But when the user goes to another tab, or another app or turns off the screen (in case of mobile), it becomes a "hellish unknown world".
Websockets may or may not become "paused" or "turned off"
Timers look like they are being throttled or debounced.
This behaviour seems to depend on browsers and platform and, maybe, even depend on the particular user behaviour. I guess browsers and OS have their own lifecycle / mechanisms to save battery and/or computation.
When the user comes back, the app is in an unknown state and I am struggling to restore the state properly.
Regarding websockets I have auto-reconnection with socket.io and reconnecting-websocket but it's not enough to solve everything.
Looking for answers
What are the "lifecycles" of the different browsers regarding these? Is this documented? When do they decide to turn off and throttle?
What do they do exactly to websockets? Browsers just disconnect them?
What do they do exactly to timers? They throttle them or debounce them or something else?
What happens to javascript execution in general? Paused / destroyed / throttled?
Is there a way to hook into some kind of browser lifecycle event when it's going to turn things off? The only thing I could find might be the visibility API
Is there a way to artificially reproduce this behaviour to be able to test solutions? It's especially hard on desktop. Websockets can't be turned off and chromium developers don't seem in a hurry to help an issue from 2014(!): websockets not included when using connection throttling
Regardless of the above, is there a pragmatic cross-browser solution to detect / solve this problem? (for example from experience, Firefox on desktop seems to behave completely different compared to Chrome, and an iPhone will disconnect far more often than an Android)
Related Links
Safari dropping web socket connection due to inactivity when page not in focus
Not exactly sure, but you could use service workers. As much as I know, they run in background even if your tab is not opened and get terminated if your tab closes.
Btw. lifecycles of browser tabs seem to be different on every browser, since every browser handles it different. From what I see the browser can freeze tabs if it needs more memory for other things.
Here is the docs from Chrome.
I remembered that there are some events, like onload that tell you if a user has left or reopened the tab. You could use these event to reconnect etc..
I would give different advice regarding how to design your app. From what I understand your intention is to add more logic in order to understand if the user is no longer active in the browser. This entails a different problem which is browser specifics to implement that logic. With that in mind, I would instead invest in have better error handling, both in the server and client.
Errors won't be browser-specific. Handling those will make your app more resilient and agnostic to browser changes, that could eventually change, let's say, the way they hibernate a tab, any other feature that a vendor might implement in the future.
This is an idea that you can find in services architecture, but the same pattern applies to any web-app. You might want to look for Design-for-Fail concepts:
Complexity makes it infeasible to assume robustness on the part of the systems upon which one relies. Instead, one needs to design systems and applications at any given layer in the IT stack-based to assume the possibility of failure at lower levels. Design-for-fail necessitates thinking about fault tolerance at all layers. No longer can application developers confine themselves to thinking about functionality.
https://www.oreilly.com/library/view/designing-delivery/9781491903742/ch04.html
I have an app that makes calls and then updates the screen based on the data coming in. The app is wicked slow on I.E (cant even scroll) but on Chrome the app is very fast. I noticed that if i stop all network calls then the app is also fast on IE. I thought maybe there was too much data on the screen being updated, so i had the Angular controllers stop updating the objects used on the screen; this did not help at all. So then I thought the amount of data on the get-request must be too large; so I changed the ASP.net-WebAPI to have small get requests that would check for an update flag and only request the full array of data if a change was made (this made the total data sent much smaller); these more frequent request with less than a kilobyte each made the app even less responsive!!! So are these "frequent" get-requests (only a few hundred bytes and once every 3 seconds) are way too much for IE to handle? This seems stupid; what is the real reason IE cannot handle my application? Are 20 get-requests/minute each of only a few hundred bytes really killing my app??? I know the renderer in IE is old, but why would my app freeze whenever a network call is made?!
I am using ng-bootstrap in my application. I also am using font-awesome, but taking out font awesome did not help.
Turns a solution to making it run faster is to call enableProdMode(); in the main.ts
Strange that IE was so drastically effected by it while the other browsers were not. Makes it impossible for me to debug that component in IE though...
In the project I am currently working on we are running an angular app on an handheld scanner device (the model is a Motorola MC9200).
We are using a browser called Zetakey web browser to run the web app. This browser by default has javascript garbage collection turned off in order to maintain a reasonable response time.
We discovered that after about 1.5 hours of use the browser crashes because it is out of memory.
As part of our program we use a page refresh to clear all data during a sort of logout sequence.
I think that this is causing the browser to reallocate all the memory on the page and it does not appear to clear the old memory.
I was wondering if there is a simple way in angular or javascript to reset the data without explicitly running through and resetting each variable and property.
[Edited for grammar]
Update:
Zetakey has given us an early deployment of their next browser release where they just slow down the garbage collection cycle instead of killing it completely. It seems to have resolved the issue.
I've found users are not getting updates to my Chrome App because they keep the app open, and let their browser get out of date (i.e. the hamburger icon is red for a prolonged period).
Empirically it seems the chrome.runtime.onUpdateAvailable event is not triggered when the browser itself is out of date.
At a minimum I'd like to display an in-App warning UI to tell the user the need to restart the browser to get updates (and eventually, block usage of the app altogether until updated). It seems like chrome.runtime.onBrowserUpdateAvailable was intended exactly for this, however that event is marked as long deprecated, but the replacement isn't good for this use case: chrome.runtime.onRestartRequired is only supported on Chrome OS, for kiosk apps.
The relevant bugs, http://crbug.com/177029 and http://crbug.com/242983 didn't really explain if onBrowserUpdateAvailable ever worked on non-ChromeOS versions, and if so, why it made sense to deprecate it without replacement on those other OSes.
Am I going about this all wrong? should I just use the deprecated event? Do people know that event works reliably for this scenario across OSes?
(I haven't experimented with the APIs in great depth, and only have the documentation to go on, as browser updates are sufficiently infrequent it's going to be a very long experiment to run, and API behavior may change across versions during that experiment anyway).
If you need users to update to your latest client in order to work with your non-backward-compatible server, then you have complete control over the situation: detect the client mismatch and cease functioning (with a message explaining why) until the user restarts Chrome and gets your updated app.*
But if you're merely annoyed as a matter of hygienics that users aren't updating, it's hard to justify such a drastic approach. Moreover, by definition you're dealing with users who for some reason just plain don't care about updating anything, which is why they've been ignoring the red hamburger for who-knows how long. If this is the case, then adding yet another noisy notification probably isn't going to cure their behavior. Cue your personal equivalent of Serenity Prayer here.
*Side note: I'm surprised that app updates would be stalled because of lack of browser updates. Are you sure your app wasn't updated to specify a minimum_chrome_version? That case would be understandable, because we wouldn't want to update a Chrome App to a version known to be incompatible with the current browser.