INTERVIEW PREP · FRONTEND
30 Frontend Interview Questions for Mid and Senior Developers
We have run over 150 frontend interviews. These are the questions that actually come up — pulled from four interview videos, deduplicated, and answered in full.
Most frontend developers fail interviews on the secondary skills: performance, security, deployment, testing. Not component code. This list is weighted the same way real interviews are.
THE QUESTIONS
Real questions, senior answers
- 02
You are setting up a new frontend application. What performance optimizations do you put in place?
At the bundler level: polyfill modern JavaScript for your target browsers, then apply minification and uglification to shrink the code — and emit source maps, or you cannot debug production. Ship the bundle with gzip compression; that alone cuts the network payload by roughly 70%.
Add code splitting so the initial load only ships the JavaScript it needs — with a router, each route becomes its own chunk — and use ES6 modules so the bundler can tree shake dead code. Past the bundle: a CDN, caching, and image and font optimization. Modern bundlers like Vite do most of this out of the box.
Webpackcode splittingtree shakinggzip - 03
How would you optimize an application with very large images, like an e-commerce store?
Never ship a 3,000-pixel image into an 800-pixel element — resize to the minimum dimensions that still look sharp. Compress, strip metadata, reduce the color space if you can, and prefer WebP over PNG. Serve everything from a CDN, lazy load images below the fold, and set explicit width and height so late images do not cause layout shift. Use srcset to ship smaller variants per device — modern CDNs generate the thumbnails and the snippet for you.
WebPsrcsetlazy loadingCDN - 04
What is critical CSS and how do you extract it?
Critical CSS is the CSS needed to position and style the elements above the fold — what the user sees without scrolling. CSS is a global namespace, so browsers parse and apply all of it before moving on with the HTML; it is render-blocking and all-or-nothing, and a big stylesheet slows the whole first paint. Extract the critical part with a bundler plugin — for example a Webpack plugin that renders the page in Puppeteer at a given width and uses the browser's CSS coverage tool — then inline it and defer the rest.
critical CSSrender-blockingPuppeteer - 05
What do the defer and async attributes do on a script tag, and why use them?
Both download the script in the background instead of blocking HTML parsing. defer executes the script just before DOMContentLoaded, once the HTML is parsed; async executes as soon as the download finishes, whenever that happens. ES6 module scripts are deferred by default in most browsers. The point of both: keep non-critical JavaScript off the critical rendering path so the initial load is faster.
deferasynccritical rendering path - 06
What is the difference between a normal ES6 import and a dynamic import?
A static ES6 import is resolved at build time, so the bundler gets static analysis: tree shaking, TypeScript type inference — things require and CommonJS cannot give you, because require only runs at runtime. A dynamic import behaves like a function, so you can call it inside an if statement or a click handler. That is what enables lazy loading: only fetch lodash — or a whole component — when the user actually triggers the action that needs it.
ES6 modulesdynamic importtree shaking - 07
What is the CLS metric and how do you fix a bad score?
Cumulative Layout Shift is a Core Web Vital measuring how much the layout jumps while the page loads — an image arrives late, pushes everything down, and the user clicks the wrong thing. First find the shifting element with a debugging tool; Chrome's performance insights pinpoint the exact div. Then fix the cause: explicit width and height attributes on images, optimized font loading with a declared fallback height, or critical CSS when styles arrive late.
CLSCore Web Vitalslayout shift - 08
How does a CDN work, and why would you use one?
A CDN is a network of servers that replicates your static assets — HTML, JavaScript, CSS — across edge locations around the world. A latency-based DNS lookup routes each user to the closest edge, so nobody waits on a round trip to your origin server. It is easy to set up and a must-have for almost any frontend; CloudFront and Cloudflare both do the job.
CDNCloudFrontedge locations - 09
How would you deploy a frontend application?
Client-side only means a static deployment: upload the build to blob storage like S3 and put CloudFront — or any CDN — in front, so users hit the nearest edge location. That setup scales through traffic spikes without you doing anything.
SSR changes the picture: you need compute. Containers on Fargate, EC2 instances behind a load balancer, or a platform like Vercel that distributes the compute for you. Static assets still go through the CDN either way. Be careful with Lambda for e-commerce SSR — cold start times hurt.
S3CloudFrontSSRdeployment - 10
What tools and metrics would you use to monitor a frontend application?
Three layers. Error tracking with Sentry: stack traces, device and OS context, and alerting so whoever is on call can reproduce the exception. Core Web Vitals from real users — first contentful paint, Speed Index, CLS — to know the loading speed people actually experience, plus server metrics (CPU, memory, response times) if you render server-side. Finally product analytics like Google Analytics — not the best tool, but the industry standard and easy to implement.
SentryCore Web Vitalsmonitoring - 11
How do you manage code quality in a large-scale frontend application?
Start with a linter plus Prettier so everyone writes in the same style and small issues die in the editor — add TypeScript linting and an a11y rule set for accessibility. Layer on unit tests, some E2E tests, and a dependency scan, because node_modules is a real attack surface. Then wire Lighthouse or Sentry into the pipeline so a fat image or new font shows up as a Core Web Vitals regression before it ships.
ESLintPrettierE2E testingLighthouse - 12
What is an XSS attack and how do you prevent it?
In cross-site scripting, an attacker persists JavaScript into your database — as a comment, say — and every user who loads that content executes it; the script can silently POST their credentials to the attacker. Defense one: sanitize input so script never reaches the database. Defense two: never render raw HTML or JS received over the network — in React, that means avoiding dangerouslySetInnerHTML at all cost.
XSSinput sanitizationsecurity - 13
What are JSON Web Tokens and how are they used for authentication?
A JWT is the credential a client attaches to requests — usually in the Authorization header — to prove who it is. The flow: the client redirects the user to an identity server, the user authenticates with credentials or multi-factor auth, the client gets a token back, and the backend verifies that token against the identity server before returning protected resources. The frontend JavaScript itself should ideally never touch the token.
JWTauthenticationidentity server - 14
Where should you store a JWT in the browser?
In an HTTP-only cookie. sessionStorage clears when the browser closes, forcing constant re-authentication. localStorage is readable by JavaScript, so any injected script — an XSS payload, a malicious Chrome extension — can steal the token and act on behalf of the user. HTTP-only cookies are invisible to frontend code but ride along automatically on every request, so the backend can still identify the user.
JWTHTTP-only cookieXSS - 15
What are ARIA attributes and when are they useful?
Default to semantic HTML — header, footer, nav — because accessibility tools understand those tags natively. ARIA attributes exist for the edge cases where design constraints or a custom widget force you onto a div or span: they assign an accessibility role to a non-semantic element. Use them when you cannot use semantic tags, not instead of them.
ARIAsemantic HTMLaccessibility - 16
What is the shadow DOM and when would you use it?
The shadow DOM is an isolated subtree of the DOM: styles inside cannot leak out, global styles cannot leak in, and it does not inherit native browser styles — so a dropdown looks identical in Chrome and Safari. That isolation is worth it when you ship a component library or open-source widget that must not conflict with the host application.
For a normal product app it is over-engineering: more complexity, worse performance, no polyfill for older browsers. For CSS conflicts — including across micro frontends — CSS Modules or CSS-in-JS solve the problem far more cheaply by hashing class names per file path.
shadow DOMCSS Modulesencapsulation - 17
Walk me through one tick of the event loop. What runs first: synchronous code, promises, or setTimeout?
Run the call stack dry first — all synchronous code. Then drain the microtask queue: resolved promise callbacks execute here, before anything else. Then the browser repaints so the user sees the updates, and only on the next tick does it pick a macrotask like a setTimeout callback. That is why a setTimeout with delay 0 still logs after 'script end' and after every promise callback.
event loopmicrotask queuesetTimeout - 18
What is one advantage and one disadvantage of closures in JavaScript?
Advantage: simpler function signatures — a closure reads variables from its enclosing scope, so you do not have to pass everything in as parameters. Disadvantage: memory. Enclosed variables cannot be garbage collected while the function lives, and JavaScript is traditionally a poor language for memory handling anyway.
closuresscopegarbage collection - 19
A user presses the submit button too often, triggering too many backend calls. How do you fix it?
Throttle the handler so it fires at most once per interval — the right call for a submit button. For a text input firing on every keystroke, debounce instead: wait until the user stops typing before hitting the backend.
throttledebounce - 20
What is the difference between essential state and derived state?
Essential state changes independently — it comes from user interaction or data fetching, and nothing else can reproduce it. Derived state is anything you can compute from other state. On a checkout page: the items in the cart are essential; the item count, net price and price with tax are all derived. Compute derived values — do not store them.
state managementderived state - 21
What are the two rules of hooks in React?
One: call hooks at the top of the component, never inside conditions or loops. Two: only call a hook from a React function component or from another hook.
Reacthooks - 22
What can class components do that functional components cannot?
The keyword is lifecycle methods. Class components can hook into shouldComponentUpdate to control whether a component re-renders, and they are the only way to implement error boundaries — both need lifecycle access that function components do not expose.
Reactclass componentserror boundaries - 23
Why can't you pass an async function directly to useEffect?
useEffect treats the function's return value as the cleanup that runs on unmount — where you remove the scroll listener you attached, or every re-render stacks another listener. An async function returns a promise, and the useEffect API does not understand a promise as a cleanup function.
ReactuseEffectcleanup - 24
What is concurrent React, and what is a fiber?
Concurrent React — stable since React 18 — gives React an internal priority queue: it can pause a low-priority render, like painting freshly fetched data, to handle a high-priority update like the user typing or scrolling, so the interface stays responsive. A fiber is the unit of work that makes this possible: a node holding a component's code, props and current state. React walks the fiber tree on each render and can pause mid-tree, handle the urgent work, and resume exactly where it left off.
concurrent ReactfiberReact 18 - 25
How do you optimize the re-rendering process in React?
First avoid the render entirely: memoize the component so a re-render is skipped when the incoming props are unchanged. When a render must happen, useMemo and useCallback keep expensive values and functions from being recomputed unless their dependencies change. Slow renders show up in your metrics as bad INP — interaction to next paint, the Core Web Vital most affected by expensive re-rendering.
ReactuseMemouseCallbackINP - 27
What are the disadvantages of global state and of React context?
Abused global state triggers re-renders across every subscribed component. It also couples your code: components carry a hidden dependency, so they are harder to move and harder to test — every test now has to mock the store. React context has the same failure mode: suddenly everything is connected to it and needs providers mocked, so use it as much as necessary and as little as possible.
global stateReact contextcoupling - 28
In server-side rendering, what is hydration?
The server sends fully rendered HTML, so the user sees the page — but nothing is interactive until the framework attaches the virtual DOM and event handlers to that markup. That attach step is hydration; in React it starts with hydrateRoot. Until it finishes, clicks do nothing — that is the click-rage window. Avoid mismatch warnings by rendering identical HTML on both sides: no timestamps or generated values in server markup — produce those client-side, in a useEffect.
SSRhydrationvirtual DOM - 29
Name three advantages and three disadvantages of server-side rendering.
Advantages: much better SEO, because search bots get pre-rendered HTML; better web performance — the FCP improves since users see content immediately. Disadvantages: setup complexity, coupling between frontend and backend, and framework lock-in — SSR today mostly means committing to something like Next.js, which ships breaking changes fast. Deployment also gets heavier: you need compute, not just static hosting.
SSRSEONext.js - 30
What are micro frontends and when do they make sense?
Micro frontends split one frontend monolith into independently deployed applications — header, product page, checkout — composed by a shell that owns authentication and shared state. They solve an organizational problem, not a technical one: past roughly 30 frontend engineers, teams block each other in one deploy pipeline, and splitting lets them ship in parallel.
The price is real: visual consistency across apps, state shared through the shell, and heavy tooling complexity — you are distributing a system. Most companies adopt them too early. Do not, until the deployment pipeline is actually the bottleneck.
micro frontendsarchitecturedeployment

Free Senior Training.
One session, the whole system: the fundamentals, the interview strategy, and the plan to the offer. Watch it free.
MORE GUIDES


