Hello devs, I'm sure you've heard it before— "We need to optimize this code or flow; it's taking too long and hurting the user experience!" Sounds familiar? You’ve got this! 😎🚀
What does optimization actually means..
If your pages are loading slowly, tasks are taking too long to return results, or your landing page is sluggish—chances are users won’t stick around to see what your website has to offer. That’s a clear sign it’s time for optimization!
How?
1. Don't block the main thread
2. Break up your long tasks
You need to understand what tasks are and how browser handles them
What tasks are?
- Task is a piece of work that the browser does.
- That task includes rendering, parsing HTML and CSS, running javascript and other type of work that you might not have direct control over. Of all of this, javascript you write is perhaps the largest source of tasks.
What is a main thread?
1. It is a thread where almost all javascript code you write executes and most tasks are run in the browser.
2. It process tasks 1 by 1 in a queue
Tasks taking more than 50 ms
is considered as long task
Task's blocking time: Total time taken by a task - 50 ms
Should we start with running Long task?
function longTask() {
for (let index = 0; index < 30_000; index++) {
// Emulate CPU load, as using console.log
// with open devtools is a very CPU-intensive operation.
console.log(index);
}
}
Let's try this out..
You will see performance like this 👇 (Go to performance tab by inspecting the element)
It says, long task took 2.55 s
. in RED color, it means, the task took more than what was expected as an ideal time.
Any task exceeding 50ms
is a long task
Example 1
function task(name, num = 5_000) {
console.log(`Starting task: ${name}`);
for (let index = 0; index < num; index++) {
console.log({index});
}
}
function longTask() {
task('1');
task('2');
task('3');
task('4');
task('5');
task('6');
}
useEffect(() => {
longTask()
},[])
Example 2: After breaking long tasks into smaller tasks.
useEffect(() => {
function longTask() {
// Critical tasks.
task('1');
task('3');
// Deferring set of tasks.
setTimeout(() => {
task('2');
task('4');
task('5');
task('6');
});
}
longTask()
},[])
Now as you can see below, one long Task is divided into 4 sub tasks (63.46 ms
+ 836.75 ms
+ 520.72 ms
+ 510.94 ms
)
This technique is known as yielding, works best with sequential tasks.
(In simple terms - setting a setTimeOut in a series of functions is known as yielding.)It helps dividing the tasks into subtasks, so that critical tasks can be executed first then in next task non-critical ones.
Example 3:
async function saveSettings () {
// Do critical work that is user-visible:
task('1');
task('3');
// Yield to the main thread:
await scheduler.yield()
// Work that isn't user-visible, continued in a separate task:
task('2');
task('4');
task('5');
task('6');
}
Alternative of setTimeOut -
-
scheduler.yield()
is an API specifically designed for yielding to the main thread in the browser. - Use scheduler library link
To summarize in short:
- Look what are the priority tasks that will affect user experience.
- Yield to the main thread for crutial tasks.
- Minimize work per function upto 10ms and below 50ms to avoid blocking the thread.
Using these approaches you can improve your web performance effectively.
Go check out part 2 of my exciting blog series on JavaScript performance! 🚀 🤯
If you enjoyed this blog (short and sweet), check out my other blogs too! -
👍 Like and drop a comment if you have any questions or if you find it useful!
Top comments (1)
Checkout 2nd part of this article
dev.to/shelly_agarwal_19/performan...