Volume 1

Q014: Script Loading: async, defer, module, preload and preconnect

Difficulty: SeniorFrequency: Very HighAnswer time: 6-10 minutes

What Interviewers Want To Evaluate

This question tests whether you understand how scripts are discovered, downloaded, parsed, and executed by the browser. Interviewers want to hear how classic scripts, async, defer, module scripts, preload, modulepreload, preconnect, and resource priority affect rendering and interactivity.

For senior roles, the important signal is production judgment. Script loading is where architecture, performance, analytics, third-party tags, hydration, and user experience collide.

Short Interview Answer

Classic scripts without async or defer block HTML parsing while they download and execute. defer downloads scripts without blocking parsing and executes them after HTML parsing, in document order, before DOMContentLoaded. async downloads without blocking parsing but executes as soon as it is ready, which can interrupt parsing and does not preserve order. Module scripts are deferred by default and use the module graph. preload and modulepreload help the browser discover important resources earlier. preconnect warms up connections to important origins. The goal is to keep critical rendering and interaction code prioritized while moving noncritical scripts out of the initial path.

Detailed Interview Answer

When the HTML parser reaches a normal <script src="...">, it usually pauses parsing, fetches the script if needed, executes it, and then continues. This behavior exists because the script can modify the document while parsing is in progress.

defer changes the timing. Deferred scripts are fetched while parsing continues, then executed after the document has been parsed. Their execution order follows document order. This is useful for application scripts that need the DOM to exist but do not need to block parsing.

async is different. Async scripts are fetched while parsing continues, but they execute as soon as they are available. That means they can run before or after other scripts and can interrupt parsing. This is useful for independent scripts, such as analytics, but risky for scripts with ordering dependencies.

Deep Technical Explanation

Script loading affects both discovery and execution.

classic script
  -> blocks parser
defer script
  -> download during parse, execute after parse in order
async script
  -> download during parse, execute when ready
module script
  -> deferred by default, resolves dependency graph

The browser also uses resource hints. preload tells the browser that a resource is needed soon. modulepreload is designed for module graphs. preconnect starts DNS, TCP, and TLS work early for an origin.

Internal Working

The HTML parser and preload scanner discover scripts. The network scheduler prioritizes requests based on type, hints, location, and browser heuristics. The JavaScript engine then parses, compiles, and executes the script. Module scripts also require fetching and linking dependencies before evaluation.

Execution matters as much as download. A script can be cached and still expensive if it takes a long time to parse and execute on a low-end device.

Architecture Discussion

In a Next.js or React app, script loading strategy affects hydration and route startup. The main bundle, route chunks, analytics, experiments, widgets, and third-party scripts should not all compete equally. Critical application code deserves priority. Noncritical third-party code should be delayed, isolated, or loaded after interaction when possible.

Good architecture defines script classes: critical app runtime, route code, above-the-fold interaction code, analytics, experiments, support widgets, and background utilities.

Trade-Offs

defer is predictable but still executes before DOMContentLoaded. async is fast for independent scripts but unsafe for ordered dependencies. preload can improve discovery but can hurt performance if overused. preconnect helps cross-origin latency but wastes work if the origin is not used. Deferring third-party scripts improves page load but can delay analytics or personalization.

Common Mistakes

A common mistake is using async for scripts that depend on each other. Another is preloading too many resources and accidentally competing with CSS, fonts, or the LCP image. Another is assuming download size is the only cost and ignoring parse and execution time.

Real Production Story

A page may have poor INP because third-party scripts execute during initial interaction. The network waterfall looks acceptable, but the performance trace shows long scripting tasks from analytics, experimentation, and tag managers.

The fix may be to delay noncritical scripts, remove unused tags, use consent-aware loading, split experiments server-side, or load support widgets only when opened.

Enterprise Example

In an enterprise SaaS dashboard, customer-specific analytics, feature flags, SSO helpers, and chat widgets can pile onto startup. A mature platform treats scripts as owned dependencies with budgets, loading policies, and review requirements.

Code Example

<script src="/app-shell.js" defer></script>
<script src="/analytics.js" async></script>
<link rel="modulepreload" href="/assets/dashboard.js" />
<link rel="preconnect" href="https://cdn.example.com" />

This communicates intent: app code should execute predictably after parsing, analytics is independent, a module chunk is important soon, and the CDN connection can be warmed early.

Performance Discussion

Measure both network and main-thread cost. Look for parser-blocking scripts, late-discovered chunks, unused JavaScript, third-party long tasks, and scripts that execute before the page becomes useful. Script strategy affects FCP, LCP, TTI-like readiness, and INP.

Security Considerations

Third-party scripts execute with high privilege in the page context. Use CSP, Subresource Integrity when appropriate, strict vendor review, and avoid unnecessary third-party code. Loading a script is a security decision, not only a performance decision.

Scalability Discussion

As teams add features, script creep becomes real. Use ownership, budgets, route-level bundles, script loading policies, and periodic audits. Every script should have a reason to be on the critical path.

Senior Engineer Perspective

A senior engineer should explain loading attributes and then discuss script ownership, execution cost, hydration, third-party risk, and measurement.

Lead Engineer Perspective

A lead engineer should set platform rules: default to defer or framework-managed loading, audit third-party tags, budget route JavaScript, and make script additions visible in review.

Whiteboard Explanation

Draw the HTML parser timeline. Show classic script pausing parsing, defer downloading in parallel and executing after parse, async executing when ready, and module script resolving a dependency graph.

Revision Notes

Classic scripts block parsing. defer preserves order and runs after parse. async runs when ready and does not preserve order. Modules are deferred by default. Preload improves discovery but can compete with other resources.

Key Takeaways

Script loading is about discovery, execution order, main-thread cost, and ownership. The fastest script is often the one you do not load on the critical path.

Related Topics

  • Critical rendering path
  • Event loop
  • V8
  • Hydration
  • Third-party scripts
  • CSP
  • Core Web Vitals

Practice Exercise

Create an HTML file with classic, async, defer, and module scripts that log execution order. Predict the order, then explain how network timing can change async behavior.

Follow-Up Questions

  1. How does a classic script block parsing?
  2. How does defer differ from async?
  3. Are module scripts deferred?
  4. What does modulepreload do?
  5. When would you use preconnect?
  6. Can too much preload hurt performance?
  7. How do third-party scripts affect INP?
  8. How would you audit script cost?
  9. What is Subresource Integrity?
  10. How does script loading affect hydration?

Things Interviewers Hate Hearing

"Use async for performance" is too broad. Async can break ordering and still execute at a bad time. Explain dependency, execution timing, and critical path impact.

How I Would Answer This In A Real Interview

I would explain classic scripts first: they can block parsing because they may mutate the document. Then I would contrast defer, which downloads in parallel and executes after parsing in order, with async, which downloads in parallel but executes whenever ready. Modules are deferred by default and involve a dependency graph.

Then I would connect it to production. I would keep critical app code predictable, avoid third-party scripts on the critical path, use preload or preconnect only for important resources, and measure both network and main-thread execution cost in DevTools.