squirrelscan
GitHub

Same library loaded twice: duplicate JavaScript on a page

One library loaded from two script tags, or at two different versions. squirrel reads library names out of the script URLs.

What a duplicate library is

Two script tags loading the same library from different URLs cost the bytes twice and, worse, can leave two copies in memory that do not share state. With React that means hooks failing at runtime. With jQuery it means whichever loaded last winning and any plugin registered against the first one disappearing.

Two different versions is the sharper version of the problem. It usually happens when a third-party embed brings its own copy of a library the page already loads, or when a tag manager injects one.

What squirrel checks

The rule runs on every crawled page over its <script src> elements. It extracts a library name and, where the URL carries one, a version, then groups by name. It emits one or two checks:

  • duplicate-js-version-mismatch: fails with the message N library(s) loaded with different versions, listing each as <name> (versions: 3.6.0, 3.7.1).
  • duplicate-js-same-version: warns with the message N library(s) loaded multiple times, listing each as <name> (2x).
  • duplicate-js: passes with the message No duplicate JavaScript libraries detected, recording how many scripts it analysed.

Names are matched from four URL shapes, in order: an unpkg path, a jsDelivr npm path, a cdnjs path, and a generic /<name>.js path where the name may be followed by a dotted or hyphenated numeric version and by .min. When none matches, the leading run of letters, digits and hyphens in the filename becomes the name. Names are lowercased; versions are compared as written. The rule reads the <script src> elements on the page only.

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

Load each library once, from one place. Where a bundler is in use, that usually means marking the library external and providing it yourself rather than letting two chunks each include it:

<script src="https://unpkg.com/react@18.3.1/umd/react.production.min.js"></script>

Where a third-party embed brings its own copy, the vendor usually has a build that uses the page’s copy instead.

The common false positive comes from matching on filenames. Two unrelated files that share a name, such as /a/main.js and /b/main.js, both reduce to main and are reported as one library loaded twice. Check the listed names before changing anything.

Rule IDperf/duplicate-js
CategoryPerformance
ScopePer-page
Severitywarning
Weight5/10

Enable / disable

Disable this rule

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

Disable all Performance rules

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

Enable only this rule

[rules]
enable = ["perf/duplicate-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 duplicated library is listed with its versions. Signed-out local audits need no account and cost nothing. Signed-in audits spend credits.

Type to search…

↑↓ navigate↵ openesc close