1. Dependency Graph
A tree-like structure created by module bundlers based on imports, which allows applications to be broken down into smaller chunks for code splitting and lazy loading.
Hear it at 0:31 →Engineering video
6:12 · 17 June 2024
A tree-like structure created by module bundlers based on imports, which allows applications to be broken down into smaller chunks for code splitting and lazy loading.
Hear it at 0:31 →Using imports as functions within code to request bundles from the server on demand, returning module contents via a promise.
Hear it at 1:00 →Contrasts client-side rendering (which can lead to a blank white screen while waiting for the bundle) with server-side rendering (which delivers fully rendered HTML faster).
Hear it at 1:43 →Making server-rendered HTML interactive by attaching event listeners and connecting it to the client-rendered component structure using hydrate root.
Hear it at 1:32 →The mechanism where the call stack executes synchronous code, followed by processing microtasks (like promise resolves) and task queues (like timeouts).
Hear it at 2:52 →Writing CSS inside JavaScript files and using a module bundler to generate unique class names added to the document head, preventing style conflicts.
Hear it at 4:00 →The browser process of fetching HTML and CSS, building the DOM and CSSOM, combining them into a render tree, performing layout, and painting the content.
Hear it at 4:57 →How script attributes affect loading and execution relative to rendering, such as deferring script execution until after the first render.
Hear it at 5:41 →Technical interviews suck, but they suck a lot less if, number one, you've seen the questions before, and number two, you can answer questions using mental models. In this video, I will go over five senior frontend interview questions that me or my mentees got, and five mental models that you can use to answer these questions, so you don't freeze in your next interview and get closer to that offer stage.
Number one, explain how code splitting works. Code splitting, it's breaking up your application bundle into smaller chunks that can be lazy loaded, instead of loading the whole thing at once. But how does it really work under the hood? For that, we need to understand our first mental model, the dependency graph. Based on your imports, the module bundle creates a dependency graph. They take all your code and put it together in a tree-like structure.
Because all our code is there, we can now split it by identifying different sections of this tree that can actually be packaged independently. And this is what code splitting is. It's literally just separating that big bundle into smaller independent bundlers that can be lazy loaded or loaded on demand. And that leads us to the next senior front end mental model, dynamic imports. We talked already about static imports, but we also can actually use imports inside our code as functions.
What happens under the hood when we do that is that we are actually going to the server to get that bundle, and whenever that arrives from the server, we can then execute, we get the content of the module as a return to that promise. Back to our original question, code splitting, it's splitting our main bundle in smaller chunks that can be lazy loaded using dynamic imports. Now, let's move on with number two, explain the rehydration process.
Rehydration is basically making server rendered HTML interactive by attaching event listeners to it and rendering the component structure that corresponds to it. But why do we need to do this? Well, that gets us to our first mental model, which is client side rendering. Like any good love story, it starts with a client and a server, the client request a website, the server sends back an index HTML.
In the index HTML, there's a reference to the bundle JS, which gets requested and loaded up in the client. And now the magic starts. We render our application which usually takes quite a while. We basically call render route if this would be react and we basically wait. The problem is while you're waiting, that's how the application looks like. This, also called the white screen of death. It's what your users hate.
And it was popularised by Windows. Now, we are hipsters in 2024 and we use server side rendering. Here things are pretty much the same, but not really. We do have a client and we ask for the HTML, but this time we get a fully rendered HTML, because we render on the server. That takes a bit of time, but it's definitely faster than on a client. We still have to get our bundle after we show something to the user, so they will see the web page, but can't really interact with it. We download our bundle, we parse it, and then we run hydrate root.
And this is where we take the existing server side render HTML and attach it to the component structure we render on the client. On to number three, in which order the following will be printed in the console. You can definitely try to guess this, but it's a lot easier if you know the next mental model that we're going to talk about, which is the event loop. How does it really work? Well, we have a call stack and an event loop that pretty much stays to execute everything in the call stack.
Once that stack is empty, it will go to the microtask queue and try to pick the next thing in the queue. Once the microtask queue is empty, it will actually go to the task queue and pretty much re-render the UI when it finish the work. And keeps doing that until the end of times. Now, how does this apply to the code we've seen before? Well, let me explain. So, we're going to have some synchronous code that will go straight into the call stack and probably will be executed.
Then we have our set timeout. This one does not get executed immediately. It will go to the task queue. And then promise resolve which goes to the microtask queue. Finally, another piece of synchronous code straight into the call stack and executed immediately. And now, our call stack, it's empty. So, let's give you, we got number one executed, then number four. But now, we're going to look for something to do.
There's nothing to do, so we look at the microtask queue and get number three, which is the resolve from our promise. And finally, number four. Not bad. Now, if you want more interview questions, check out the link in the description for the free technical assessment. Let's go on with number explain CSS in JS. Before we get there, we need to understand the real CSS problem. And if you're working with component frameworks like React, imagine we have two components, they both reference the same class and then both add different styles to that class.
Well, if they both declare the CSS class, we'll end up having conflicting CSS properties. And nobody would really know, how would this look like in production? The solution, CSS in JS. Basically, with CSS in JS, we write all our CSS inside JavaScript files. Now, that gets parsed and then finally, the module bundler like webpack will generate a unique class name and add all our CSS to the head of the document, and then finally add that class to the corresponding element.
All done under the hood magically by our module bundler, and this guarantees that there's unique classes for every component and there's no CSS conflict onto number five. What does defer do to a script tag? You can go ahead and try to memorize it, but then there's also sync, and there's also module when it comes to script tags, and good luck memorizing all those. What if I told you you could actually explain all of them with one single mental model, and that is the critical rendering path.
If you Google it, you will find something like this, which, to be honest, doesn't really help much. So, let's actually see it in action, whenever we go into a web page, the browser will fetch that HTML and start parsing it. In parallel, it'll also start parsing our CSS. Pretty much all the CSS we have in the head tag. If there's any synchronous JavaScript, like normal JavaScript tags, it will also try to build those three, to produce the DOM, the document object model, and the CSS form.
Basically, the CSS3 with all our style applied to our components. It will then combine both of those into a render tree. Then, it will go to the layout phase where it figures out the sizes of everything and finally painting it. And this is where the first content will paint happen. So, basically, we can add the defer tag to our script, and that means it will basically get downloaded, but then paused until that first render is done and executed afterwards.
We also have a sync where we download the code and randomly executed whenever we can first in parallel to the render process, and module, which is by default deferred, but you might have different module, so you need to do different downloads and then finally execute it. After the first content with pain. If you want even more interview questions, check out the two videos I link up here. This was Bogdan from the senior dev and this is the end of the transmission.