squirrelscan
GitHub

core-js and Babel helpers: legacy JavaScript in a bundle

Polyfill bundles and ES5 transpilation helpers shipped to browsers that do not need them. squirrel reads script URLs and inline code.

What legacy JavaScript is

A polyfill implements a feature the browser lacks. A transpiler rewrites modern syntax into older syntax that more browsers understand. Both were necessary when a meaningful share of traffic ran browsers without Promise or arrow functions. That share is now small, and the code is still shipped by default in many build configurations.

The cost is bytes and parse time for every visitor, including the majority whose browser needed none of it. The lever is the build target: a browserslist that names modern browsers makes the transpiler and the polyfill injector emit far less.

What squirrel checks

The rule runs on every crawled page and looks at three things. It emits one to three checks:

  • legacy-polyfills: warns with the message N legacy polyfill(s) detected, listing each by name. It matches eleven patterns in <script src> URLs: core-js, regenerator-runtime, babel-polyfill, polyfill.io, es5-shim, es6-shim, promise-polyfill, fetch-polyfill, whatwg-fetch, @babel/runtime and tslib.
  • es5-code-patterns: reports at info status with the message N ES5 transpilation pattern(s) found, listing up to five. It scans inline scripts of 500 characters or more, skipping any whose type mentions json, for nine signatures including _classCallCheck, _createClass, _inherits, _typeof, __esModule, __spreadArray, __awaiter and __generator.
  • differential-serving: passes with the message Uses module/nomodule differential serving when the page has both a script[type="module"] and a nomodule script.
  • es-modules: passes with the message N ES module script(s) detected when there are module scripts but no nomodule counterpart.
  • legacy-js: reports at info status with the message No legacy JavaScript patterns detected when there are no polyfills, no ES5 patterns and no module scripts.

Every result here is a warning at most, and the rule’s severity is info. A page with no parsed document emits nothing at all.

Elements inside <noscript> are skipped: a browser with scripting enabled reads <noscript> content as plain text, so nothing in it loads or renders. See content inside noscript.

How to fix it

Set the build target to the browsers the site supports:

{
  "browserslist": ["> 0.5%", "last 2 versions", "not dead"]
}

Babel and the bundlers read that list, and a modern target removes most of the helpers and nearly all of the polyfills. TypeScript has its own target compiler option, which controls the same thing for its helpers. Where a specific feature still needs one, importing that polyfill alone is far smaller than a whole core-js bundle.

The common false positive is tslib. It is TypeScript’s helper library rather than a polyfill, and importing it is usually the smaller option, because the alternative is inlining the same helpers into every file that needs them.

Rule IDperf/legacy-js
CategoryPerformance
ScopePer-page
Severityinfo
Weight3/10

Enable / disable

Disable this rule

[rules]
disable = ["perf/legacy-js"]

Disable all Performance rules

[rules]
disable = ["perf/*"]

Enable only this rule

[rules]
enable = ["perf/legacy-js"]

enable replaces the default ["*"], so this is the only rule selected. Leave disable out: a rule that matches any disable pattern is skipped even when enable names it. Only an enabled setting under a rule’s own [rule_options] table overrides both lists.

Performance findings ship in every audit next to the SEO, security and agent experience rules. See Core Web Vitals for how an agent works through a report.

References

Check your site

Run squirrel audit https://example.com and open the Performance section of the report. Each polyfill and transpilation pattern is listed by name. Signed-out local audits need no account and cost nothing. Signed-in audits spend credits.

Type to search…

↑↓ navigate↵ openesc close