Show HN: Speed up your site by running JavaScript when the browser is idle
npmjs.com
npmjs.com
This comment was better than the docs, as usual.
>this is a convenience wrapper around “requestIdleCallback” That's right. I changed README.
https://developer.mozilla.org/en-US/docs/Web/API/Window/requ...
That's right. I changed README to everyone to understand it.
MDN has a good example and looks like this is not supported by Safari -
https://developer.mozilla.org/en-US/docs/Web/API/Background_...
Gecko is the engine behind Firefox and is maintained by Mozilla, so it has a good number of open source contributors that help fix issues when they are found. It also has some issues occasionally but since it has only a ~3% usage these days you don't get as many complaints.
Blink is used by Chromium (which includes Edge, Chrome, Opera, Brave, and Samsung browsers). It has the biggest market share and probably the most people actively paid to work on it.
Webkit is currently only used by Safari and maintained by Apple alone. (Also all iOS browsers have to use webkit which is why iOS chrome has a lot of the same bugs as iOS safari etc). Apple has a conservative approach to Webkit and doesn't implement as many new features or standards as quickly as the other engines. It has the biggest non blink engine market share so it's usually the outlier when it comes to support issues.
Before 2013 Chromium was webkit based, but that year they made a fork and took their engine in a new direction so Webkit lost some of its previous maintainers.
This is far too generous. They intentionally withold features in an effort to push people towards their app store.
It's currently an experimental feature that can be enabled, so hopefully Apple will enable it by default in 2023.
https://github.com/hiroki0525/idle-task/blob/main/src/index....
References - https://developer.chrome.com/blog/using-requestidlecallback/...
This looks well-designed and I'm sure somebody has a usecase for it, but I'm not sure I've ever had one
Those are interactive applications, there's not that much work for them to do when you're not interacting with them.
Any sort of thing that is not urgent and high priority, and where it's no big deal if it's not executed immediately will benefit from being run in requestIdleCallback.
Say you need to call a few rest apis that trigger changes to the DOM. If the user is actively interacting with your application, doing an operation like this, say every 5 seconds, could cause momentary lag that feels bad. What if you could wait to do the update until the main thread is free?
If it isn't, how is this different than async operations?
The downside is it potentially introduces “jank”, where incremental changes render temporarily, and computation time is somewhat slower overall. In my experience/opinion, the tradeoff is worth it around 100-200ms depending on what’s being unblocked.
Seriously, web devs need to learn to respect my battery and electricity bill more.
It's not about doing stuff in a tab that isn't in focus. "Idle" refers to the main thread idling in the page you're currently using, so it's about controlling the execution order and priority of JS tasks. E.g. on Google Maps you give priority to rendering the visible map tiles while deferring preloading the surrounding non-visible tiles until the main thread is unblocked (and thus idling).
It doesn't run stuff when you're the tab is backgrounded (browsers already heavily reduce what sites can do when not in focus[1]). Instead, it just lets you delay work until the page isn't doing anything else (such as rendering the page). For example, you might do this when updating a visualization on a page so that the other updates can complete first (e.g., update the input UI and redraw the visualization when that's done).
[1] https://blog.chromium.org/2020/11/tab-throttling-and-more-pe...
This is not used for malicious CPU hijacking or whatever. It's a way to schedule low-priority JS tasks for later when the main thread is unblocked and give priority to more important things. It's a very useful API for when optimizing games or complex web applications.
For some scripts "facade" solution might work even better than running them on idle. Consider a "chat plugin", that usually pops up each time you visit. If we'd replace chat script with simple dummy button, that loads actual script when user really needs to talk to website support - visitor wins as they are not bothered by popups and site loads faster.
Any ideas how to apply this idea for more 3rd party scripts, especially tracking ones?
Of course, none of this works in Safari, where setTimeout is still your only friend.
For example, you may schedule periodic API polling (and JSON response parsing) using this API to prioritise user input handling.
I would guess (but not know!) that the browser could de-prioritise these tasks even further when the browser decides to (such as when in the background).
Of course there are cases when you need some background activity, for example if you are listening to music or running a program. As I understand, it is extremely difficult do distuinguish between tabs doing useful work and not doing. I would be fine with a manual switch to allow site run in background.
Some initial impressions (based on https://github.com/hiroki0525/idle-task/blob/7e88c8b97c926cf...):
• The cancelIdleCallback fallback implementation will never be defined, so cancelAllIdleTasks will unexpectedly throw an exception in environments like Safari that depend on the polyfill. (Solution: delete lines 14–15.)
• That the simple fallback implementation is a modifying polyfill is not nice, if not clearly stated. Typically better to define it as a local, e.g. `const rIC = typeof requestIdleCallback !== "undefined" ? requestIdleCallback : function …` and subsequently use rIC instead of requestIdleCallback. (Related, I’m not sure quite why you only install the polyfill if self is a thing, are you deliberately ensuring you can’t use this in Node?)
• The default code path is broken, process.env.NODE_ENV will fail in normal browser environments since process is undefined. (And no, no build process gets rid of this, fetch the distributed package and see that its index.js still contains it.)
• Line 74, don’t return a value from a private function if none of the uses use that value; just drop the return keyword.
• Lines 86–93, splitting logArgs out doesn’t make sense to me, it’s functionally harmless, but needless bloat. (I am perennially disappointed at the utterly primitive state of JavaScript bundlers/optimisers/minifiers: especially with TypeScript knowledge of the interfaces being touched, reordering and inlining is a trivial and obvious optimisation that only changes behaviour on bonkers code that deserves to get broken, but no tool will do it, though Closure Compiler’s advanced optimisations mode might be able to be coaxed into doing it—if it even supports spread syntax.)
• The vibe I’m getting is that this works with a mixture of callbacks and promises, and ends up complicated because of it, parts of it feeling like the ’90s and parts like the mid-’10s. The modern approach would be to use abort signals, which… eh, they’re simpler in some cases, more complicated in others. But from this library’s perspective, you could replace the entire interface with just one promise-returning function, which I’d name schedule(task, options), with options including {signal: AbortSignal}. Cancellation would be handled a bit differently, but it’d be more flexible, because it’s left up to the caller how they hook cancellation up (want to be able to cancel a subset of all the tasks together? Easy, give them the same signal). And I think the code of this library would be simplified by going all in on such a pattern.
https://github.com/pastelsky/network-idle-callback
Helpful for progressively hydrating features in a page, or loading assets for next interaction
The point of this is to run low-priority tasks without impacting the main loop, and without the complexity of separate threads.
What would be an example?
It’s low priority, and perhaps it’s quick, but there is no reason it can’t when idle.
ducks
from the link you provided…
Be respectful. Anyone sharing work is making a contribution, however modest.
Ask questions out of curiosity. Don't cross-examine.
Instead of "you're doing it wrong", suggest alternatives. When someone is learning, help them learn more.
When something isn't good, you needn't pretend that it is, but don't be gratuitously negative.
Reflexive snark comment that's not even about the thing being shown is none of that. And there's also
Please don't post shallow dismissals, especially of other people's work.
from
You clearly don't like my idea, but that doesn't mean it isn't valid.
At least in the old days if CSS or JS didn't load, you still got a semi-usable page.
Turning HTML+CSS+JS into an application platform has been one of the most fundamentally stupid things we've done as a field and we'll keep paying for it for years on end, second only to not adding slices to C.
This is really about how to make your UI more responsive by performing intensive tasks only when your browser isn’t doing any other tasks related to the javascript code.
In non JS applications, you typically would do this on any thread but the UI thread. But with Javascript, you have the option of doing tasks on the main thread, but only when all other tasks are not being executed. IE a priority queue.