1. CSS Rendering and Blocking
CSS is rendered synchronously and acts as a blocking resource because it is a global namespace, requiring the browser to interpret all rules before proceeding with HTML.
Watch section from 0:05 →Engineering video
14:05 · 24 September 2024
CSS is rendered synchronously and acts as a blocking resource because it is a global namespace, requiring the browser to interpret all rules before proceeding with HTML.
Watch section from 0:05 →Async scripts download in the background and execute immediately upon completion, whereas defer scripts download in the background and execute after the DOM finish event.
Watch section from 0:44 →CSS performance can be improved by using browser coverage tools to remove unused styles, applying compression and caching, and extracting critical CSS for initial rendering.
Watch section from 1:22 →Closures offer simpler function signatures by providing access to outer scopes, but they can increase memory usage because enclosed variables cannot be garbage collected until the function is no longer used.
Watch section from 2:09 →Synchronous code runs first, followed by microtasks like resolved promises, and then tasks are processed across the event loop ticks.
Watch section from 3:03 →ES6 modules enable static analysis at build time, facilitating optimizations like tree shaking, whereas require resolves modules dynamically at runtime.
Watch section from 4:05 →Hooks must be called at the top level of a component and can only be used inside React components or custom hooks.
Watch section from 5:38 →Concurrent React introduces a priority queue allowing renders to be paused and resumed using fibers, which represent units of work containing component state and props.
Watch section from 6:00 →Rehydration involves taking pre-rendered HTML from the server and attaching the virtual DOM and event handlers via hydrateRoot to make the page interactive.
Watch section from 8:24 →Abusing global state can cause excessive re-renders due to widespread component subscriptions, tightly couple code, and make unit testing harder by requiring mocks.
Watch section from 9:23 →Web application speed can be improved using CDNs, asset compression, HTTP caching, bundle splitting with lazy loading, and image optimization formats like WebP.
Watch section from 10:14 →Code splitting breaks down a large JavaScript bundle into smaller chunks loaded on demand, often mapped to application routes using tools like Webpack and routers.
Watch section from 10:59 →Slow re-renders heavily impact metrics like Interaction to Next Paint by delaying the UI response following a user action.
Watch section from 11:36 →SSR provides strong SEO and better First Contentful Paint performance, but introduces architectural complexity, frontend-backend coupling, and framework lock-in.
Watch section from 12:19 →Building micro frontends involves maintaining visual consistency across independently deployed apps, managing integration complexity, and handling shared state like authentication.
Watch section from 13:20 →Hi folks. So today together with Bogdan, we will answer 30 front end interview questions in 10 minutes. Question number one, is CSS rendered before or after the DOM is constructed in the critical rendering path? CSS is rendered before and it's synchronous. So it all has to be interpreted before we start parsing and showing the DOM. On to question number two, HTML is rendered incrementally as is being interpreted.
Can we say the same about CSS? No. CSS, it's blocking. So it's all or nothing with CSS, and that's because CSS is a global namespace. So the browser developers made a decision to really interpret all the CSS, calculate any possible rule pointing to a specific element before we move with the HTML. Question number three, which one will be interpreted after the HTML is fully rendered? Is it a sync or defer script that will be interpreted first?
It's probably defer. A sync will be interpreted as soon as it was downloaded. So they both start downloading in the background. script, but a sync, as soon as it's downloaded, it will get parsed in the background and interpreted. Randomly time, a defer will actually be done after the DOM finish event. On to question number four, given that box sizing property of an element, it's border box, it's the padding included in the width calculation.
Yes, the padding would be included in the width calculation in the case of border box. On to question number five, tell me three ways I can optimize my CSS to make my web application faster. Number one, you could clean it up with a coverage tool from the browser to really make sure you are shipping only styles that are used. Number two, I would say would be compression and caching, and number three would be critical CSS, basically extracting all the CSS you need for the first render and loading the rest of the CSS after the initial render.
Number six, what will be the final color of the button? This an ID, so it has the highest specificity, so probably this one will be applied. So I would say it's green. On to question number seven, what are the different ways to store data in the browser basic fundamental question. Um, we can probably use cookies, we can probably use local storage, and we can also use session storage. Well, answered, let's move on with number eight.
What is one advantage and one disadvantage of using closures in JavaScript? So, one advantage it's having simpler function signatures because we do not need to pass so many things into a function, because the function has access to the local and global scope. But the disadvantage would be that we use a lot of memory. The reason for that is because functions enclosed so many variables and they cannot be garbage collected until we stop using that function.
So, JavaScript is traditionally a poor language for memory handling. Onto question number nine, a user presses the submit button too often, triggering too many calls to our back end. How can we fix it? So, they are using the submit button, we can do a debounce or a throttle. I think both of them would work because it's a button submission. If this would be an input field and it would be typing, I would say it would be debouncing.
But if it says submit button, probably throttling could also work. Onto question number 10, what is the order of execution? So, this is synchronous, so probably this one would be the first. Set timeout will send this call back to the micro micro task queue, so we have to wait. Promise is resolved to the micro task queue. Script end will execute. So, script starts, script end, then we go to the micro task queue.
Promise call back, then we have the event tick. Finished, and we in the next tick we print timeout. Question number 11, what is the time complexity of the following code? When we're using array sort, I think array sort in JavaScript implements an n log n sorting function. So that would be the complexity of this line. Here, we have a reduce, which has a complexity of n. We're doing bigger notation, the bigger term will be the dominant one.
So we only include that one, which is n log n of n because of the sorting. So, it's n log n of n. Question number 12, why is person also an employee? actual typing. So in TypeScript if two things have the same properties, then they're considered the same. Question number 13. What do ES6 modules allow you to do that require did not. So ES6 modules give you static analysis. That means your your transpiler or your module bundler knows a lot more about your modules, so it can do things like tree shaking, whereas with require, we don't really know much about the modules until we actually execute require and
this will run at runtime. But ES6 modules give you a lot of information already at build time. Number 14, explain this keyword in JavaScript. Okay, so this usually refers to the global uh scope or we call this, you call so you get a window object in the browser. If you're in an event handler, it will refer to the button or the element that was click that triggered the event handler. If you're in a normal function, depending on how it was called or if you're running in strict mode, it points to different things. If it's strict mode, it points to nothing.
If it's a method on an object or a class instance, it will refer to the to the object, you know, the method it's present on. And if you use bind or apply, then it will be uh whatever you bind it or applied it to. And if it's an arrow function, arrow functions usually don't have it sound, so they inherit it. It's either global one or method on an object. Question number 15, describe all the steps in an event loop tick.
So in an event loop tick, we would have to clean everything that's in the stack. So we run the stack all the way down when there's no more synchronous code to execute. Then we check our microtask queue. So this will be things like if in this code we actually resolve the promise, we will also like take the callback of that promise resolved and execute it. And then we would repaint the browser, make sure that the user gets the updates and that's it.
And then we look at the microtask queue, and when we pick something from the microtask queue, the next tick started. Number 16, now we are on with React questions. What are the two rules of hooks in React? Number one rule is that hooks should be at the top of the component. That's the easiest one to remember. And the number two is that uh you should only use hooks inside another hook or inside a React component.
Number 17, tell me one thing you can do with class components that you cannot do with functional components. So the keyword here, it's component life cycle. Life components allows us to hook into the different life cycle methods. So if you want to do things like control if a component should re-render, you could do that with should component re-render or if you can add error boundaries, you can only do that with class components because you have access to the life cycle methods. On to number 18, why can't we use a sync functions as inputs to the use effect hook? The reason for that is probably because the use effect expects a function and whatever that function returns, use effect would run as a clean up function when the component gets unmounted. So if you test something to the scroll event, that's an opportunity for you to move that listener. If you don't do that and the component gets render multiple times, you will end up attaching many the scroll event. So the problem with the sync function is that you turn a promise and the use effect API doesn't really understand that promise as a function. On to number 19, what does concurrent react or a synchronous react means? Concurrent react or sync react is to the new architecture style of react, which was introduced gradually over several releases, but it's stable with react 18. React internally has a priority queue and it can pause and restart re-render processes. So if you have imagine a low priority render, like you're fetching data and render some components, it can be paused to allow a more higher priority update like the user scrolling or the user typing in an input field, so that the interface appears much more responsive. Number 20, what is a fiber in React? So in the new architecture, which is this concurrent React, React will build fibers for your components. A fiber, it's what they call a unit of work, but it actually contains all the code of your component, the props, the state, the current memory state and React will create a tree of those things. And whenever React re-renders, it will actually go through the tree and find the work I need to do. It is this fiber structure that allows React to be able to pause re-renders and move on to higher priority ones. And when it's done with that, come back and start where it left off. Question number 21. Name all the different ways we can
Optimize the re-rendering process in React. Probably number one would be avoiding re-renderings. And you can do that with use memo. Basically, if the props coming in are the same as the props you have, you can skip a re-render. And given that you cannot avoid the re-render, then you can probably use things like use memo and use callback to make sure that if you have anything expensive inside the component, it doesn't get recomputed unless the dependencies of that value are actually changed.
Question number 22. What is rehydration in React, specifically in the SSR? Right, so if we do server side rendering with React, you want to uh you send over the pre-render HTML for the from the backend, but that HTML is not really interactive until you don't attach the virtual DOM to it and all the event handlers. So, the first thing we do usually after we receive that HTML and it gets rendered, is we call the hydrate root method.
We generate the actual uh component tree and the virtual dome and we attach it to the existing HTML. So that's what they call rehydration. On to question number 23. What are three ways sibling components can share state? Okay, so number one, probably the easiest is to lift that state to a parent to a common ancestor, uh to a common parent. Number two, I would say probably putting it into your context, for example, and then connecting both of them to that context.
And then number three, probably using some state library like Redux or flux or any other X state or two stand to actually connect both of them to the same state. Question number 24. Name three disadvantages of global state. Number one, the disadvantage, if you abuse global state, you're going to trigger a lot of re-renders. You have so many components kind of subscribe to the same global state variable.
Number two, you're adding a dependency, so you're coupling your code, it's going to be harder to move components around because they are attached to this global state dependency. And number three, testing will be harder. Because now every time you mock you want to test a specific component, you cannot test this in isolation. You need to mock the value of that global state. Those are the first three that come to my mind.
On to number 25. Can you tell me a disadvantage of using React context? mentation before that, you might have different re-renders if you if you abuse context. You also have this unique, all of a sudden, all the components I connected to context, you need to provide mocks. So let's maintain ability. And yeah, again, you don't want to abuse this, use it as as much as necessary, but as little as possible.
On to number 26, name five techniques, five that I can make I can use to make a front-end application faster. Okay, so number one would be adding a CDN, so you're serving your assets closer to the user. Number two, I would say compression. So compress all your assets like Gzip or or verly if you can. at HTTP level. Number three, caching, all these three things can be done by a CDN. Number four, bundle splitting, so do not to use lazy loading, so don't load all your JavaScript up front, if you can defer, part of it, defer it.
And number five, I would say image optimization, images are usually a big reason why apps are slow. So, uh, when I say image optimization, I would say yes, compression, yes, caching, but also format. So WebP, it's a much better format than any other on the web, if you use WebP, you'll be more efficient in loading. Excellent. On to number 27, what is code splitting and how does it work? So code splitting, it's when you have our bundle, but you know for some reason that you'll not be using all of it, and you decide to load part of it on demand.
Okay, lazy loading. Uh, we can do this with in modern JavaScript because we have Webpack, which has a dependency tree, and for example, you have React router and we together Webpack and the router can work out. What code you need on each route, so if the user goes on the home page, we then need to show them code. from the profile page. So we can basically split our bundle into different chunks and load those chunks as the user needs them, rather than loading everything up front.
On to question number 28, which web core vital would be most affected by slow re-renders? Okay, so we're talking about re-render, which means the ones that are actually measuring the first loading do not apply. So this one doesn't apply, this one doesn't applied. Okay, maybe this one, this is where I have a doubt, so let's leave it on. First content of paint, no, it's not about re-render. Uh the LCP can be, the CLS, it's usually not re-render.
we have the first input delay probably and the interaction to next paint I would say interaction to next paint is probably the most affected. Uh the first input delay can be affected, but if when we think about okay, we are going to component too many times, so it's too expensive, this is probably the time it takes from a user interaction to actually painting the UI again. That's the one. On to question number 29, name three advantages and three disadvantages of using SSR server side rendering, for example, Next.js.
SEO, it's a lot better because we deliver a pre-rendered HTML and the bots, the the search engine bots, they can interpret the page. Uh number two would be performance, we have much better FCP for example, because we show something already to the user. And number three in terms of advantages of SSR, I think SEO and web performance are the main advantages. So I'll lead with those ones. Let me go to the disadvantages and maybe the the advantage comes to my mind.
So three disadvantages would be number one would be complexity, so we need to set it up, it just takes a lot more to do certain things. Number two would be coupling, there is certain coupling between the front end and the back end, things don't live separated anymore, there's so much we need to do together. And number three, I would say it's a lot of framework locking, so if you want to do SSR these days you need to lock into something like Next.js and all of a sudden you need to learn in Next.js specific things, which is always almost a a disadvantage because they've been releasing a new version every six months and you need to adapt.
Moving on to question number 30, what are the top three challenges when building a micro front ends architecture? Okay, so building micro front ends, that means we're going to have like different front ends that deploy independently and then a shell that put them together. I'd say number one, it's maintaining visual consistency, like they all have to share some shared CSS styles. And that's never uh so easy to do.
Number two would be complexity. It takes a lot of sophisticated work to put those things together in the shell and make sure there's no errors. And number three would be shared state. So all of a sudden the shell, for example, has to inject authentication state or user settings in all these different micro front ends. Amazing, challenging, but you made it until the end. If you're interviewing right now, check out the free think assessment to find your gaps and your interview readiness, and we will see you folks in the next one.