Lighthouse audit legacy-javascript-insight · Performance

"Avoid serving legacy JavaScript to modern browsers": how to fix it

Quick answer: Lighthouse flags polyfills and Babel transforms that modern browsers do not need, such as Array.from or transpiled classes. Lighthouse 13 calls it "Legacy JavaScript". Fix your own bundle with a modern browserslist, @babel/preset-env with useBuiltIns usage, and an ES2020 build target. For third-party scripts, update or remove the tag.
View raw .md for LLMs / your notes

This audit flags polyfills and Babel transforms that modern browsers do not need. Lighthouse 13 shows it as the Legacy JavaScript insight. Older Lighthouse versions, PageSpeed Insights reports, GTmetrix, and Screaming Frog still print the old wording: "Avoid serving legacy JavaScript to modern browsers". It is the same check. In our study of 269 Shopify storefronts, 211 of them (78.4%) failed it. This page covers what the report rows mean, how to fix the code you own, and what to do when the row is a third-party script.

TL;DR

What does "Avoid serving legacy JavaScript to modern browsers" mean?

Build tools often compile modern JavaScript down to ES5 so it runs in old browsers like Internet Explorer 11. They also add polyfills: small libraries that recreate newer built-in methods. Modern browsers already have those features, so that extra code is pure cost for them.

Lighthouse scans each script for known signatures of this code and lists what it finds:

Column in the reportWhat it tells you
URLThe script that contains the legacy code. This tells you who owns the fix.
Signal (the code rows under each URL)The polyfill or transform Lighthouse matched, such as Array.from, Object.assign, @babel/plugin-transform-regenerator, or @babel/plugin-transform-spread
Wasted bytesLighthouse's estimate of the bytes that legacy code adds to that script

The insight does not change your Performance score by itself. It feeds the score through the metrics: smaller scripts parse and run faster, which helps Total Blocking Time and main-thread work.

Why did Lighthouse rename it to "Legacy JavaScript"?

Lighthouse 13 replaced many of the older opportunity audits with "insights" that match the Performance panel in Chrome DevTools. The audit id changed from legacy-javascript to legacy-javascript-insight, and the title changed from "Avoid serving legacy JavaScript to modern browsers" to "Legacy JavaScript". The check and the fix are the same. If you search for either wording, this page applies.

How do I find which scripts Lighthouse flagged?

  1. In the report, open the Performance section and expand Legacy JavaScript (or "Avoid serving legacy JavaScript to modern browsers" in older versions). Note each URL and the signals under it.
  2. Sort by ownership. URLs on your own domain or your bundle filenames are yours to fix. URLs on connect.facebook.net, googletagmanager.com, app CDNs, or captcha domains belong to a vendor.
  3. For many pages, read the JSON output:

   lighthouse https://example.com --only-categories=performance --output=json --quiet \
     | jq -r '.audits["legacy-javascript-insight"].details.items[]
              | "\(.wastedBytes) \(.url)"'
   

How do I fix legacy JavaScript in my own build?

The fix is to tell your toolchain which browsers you support, then let it skip the code those browsers do not need.

1. Set a modern browserslist

Most tools (Babel, Autoprefixer, Next.js, many bundler plugins) read the same browserslist setting. Add it to package.json:

{
  "browserslist": [
    "defaults and fully supports es6-module",
    "not dead"
  ]
}

This targets browsers that support native ES modules. Every current version of Chrome, Edge, Firefox, and Safari meets it. Run npx browserslist to see the exact list it resolves to.

2. Polyfill only what the targets need

If you use @babel/preset-env, do not import all of core-js at the top of your entry file. Let Babel add only the polyfills your code uses and your targets lack:

// babel.config.js
module.exports = {
  presets: [
    ['@babel/preset-env', {
      useBuiltIns: 'usage',
      corejs: 3,
      bugfixes: true,
    }],
  ],
};

Then remove any import 'core-js' or import '@babel/polyfill' line from the entry file. With modern targets, most of the polyfills Lighthouse lists disappear from the bundle.

3. Raise the TypeScript and bundler target

4. Serve a legacy bundle only if you must

If you have a real requirement to support old browsers, build two bundles. Load the modern one with <script type="module"> and the legacy one with <script nomodule>. Modern browsers ignore nomodule, so they never download the legacy code.

<script type="module" src="/app.modern.js"></script>
<script nomodule src="/app.legacy.js"></script>

How do I fix it in Next.js, WordPress, or Shopify?

Can I pass this audit if a third-party script causes it?

Usually not, and it is often not worth trying. A vendor builds its script for the widest set of browsers it supports, and you cannot recompile it. Your options:

  1. Remove the tag if it does not earn its place. This is the only fix you fully control.
  2. Update to the vendor's current SDK. Some vendors publish a modern build.
  3. Load it later. Moving an optional tag after window.load does not remove the bytes, but it takes them off the critical path for TBT.
  4. Accept the row. The savings on a single vendor script are often 10 KiB to 20 KiB. Spend the effort on unused JavaScript first, where the same scripts usually waste far more.

How do I verify the fix?

  1. Rebuild for production and re-run Lighthouse. The rows for your own bundle should be gone or have smaller savings.
  2. Search the built output for the signals Lighthouse listed. For example, grep -l "regeneratorRuntime" dist/*.js should return nothing after you drop ES5 async transforms.
  3. Test in the browsers you still support. A target that is too aggressive breaks old browsers, so check your analytics for real browser versions before you raise it.
  4. Compare the bundle size before and after with your bundler's analyzer or ls -lh on the output files.

What mistakes should I avoid?


Audit your URL at https://lighthouse-md.com.

Audit your page now

Paste your URL, get scores plus a CLAUDE.md plan for Claude Code.

Run audit →
Add us as a preferred source on Google

One click, and Google shows more of lighthouse-md.com in your search results.