Video guide
25:53 · 27 March 2024
Senior Frontend Developer Interview Questions & Answers
Chapters 6 sections
Interview questions in this video:
- 01
1. What is Webpack used for?
It's a module bundler: it parses your imports and exports, builds a dependency graph from your entry point, and combines hundreds of files into deployable bundles.
The alternative — a script tag per file — stopped being practical the moment applications grew past a handful of modules.
Module bundlersDependency graph - 02
2. What is tree shaking, and when does it NOT work?
Dead-code elimination at bundle time: the bundler drops modules — and parts of modules — that nothing imports. Default since Webpack 5.
The catch: it only works with static ES module imports. CommonJS require() calls are dynamic, evaluated at runtime, so the bundler can't prove what's unused. One CJS dependency and that subtree ships whole.
Dead code eliminationESM vs CommonJS - 03
3. What are the trade-offs of CSS-in-JS?
The win: dynamic styles driven by JavaScript state, and generated class names that end specificity conflicts.
The costs: your CSS rides inside the JS bundle, so it can't be cached separately and gets parsed late — hello cumulative layout shift. Debugging hashed class names is worse. And in React, every styled element is another component in an already deep tree.
Mitigation: extract the styles at build time and serve them from the CDN like ordinary CSS.
styled-componentsCachingCLS - 04
4. What is an error boundary component?
A component that localizes failures: when a child throws — say a data fetch renders bad state — the boundary catches it and renders a fallback instead of letting the whole tree unmount.
One broken widget shouldn't take down the page. Boundaries make the blast radius a design decision.
Error handlingFault isolation - 05
5. Why can't you pass an async function directly to useEffect?
Because useEffect's return value must be the cleanup function — the thing that removes event handlers so re-renders don't stack them up.
An async function always returns a promise, and React doesn't know what to do with a promise where a cleanup function belongs. Define the async function inside the effect and call it.
useEffectCleanup functions - 06
6. An app has fetched data, auth state, and global user settings with complex transitions. How do you organize state?
Three different homes. Fetched data stays in component state, lifted only when siblings need it. Auth goes in context — it's genuinely global, everything checks roles and permissions.
Settings with non-trivial transitions want the reducer pattern — useReducer with context, or a small store — because complex state transitions need one deterministic, testable transition function.
State placementContextReducer pattern - 07
7. What's the difference between essential and derived state?
Essential state changes on its own — the items in a cart. Derived state can be computed from it — the subtotal, the VAT.
Keep only essential state in your hooks and compute the rest. Every redundant state variable is a future sync bug.
Essential stateDerived values - 08
8. What are the drawbacks of putting state in React context?
Every consumer re-renders whenever the context value changes. Lift independent state into one context and you've coupled unrelated components' render cycles.
Split contexts by change pattern, and keep state as close to where it's used as possible. Context is a broadcast tool, not a default store.
Context re-rendersState locality - 09
9. You inherit a React app with zero tests. How do you approach testing it?
End-to-end tests first: they cover features, and they survive refactors because they don't care how the code is shaped. Then unit tests on reusable components with real logic — not on whether an image renders.
Integration tests go on the critical paths: login, payments. The balance matters because e2e failures tell you something broke; unit tests tell you where.
Testing pyramidE2E first - 10
10. What is code coverage, and how much is appropriate on the frontend?
The percentage of code that executes while tests run — not the percentage that's meaningfully verified.
On the frontend, 60-70% is the honest target: below 60 the suite isn't trustworthy, above 80-90 you're writing tests for the metric. Mandated 95% produces test theater — we've watched it happen.
Coverage targetsTest quality - 11
11. What causes a bad First Contentful Paint, and how do you fix it?
The usual suspects: a huge client-rendered JS bundle, no CDN (uncompressed, uncached assets), and a pile of render-blocking CSS.
Triage in order of leverage: CDN with caching and compression first. Then audit the bundle and drop dead weight. Then code-split by route — with the product manager, pick the pages that must be fast — and lazy-load the rest.
FCPCDNCode splitting - 12
12. When would you introduce server-side rendering — and when not?
SSR pays off when the product is sensitive to loading speed or SEO: e-commerce, media. The user gets real HTML instantly.
For a SaaS dashboard behind a login, it's complexity without payoff — client-side rendering is fine. Teams that rushed to SSR have rolled it back; treat it as a product decision, not a default.
SSR trade-offsSEOProduct thinking
Transcript
Hi folks, Drago here from the senior dev. And uh today, together with Bogdan, we're gonna go to a bunch of senior front-end interview questions. These are real interview questions that we've got ourselves in senior front-end interviews, but also our mentee. Uh number one, we're gonna start talking about tooling. Right? And the first question is, can you tell me about your experience using webpack? What is it used for? Uh webpack, it's a module bundler. So we basically use it to uh put several JavaScript files into a single one that used to be necessary because in the browser, um you basically, in order to add JavaScript, you need to place a script tag for every JavaScript file you have, and when you have a big application with hundreds of files, that's just not practical, so bundle um webpack will uh will kind of bundle all that, it will parse all of them, and based on your imports and exports, and put them all together into a single bundle, and then we can apply different optimizations. Um I worked a lot with webpack in the past, basically setting up projects from scratch and doing all kinds of configurations, yeah. Nice, Bogdan. Are you familiar? Talking about webpack and module bundlers, are you familiar with the term tree shaking? Tree shaking as in webpack, it's basically what webpack will do when we ship our bundle to production, and it will basically try to find dead code, those are modules that maybe we imported in our code, but we're not really using or parts of modules, and it will basically try to eliminate them, so our bundle it's as small as possible and we get the best web performance. Amazing. Have you used um tree shaking professionally in production uh at any stage? Can you give me an example of that? Uh yes, as far as I know, in version 5, it comes by default, so every time we use webpack, it will try to tree-shake our code. One thing you want to be aware of is that it only works with ES6 static imports. So if you have any any module in your dependencies, or you're using commonjs imports with require, then webpack cannot really uh tree-shake that. So you got
to be careful because yes, Webpack ships with it by default, but if we don't use those kind of modules, then it's not capable of really understanding if it should remove that code or it's not being used. Which modules were? Uh so ES6 static imports, are the ones that do uh allow Webpack to do tree shaking. And common JS, you know the old uh require notation, those ones cannot be tree shaked because they are dynamic and they are evaluated at runtime.
So there they are basically functions and Webpack cannot really use them to build this dependency tree and figure out, okay, what's going on in there? Can I drop any of that code until it gets executed in the browser? Excellent, seems like you know quite a bit about Webpack. Now, um what is talking still talking about Webpack and and tooling and module bundlers? Um you know, what is a dependency graph and what is it used for in Webpack?
Uh the dependency graph in in Webpack, it's basically what Webpack builds from our entry point, so it will basically take our first file and then figure out and go down all those import statements we have at the top. And from that it will keep going down until it reaches basically the end and that's basically a tree structure that it forms. And that's how it's uh stores basically all our modules. And then it's using that to uh traverse it, to go through it and find out if there's any modules we need to drop or which ones are in production.
So it's the kind of the main abstraction in Webpack and it will always be used to put, you know, to go from individual files to a single bundle. Cool, now we're going to move on with a question about CSS and JS. Basically, can you explain what CSS and JS is and can you give me an example, you know, what are um what are some use cases for CSS and JS? Uh, yeah, sure. So CSS in JS appeared because we're writing all this JavaScript and we have a lot we have a lot of interactivity.
And we basically want um to change CSS styles when a certain state or a certain variable changes. And CSS in JS allowed us to, um, to basically have dynamic CSS. Where you click a button and some CSS changes immediately. Um, you could do that with classes, like you would assign a different class to an element, but it's just a lot easier if you could just swap colors or directly do things with JavaScript variables inside CSS.
That's using that was not possible before because you had static CSS files. Uh and with CSS in JS we write our CSS inside JavaScript files. And then Webpack will basically somehow extract that and build different classes and attach them to attach them to, um, to the, um, to the JavaScript, uh, to the HTML DOM. But runtime, but we didn't need to worry about that. So, it basically allows you to write your CSS in JavaScript and leverage a lot of dynamic, uh, dynamic styles.
So, you have the dynamic language like JavaScript, but you can do styling with it. Awesome, so you already mentioned some of the advantages, right, of have of having JavaScript control, um, variables inside your styling. But what are some disadvantages of using CSS in JS? Uh, well, one of the main disadvantages is that because your styles are now in Java in JavaScript files, you cannot really extract them and do certain optimizations you can do to CSS.
Um, and one of the thing is you cannot really cache your CSS files. So, if your CSS didn't change back in the days, you could have the user, uh, storing that on their browser side because you attach a cache policy with HTTP headers to it, like cache control, and they would store that, and in a subsequent visit, they wouldn't have to download all your CSS. But now, all that CSS, it's inside our, uh, JavaScript file.
JavaScript bundle, it's all together, which makes our bundle bigger, um, it's a bit harder to parse, but it's also non-cacheable. Uh, you can actually counter fact that by extracting, uh, with Webpack, your CSS at runtime, um, and ship it separately. Uh, but it's still not as easy as it used to be when you had your CSS separated from from your JavaScript. Understood. It's also harder to debug your CSS uh because again, those classes that Webpack generates, they're unique hashes and all of a sudden, it's not as easy as it used to be to understand why a certain element looks a certain way. There is some tooling, right, that um CSS in JS usually brings on to make that debugging easier. Um one thing you we haven't chatted about it's the the performance, um how how how does it affect? How does CSS in JS affect performance? So that's uh one of the main things is because you cannot cache your CSS, you're loading it and it will decrease um the performance. And um yeah, it will also you might also have a lot of uh cumulative layer shift because your CSS gets now applied when uh when the JavaScript bundle gets parsed. So, um in the critical rendering path, we usually evaluate CSS first and we apply it and that ensures the fact that there's no flash when you load the page. But now because we evaluate the CSS at the end, you might have cumulative layout shift when the user loads the page. Things might move around and you got to be careful uh and sometimes split your CSS and ship CSS in JS for the dynamic parts and then still use plain old CSS for most of your grid elements. So you have a stable page. And the other thing is because we are creating new components, for example, I use style components in React, every time we style a heading or a native React element, we end up creating another component. And in a big component tree that will create a huge component layer, uh which it's always uh a huge component tree, a very deep component tree, which is always a disadvantage because it makes debugging harder and of course a bigger component tree, it's also harder for React to re render all the time even if React is very effective, you want to keep it as small as possible. Awesome. Then we're going to move on to the next question um and we will talk about JavaScript
frameworks specifically React. Have you worked with React in production so far? Uh yes, I've worked with React for the last uh pretty much since 2015. So that would be around pretty much since it came out, yeah. Awesome. Then you're probably going to fly to these questions. Uh first question is, you know, what is a pure component in React? Uh pure component in React. Well, I think so pure components used to be uh when we had class components and you wanted to avoid re renders, you use one of those because it would compare the incoming props with the existing props and if they were the same, it would skip the render.
Um you probably don't need it today because we use hooks and hooks are by default memoized, so whenever you do a whenever you do a set state, um React already checks if you are updating the state to the same value, and if that's still it does not regenerate the component. So it kind of comes by default, but back with class components we had to use pure components. Cool. Um another another type of component uh question, it's what is an error boundary component? You know, what is it used for? Why do we have error boundaries components in React?
Uh yeah, sure. So, basically error boundaries um help you limit the impact of an error. So, if you have a data fetching error in some component, you can wrap it with an error boundary and that will uh at some level uh localize the error. So, it doesn't go up the component tree and you don't show the whole thing, the whole application broken. What you can actually show a placeholder for that one component that um something went wrong.
Uh so, it allows you to localize and have a much better predictable UI, and also have no layout shift when you have these errors. They can totally destroy the UI if they're unmanaged. Awesome. Very well. Um now, still talking about React, in this case, we will focus on React hooks. And the hook that we are talking about, it's with the use effect hook. Tell me more about how is it used um you know what would be some advantages and disadvantages of using use effect?
Uh yeah sure. So we basically use effects to uh trigger a what they call a side effect in React. That would mean uh when a state variable changes maybe imagine we want to do something else like we want to make a call to our analytic system and to tell something changed. or write into local storage for example, that would be an ideal case for effect. Um I know when they came out um myself including and all the community kind of abused effects and we're using them for everything.
So we would use effects to change a different when one state variable change we would use effects to change a different uh variable. But the thing with effects is that they uh they run after the component re-render and they trigger another re-render. So if you're not careful and you abuse them, you end up having so many re-renders in your component. And of course, re-renders of parent uh will cause re-render of a child component.
So that will really it can end up affecting your application if you're abusing them um performance wise. Second question about use effect hook it's why can't we use an a sync function as a callback to use effect? Well, probably because in a sync function returns by default a promise. And the return of the use effect hook should always be a clean up function. That allows us to if we for example in the effect attach something to the uh on scroll effect to remove that handler.
Because if we don't remove it and we end up rendering, we keep attaching handlers to that event and we might blow the browser. So React allows you to return that clean up function, but when you use a sync, you're always returning a promise. And React doesn't know what to do with that promise because it's not it's it expects a function. So that's why uh you get this linter error writing most of the times that tells you, hey, you cannot uh you cannot use an uh an sync function here. Yeah.
So. So, then, make sense. We are going to move on with a question about state. Okay? And I want you to imagine that we have a simple front end application with the following state. Okay, number one, we will be fetching some data from the back end. Right, then we perform some user authentication and um set some general user settings. That will affect those those um user settings will affect the whole application. And my question is, you know, when we have to deal with such requirements on the client side, what would be the best solution to handle state management in this application and why? Uh, sure. Okay, so we have back end, we have data we get from the back end, we have authentication state that you mentioned. and some global settings, right? Yes. Um, okay. So I'll probably place those differently because of the requirements on them. Uh, so usually, uh, from my experience, data that comes from the back end can stay in component state, unless it's needed by two or three components where you could usually just um, lift it up and you'll have a bit of prop drilling, but it should be manageable with that kind of data. Um, when you have authentication state, you usually want that to be globally available to any component, because some components might need it to see the user roles and permissions. That's why I'll probably use something like React context because it's very useful to broadcast uh the state to the whole component tree. And for the settings, um, it looks like there might be some non-trivial state transitions in the settings, usually, if you have maybe complex transitions like a user can be premium or not and that will change many different settings across the app, or at least that's what I worked with in the past. Uh, in that case, you might look at the state machine or you might need a reducer pattern. You can, of course, use something like Redux for that or a smaller, like a zustand library. But you do need a reducer pattern.
state transitions, um, you can use, use get user with context, that also works. Uh, so that's how I would, uh, that's how I would distribute state these three different ways. Cool. Um, now still sticking with state. Um, one question about essential and derived state specifically. Could you explain the difference between essential and derived state? Uh, the difference between essential and derived state, uh, so basically essential state would be state that, um, changes by itself, changes independently, and you cannot use it any further. And derived state, it's state you could calculate based on the essential state. So, just to give an example, if you had a component that displays like a breakdown of a shopping cart, all the different items that you have there, they're probably essential state, but the total and the VAT amount, they are derived state. Because you can compute that based on all the other items. So, that would be an example and usually you want to keep as little state as possible, so you want to have only the essential state in you state hooks in react. Amazing. Cool. Um, now, final question about state and in react, uh, you know, what would be the disadvantages of placing state inside React context? I'd say number one is that if you lift state so far up, anytime that state changes, every component that will be connected to that, uh, context, will also change. So, if you have state that really changes independently and it's consumed by different components, you could also split it into two different react contexts, two different providers, because the components that will subscribe to those will be different. You'll have overall less re-renders. Uh, so that's one of the biggest problems, when you lift state in general, but especially when you lift it to context, it will end up causing re-renders. And as a general rule, I try to keep state or we should all try to keep state as close to where it's being used. Yeah. Amazing.
project. And um, yeah, we have a bunch of questions, two more, two more categories I will be asking you about. Uh, we're going to start with testing, right? And uh specifically, you know, how would you go about testing a React application? Yeah, uh what, you know, if any let's think about a mid-sized application, not too big, not too small. Uh there are no tests, let's say the development team was pretty crazy. They've written no tests, they just you know, usually happens. We've seen that in companies, but they stick together a bunch of components, uh there's data fetching, there's authentication, there's all uh all the kind of functionalities that you find on a client-side application built with React.
How would you go, you know, you're hired to um bring that up to to implement some best practices in that one, specifically testing. How would you go about testing this kind of application? Uh okay, so we have a React application that haven't been tested. Um, I would probably inspect the code base and try to decide, you know, we want to do unit start with unit test or uh integration test or end-to-end test, which is the typical testing pyramid. Um, I would probably in my experience in the front end, one of the best tests to have are end-to-end tests because you test the features, which is very clear and then it allows you to refactor your code behind it without changing the tests.
Um, and if we have any components that we're reusing, like imagine we might have input fields that are being reused or buttons or any kind of component that has ideally some logic and is being reused, like a drop down. Uh in that case, I would write some unit test on them. Uh I'm not a fan of unit testing everything just because in React, uh you didn't get a lot of value for testing pure components, like just if an image renders, uh we could do that. Some people do that in order to hit the code coverage.
Uh, but I would say having some good end-to-end test, having unit tests on reusable components, integration test in the front end. Ah, that's a very very good question. Um, I would say you need to understand if we write a lot of end-to-end tests, but we have imagine no unit test and integration test. What will happen is that when your end-to-end test fail, fails, it's good you know that there is a bug, but it will be extremely hard to go to the code and find exactly where it is.
So the more unit and integration test you have, the easier it is when you find a bug to localize the when you make a root cause analysis to localize the bug boundary and really eliminate all the other sides of the application. If you only write end-to-end tests, uh you will have coverage for your features, but when something breaks, it will still take you hours to debug. So I would say, uh I would be smart about it and understand your application and then have a have a certain balance.
I cannot give you exact numbers, but I would write a lot of unit tests and a lot of end-to-end test to finish the to cover the features and strategically some integration test on on the critical features like if you have login, or if you have payments, you got to see also like what's more critical in your product. Uh you did mentioned the word code coverage when you were talking about unit testing, um, you know, can you tell me more about code coverage?
Like just shortly what it is, and um what would be the appropriate amount of code coverage in your opinion in a frontend application? Uh, so yeah, code coverage, it's the amount of code that executes when we run the test, basically. So people say it's the amount of code we cover in we covered with tests, but it's actually the amount of code that actually executes when you run the test. Um, in the front end I would say it's a bit more tricky than in the back end where it's a bit easier.
But I would try to keep it all the way up to 60% whenever possible. If you go under 60, then it will be quite unpredictable and the tests are unusable because you can't really trust. Um, there's a lot of code that's not tested, so the test might fail, but you don't really know, why do I failing? 60 to 70% would be good. I think going over 80 to 90, it's a bit of an over kill and you don't get a lot of value from just marginal test. Um, in your last team or company, you know, what was the code coverage you were aiming for and you know, did you had any anecdotes, anything that you can tell us how did it went for you? Um, yeah, sure. So at least, in some of my roles, I worked in a finance industry where they they may it was a general rule for the company to have around 95% of code coverage. Uh, we ended up writing a lot of tests that made literally no sense. Um, you you have a lot of files that sometimes are just explicitly they declare types, you had to exclude all those and it was pretty much of a hard measure. Everybody was saying they do TDD, but in the end everybody got test before pushing their PR. Um, so I would be really careful with these measures because in the end uh people say they would do it and so on, but uh, but yeah, I had that experience also been in teams that didn't wrote any test at all to be very honest. That was uh chaos, that was a disaster. and I would say the perfect balance is in the front end 60 to 70, in the back end I would go a bit more up. 90 to 80, 80 to 90, 95, uh it's still doable because the back end again it's it's a bit more functional and it's sometimes much easier to unit test or to modularize things than it is in the front end. Cool. Now, um let's talk finally, final uh final category we will talk about web performance, right? Um and uh the question here is, can you explain the FCP? Okay, what are the causes of a bad FCP score? Okay, so FCP FCP would be the first contentful paint, uh which is basically the time it takes since the user hits the uh the enter button in the browser to display something and to display anything to them. Um and usually, it's really bad if you ship a lot of JavaScript that is client side rendered, so it takes a lot of time to parse all this react bundle
and interpret it for the browser to show something, or you don't use a CDN, so maybe the assets are not compressed or they're not cached. And so it it literally just takes a lot of time to to do that. Or you have a lot of CSS. Uh CSS CSS in the header uh has to be all interpreted before we move on to JavaScript and finally start incrementally rendering the HTML. Um, so if you have a lot of that, it will also take a long time. So, these are three causes that I've seen in the past. That's the first thing I would look at. Let's suppose you take charge of a front-end application, you run your um analysis, uh whatever tool you're use like House, for example, and you realize that the FCP, it has a very low FCP score. How would you go about fixing it? Uh, so okay, so we saw that the FCP is low on lighthouse. I would definitely run a couple of analysis just to make sure the score is legit. And once we have that, uh I probably, as I mentioned, look first into the CDN, it's usually the easiest thing to do and gets a lot of benefits if there is not one set. Um, and then probably I would uh use something to inspect the bundle and see if we can remove any part of the JavaScript that's not being used. And if that doesn't still work, I would look into code splitting and really only load the JavaScript that you need for a specific page. I'll probably talk to the product managers and see which are the pages that are more critical for us to to load fast. Usually, it's not all the pages, and I would focus on those ones in code split to make sure that uh we really load as little JavaScript as possible, and maybe defer some some of the JavaScript or async load it. Uh you can do that with webpack, uh with react.lazy also. You can split your component tree. Uh so basically code splitting would be one of the biggest um things I would do after we add the CDN and we make sure we have caching and compression in place. So, number one CDN, caching compression, number two, remove uh whatever libraries that you can remove that are
getting way too much JavaScript to the bundle. Uh number three, code splitting and and shipping different chunks of JavaScript as you need them, right, to make that lower. Have you considered and when do you consider something like server side rendering? Let's suppose this is a react client side um client side rendered application and you've went to all the optimizations and still because of the size of the application.
The application is too big and the FCP it's way too slow. Um, server side rendering went on well, it will definitely improve uh by basically removing, by basically, yeah, showing instantly, we ship the render HTML to the client so they will get something immediately, they'll see something. Uh, it does add, however, complexity to your code base. So, I know some use cases where people rushed into server side rendering and then they had to roll it back.
I would definitely look at our product, and if the product is very sensitive to loading speed or sensitive to SEO, then you'll get a lot of benefits from server side rendering. But if it's not, if it's like a SAS application where it's like accounting software, then there's usually no value in server side rendering. So you would stick to CSR still because it's not. Yes. Yeah. Probably an e-commerce in something like e-commerce or the media where you have a newspaper, they want to load very fast and they're very sensitive to SEO.
They're probably most of them using server side rendering. Awesome. This was it for today. We uh covered a lot of topics from CSS and JS to React, React hooks, to Web pack, to tooling, to testing, and now on to performance. I hope you um folks enjoyed this. We um we're going to publish some more serious on this. Thank you for this one and we will see you in the next one. See you in the next one.