Skip to content

Test your website now

Free, no card. We read only public pages.

Run free audit →

Performance · Info severity

Too Many Inline Scripts: Separate Code from Data

Review too many inline scripts. Separate executable code from JSON-LD and state, reduce repeated work, preserve load order, and verify actual blocking time.

Published · Updated

What the check tests

Check
perf.inline-scripts - Inline script volume in check
Passes when
Pages should not embed dozens of inline script blocks; bundle or defer them.
Scope
graded on every page crawled
Severity
Info
Fix effort
medium - a working day
Impact when fixed
low

In one paragraph

Too many inline scripts means the initial HTML contains more script elements without src than this check permits. That includes non-executable data blocks, so the count alone does not prove excessive JavaScript execution. Classify the blocks, remove duplication, and move substantial reusable code where appropriate. Preserve required ordering and judge performance with bytes and main-thread activity, not the tag count alone.

Why it matters

Classic inline JavaScript normally runs when the parser reaches it and can interrupt parsing while it executes. An inline block can also contain only a tiny configuration object, while another performs substantial synchronous work. Counting them equally loses that distinction.

Not every script element is executable JavaScript. JSON-LD, application/json state, import maps, and template data need separate interpretation. They still consume bytes and processing, but do not execute like a classic JavaScript program. Module-script loading also has different scheduling semantics from ordinary classic inline scripts.

Inline code can complicate CSP management and repeats with each HTML response instead of using an independently cached script resource. Those are practical maintenance concerns, not a reason to eliminate every small bootstrap or early theme-setting snippet.

How WebAuditOS evaluates this finding

The supplied rule counts script elements lacking a src attribute in served HTML, regardless of type or content. Twenty or fewer pass; more than twenty warn informationally. Unparseable HTML is not graded.

It does not measure code size, runtime, usefulness, or scripts injected later. A page with many JSON-LD blocks can warn without corresponding executable work. A page with one expensive inline script can pass. Treat this as an inventory signal.

How to fix it

  1. Inspect the page source and list blocks by type, owner, purpose, and approximate size. Separate executable bootstraps, settings objects, structured data, framework state, and templates.
  2. Remove confirmed duplication at the source. Repeated analytics snippets or the same component initialiser can add both bytes and unwanted repeated behaviour. Verify ownership before deletion.
  3. Move substantial reusable application code into an appropriately cached resource when that improves delivery. An external classic script can use defer where suitable:
<script src="/assets/app.js" defer></script>

The example is not a reason to defer every dependency or copy all small configuration data into another request.

  1. Preserve ordering. An inline consumer does not wait for a preceding deferred external script merely because it appears later in the HTML. Move related initialisation into the deferred workflow or an appropriate documented lifecycle.
  2. Keep intentional early functions only when justified, such as a required consent bootstrap or an accessible theme-state setup. Review their size, failure mode, and CSP authorisation rather than assuming every early block is harmless.
  3. Optimise oversized serialised state independently. Remove fields the browser does not need and avoid leaking private data into public HTML. Fewer blocks containing the same excessive state is not a payload improvement.
  4. Consolidate structured data only when it produces a maintainable equivalent graph. Valid JSON-LD can use multiple blocks; merging them solely to clear this threshold is not an established speed improvement. Preserve identifiers, relationships, and accurate content.
  5. Test real execution in a performance trace, verify CSP and interactive features, then rescan. Compare TBT, rendering, bytes, and cache behaviour rather than treating a lower count as proof of faster interaction.

What the fix can break

Combining code can change execution order, variable scope, and dependencies. A performance plugin cannot automatically know every custom integration's assumptions. Keep checkout, consent, and authentication tests explicit.

Moving an early visual-state snippet too late can create a theme flash; moving a consent gate can affect tag behaviour. Review the real role before changing scheduling.

Do not weaken CSP with unsafe-inline just to restore a broken optimisation. Fix the authorisation and ordering design. A green count with a more permissive policy is not necessarily a better outcome.

Questions

Does JSON-LD count here?

Yes. The documented rule counts script elements without src regardless of type. That is not equivalent to executable JavaScript cost.

Does defer delay classic inline code?

Not in the same way as an external classic script. Review actual script type and scheduling instead of adding ineffective attributes.

Must every inline block become a file?

No. Small justified settings and early bootstraps can remain inline. Focus on duplicated or substantial work.

Review HTML size, blocking time, and the Core Web Vitals guide.

In the report

Test this on your own site

Every scan runs perf.inline-scripts on every page it crawls, on every plan. The finding carries this id, so a line in a report can be matched to the explanation above - and the free scan needs no account.