Opens in a new tab
  1. Home
  2. Guides
  3. Utilities
Utilities guide

How to remove unused WordPress scripts

Learn how to identify unused WordPress JavaScript, trace script handles and dependencies, use wp_dequeue_script safely and conditionally load frontend assets only where they are actually required.

  • Updated September 9, 2026
  • 21 min read
  • WordPress guide

Removing unused WordPress scripts can reduce JavaScript downloads, execution time and unnecessary frontend dependencies, but the safe way to do it is not to delete every file that a performance report labels as “unused JavaScript.”

WordPress has a dependency-aware script system.

A JavaScript file can be:

  • registered but not loaded;
  • directly enqueued;
  • automatically loaded as another script’s dependency;
  • loaded only on particular templates;
  • required only after user interaction;
  • used by a plugin even when its code coverage appears low during one test.

Removing the wrong handle can break forms, sliders, menus, WooCommerce interactions, page builders, block functionality or other frontend features.

The correct process is therefore:

identify
↓
trace ownership
↓
check dependencies
↓
confirm where it is needed
↓
remove or conditionally load it
↓
test

This guide explains how WordPress loads JavaScript, how to identify unused scripts, how wp_dequeue_script() and wp_deregister_script() differ, how dependencies affect removal and how to build a safer conditional-loading strategy.

How WordPress loads scripts

WordPress does not normally require themes and plugins to print raw script tags manually.

Instead, it provides an asset-management system based around functions such as:

wp_register_script()
wp_enqueue_script()
wp_dequeue_script()
wp_deregister_script()
wp_script_is()

The official wp_enqueue_script() documentation describes it as the recommended method for adding JavaScript to a WordPress-generated page.

For the broader architecture, see wp_enqueue_scripts Explained.

What is a script handle?

WordPress identifies scripts using a handle.

For example:

wp_enqueue_script(
    'example-slider',
    plugin_dir_url( __FILE__ ) . 'slider.js'
);

The handle is:

example-slider

The URL may change between versions, but WordPress code can continue referring to the asset by its handle.

Why handles matter when removing scripts

You normally remove a WordPress-managed script by its handle rather than by manipulating the final HTML.

For example:

wp_dequeue_script( 'example-slider' );

This tells WordPress to remove that handle from its current script queue.

Registered does not mean loaded

A common mistake is to see a script inside the WordPress registry and assume the browser downloads it.

That is not necessarily true.

A plugin may register a script:

wp_register_script(
    'example-gallery',
    plugin_dir_url( __FILE__ ) . 'gallery.js'
);

without enqueueing it.

In that state:

registered
=
WordPress knows about the asset

but:

not necessarily downloaded

Registered scripts can become dependencies later

The official wp_register_script() documentation explains that a registered script can automatically be loaded when another enqueued script declares it as a dependency.

For example:

wp_register_script(
    'library-a',
    '/library-a.js'
);

wp_enqueue_script(
    'feature-b',
    '/feature-b.js',
    array( 'library-a' )
);

Even though you never explicitly enqueue:

library-a

WordPress loads it because:

feature-b
↓ depends on
library-a

This is why dependency auditing matters

Removing:

library-a

without checking:

feature-b

can break the dependent script.

What does “unused JavaScript” actually mean?

Performance tools frequently report unused JavaScript.

That phrase usually means:

JavaScript downloaded
but not executed
during the measured page load

It does not automatically mean:

JavaScript has no purpose anywhere on the site

A script can appear unused during one test and still be necessary

Consider a contact-form library.

The initial page load might not execute most of its code.

But later:

visitor clicks field
↓
validation runs

visitor submits
↓
AJAX runs

validation fails
↓
error handling runs

A page-load-only coverage test may not execute all of those code paths.

Unused code and unused script are different problems

This distinction is critical.

A 200 KB bundle might contain:

30 KB actually required
170 KB unused on this page

That does not necessarily mean you can remove the whole bundle.

The better engineering solution may be:

  • code splitting;
  • smaller bundles;
  • conditional loading;
  • plugin configuration;
  • removing the underlying feature.

Start with the browser Network panel

Open your browser developer tools and reload the page with the Network panel visible.

Filter requests by:

JS

Review:

  • filename;
  • URL;
  • domain;
  • transfer size;
  • initiator;
  • loading order;
  • whether the file is cached.

Do not inspect only filenames

A filename such as:

frontend.min.js

does not tell you who owns it.

The path often provides more information:

/wp-content/plugins/plugin-name/assets/js/frontend.min.js

or:

/wp-content/themes/theme-name/assets/js/app.js

This can immediately identify the likely owner.

Use browser code coverage as supporting evidence

Browser developer tools can measure how much JavaScript executes during a test.

This can help identify large scripts that are downloaded but barely used.

However, coverage should be interpreted carefully.

Test the interactions associated with the script before deciding it is unnecessary.

For example:

  • open menus;
  • submit forms;
  • open modals;
  • change product variations;
  • add items to cart;
  • use search;
  • open galleries;
  • trigger lazy-loaded features.

Performance audits are starting points, not removal instructions

A performance report may say:

Reduce unused JavaScript

The correct interpretation is:

investigate why this code was delivered

not:

delete every highlighted file

Find the WordPress handle

Before using wp_dequeue_script(), you need the script handle.

Possible sources include:

  • the plugin source code;
  • the theme source code;
  • WordPress debugging tools;
  • the global script registry;
  • script HTML IDs generated from handles.

Script tags often expose the handle

WordPress commonly outputs script IDs derived from the handle.

For example:

<script
    src="..."
    id="example-slider-js"
></script>

The corresponding handle is often:

example-slider

This is useful for investigation, although source-code verification is still preferable.

Search the plugin or theme source code

Search for:

wp_enqueue_script(
wp_register_script(

and for the filename you identified in DevTools.

You may find something like:

wp_enqueue_script(
    'example-slider',
    plugins_url(
        'assets/js/slider.js',
        __FILE__
    ),
    array( 'jquery' ),
    '2.0.0',
    true
);

Now you know:

handle:
example-slider

dependency:
jquery

owner:
plugin

Use wp_script_is() to inspect a script state

WordPress provides:

wp_script_is()

The official wp_script_is() documentation supports statuses including:

  • enqueued;
  • registered;
  • queue;
  • to_do;
  • done.

For example:

if ( wp_script_is( 'example-slider', 'enqueued' ) ) {
    // The script is currently enqueued.
}

Registered and enqueued are different states

You can check both:

wp_script_is(
    'example-slider',
    'registered'
);

wp_script_is(
    'example-slider',
    'enqueued'
);

A script may return:

registered = true
enqueued = false

which means there may be nothing to remove from the current page queue.

Inspect the WordPress script registry

WordPress exposes its current script manager through:

wp_scripts()

The official wp_scripts() documentation identifies it as the function that initializes or returns the WP_Scripts instance.

For debugging, you can inspect information such as:

$scripts = wp_scripts();

$scripts->registered;
$scripts->queue;
$scripts->done;

Do not dump the entire object publicly on production.

The registered array contains dependency information

For a known handle:

$scripts = wp_scripts();

$script = $scripts->registered[
    'example-slider'
];

you may inspect:

$script->src
$script->deps
$script->ver

This can help answer:

Where does it come from?
What does it depend on?

You also need the reverse dependency question

Knowing:

example-slider
depends on jquery

is only half of the dependency analysis.

You should also ask:

Does another script depend on example-slider?

If yes, removing it may prevent the dependent feature from working correctly.

What does wp_dequeue_script() do?

WordPress provides:

wp_dequeue_script( $handle );

The official wp_dequeue_script() documentation defines it as removing a previously enqueued script.

For example:

wp_dequeue_script(
    'example-slider'
);

This removes the script from the current queue.

Dequeueing does not necessarily remove registration

Think of the states as:

registered
↓
available

enqueued
↓
requested for current page

Dequeue removes:

enqueued state

but does not inherently erase the registration.

What does wp_deregister_script() do?

WordPress also provides:

wp_deregister_script()

The official wp_deregister_script() documentation defines it as removing a registered script.

For example:

wp_deregister_script(
    'example-slider'
);

Now WordPress no longer has the script registered under that handle.

Dequeue vs. deregister

A useful model is:

wp_dequeue_script()
→ do not load this queued script here

wp_deregister_script()
→ remove this script from the registry

They solve different problems.

Usually start with dequeue

If your goal is simply:

do not load this asset
on this template

dequeueing is usually the more targeted operation.

Deregistering becomes relevant when you intentionally need to remove or replace the registration itself.

WordPress protects some critical admin scripts

The current wp_deregister_script() implementation contains safeguards that prevent certain important scripts from being deregistered improperly in the WordPress administration area.

This is another reason frontend optimization should normally be performed through the frontend:

wp_enqueue_scripts

lifecycle rather than through broad global code.

A basic dequeue example

Suppose a plugin loads:

example-slider

on every page, but your homepage does not use a slider.

You could conditionally remove it:

add_action(
    'wp_enqueue_scripts',
    function () {
        if ( is_front_page() ) {
            wp_dequeue_script(
                'example-slider'
            );
        }
    },
    100
);

The late priority is intentional in this example.

Your callback must run after the plugin has enqueued the script.

Hook priority matters

Suppose the plugin enqueues at:

priority 20

while your removal runs at:

priority 10

The sequence becomes:

your code runs
↓
nothing currently queued
↓
plugin runs later
↓
script gets enqueued

Your removal appears not to work.

Use a later priority when removing another component’s asset

A common pattern is:

add_action(
    'wp_enqueue_scripts',
    'my_remove_scripts',
    100
);

The exact priority should reflect the asset owner rather than blindly using a magic number.

Do not use wp_head to randomly strip script tags

WordPress’s enqueue system already tracks:

  • handles;
  • dependencies;
  • versions;
  • loading strategies;
  • head/footer placement.

Removing generated HTML afterward bypasses that dependency model.

If an asset is managed by WordPress, prefer the WordPress asset APIs.

Conditional loading is usually better than global removal

The best optimization is often not:

remove plugin script everywhere

but:

load plugin script only
where plugin functionality exists

Example: load a form script only on the contact page

A poorly configured plugin might enqueue:

form-validation.js

on:

  • homepage;
  • blog articles;
  • archives;
  • contact page.

But if the form exists only on:

/contact/

the ideal architecture is:

contact page
→ load form script

other pages
→ do not load it

Removing a script everywhere can break the feature page

This would be unsafe:

add_action(
    'wp_enqueue_scripts',
    function () {
        wp_dequeue_script(
            'form-validation'
        );
    },
    100
);

because the contact page needs it too.

Condition the removal instead

For example:

add_action(
    'wp_enqueue_scripts',
    function () {
        if ( ! is_page( 'contact' ) ) {
            wp_dequeue_script(
                'form-validation'
            );
        }
    },
    100
);

This keeps the functionality where it is needed.

Page IDs can be safer than slugs in some projects

A slug can change.

For internal project code, you may prefer a stable page ID:

if ( ! is_page( 123 ) ) {
    wp_dequeue_script(
        'form-validation'
    );
}

The correct choice depends on how the project manages configuration across environments.

Use WordPress conditional tags

Useful conditions include:

is_front_page()
is_home()
is_page()
is_single()
is_singular()
is_archive()
is_search()
is_404()

The official WordPress Conditional Tags documentation explains the available query conditions.

Conditional tags must run at the right time

The frontend wp_enqueue_scripts lifecycle is appropriate because WordPress query conditionals such as is_page() are available there.

The official wp_enqueue_scripts() documentation notes that this stage runs where normal query conditionals are available.

Remove scripts by post type

You may have a script needed only for products.

For example:

add_action(
    'wp_enqueue_scripts',
    function () {
        if ( ! is_singular( 'product' ) ) {
            wp_dequeue_script(
                'product-gallery'
            );
        }
    },
    100
);

But do not assume every WooCommerce script is needed only on a product page.

Cart fragments, checkout interactions and account functionality can have different scopes.

WooCommerce deserves careful testing

An ecommerce site may depend on JavaScript for:

  • product variation selection;
  • gallery behavior;
  • add-to-cart actions;
  • mini-cart updates;
  • coupon application;
  • checkout validation;
  • payment gateways;
  • account interactions.

A script that appears unnecessary on one product page can still be required during another WooCommerce workflow.

See WooCommerce Account and Checkout Pages, Explained for the broader architecture of those pages.

Check logged-in and logged-out states

Some scripts are conditional on authentication.

A logged-out visitor may see:

script not used

while a logged-in editor or member may trigger:

  • toolbar functionality;
  • account menus;
  • membership features;
  • frontend editing;
  • personalized widgets.

Test both states where relevant.

Check mobile behavior separately

Responsive navigation is one of the easiest things to break when removing frontend JavaScript.

A desktop menu may work without JavaScript while the mobile menu depends on:

click
↓
JavaScript
↓
open navigation panel

Always test touch interactions after asset removal.

Check hidden components

A script might control something that is not initially visible.

Examples include:

  • modals;
  • accordions;
  • tabs;
  • cookie banners;
  • search overlays;
  • off-canvas menus;
  • lazy-loaded galleries.

Initial code coverage may underestimate these features.

Check dependency chains before removing jQuery

jQuery is one of the most commonly targeted WordPress scripts because modern JavaScript can often replace it.

But WordPress plugins can still declare:

jquery

as a dependency.

If you remove jQuery while another enqueued script depends on it, you have changed the dependency architecture rather than merely removing unused bytes.

See Checking Your Site for Legacy jQuery Dependencies before attempting that optimization.

jQuery Migrate is a separate dependency

WordPress also maintains a jQuery Migrate compatibility layer in its normal jQuery dependency graph.

Whether your site still requires it is a separate question from whether the site requires jQuery itself.

See What Is jQuery Migrate, and Do You Need It?.

Do not replace WordPress’s jQuery casually

Some old optimization guides suggest:

deregister WordPress jQuery
↓
load CDN jQuery instead

This can create:

  • version mismatches;
  • dependency problems;
  • load-order problems;
  • plugin incompatibility.

If the objective is removing unused JavaScript, replacing one managed dependency with another remote copy does not solve the architectural problem.

Third-party scripts deserve their own audit

A WordPress page may load JavaScript directly from:

  • analytics providers;
  • chat systems;
  • advertising networks;
  • video platforms;
  • maps;
  • social platforms.

These may not always be manageable through a WordPress handle if the provider injects them dynamically.

See WordPress Privacy and Third-Party Requests for the broader audit model.

One third-party script can create many more requests

The request graph may look like:

chat-widget.js
↓
executes
↓
loads iframe
↓
loads API
↓
loads analytics
↓
loads fonts

Removing the initial script can therefore eliminate much more than the size of that single JavaScript file.

This is one reason third-party feature removal can produce greater gains than micro-optimizing small WordPress core assets.

Why third-party embeds can be expensive

An embedded video or social post may introduce:

  • JavaScript;
  • iframes;
  • stylesheets;
  • tracking;
  • additional domains.

If unused embeds are contributing scripts to the page, see Why Third-Party Embeds Slow Down WordPress.

Remove the feature before hacking around its assets

If a plugin feature is completely unused, the best solution may be:

disable feature
or
remove plugin

rather than maintaining:

plugin active
+
custom dequeue rules
+
custom exceptions

A cleaner architecture reduces future maintenance.

Plugin settings may already provide conditional loading

Before writing custom PHP, inspect the plugin settings.

Some plugins provide options such as:

  • load assets only when shortcode exists;
  • disable frontend scripts;
  • disable unused widgets;
  • disable globally loaded styles;
  • disable legacy compatibility.

A supported plugin setting is usually preferable to overriding the plugin externally.

Fixing the source is better than compensating downstream

If you maintain the plugin or theme, do not enqueue feature-specific JavaScript globally and then dequeue it elsewhere.

Instead of:

every page
→ enqueue slider.js

later
→ remove slider.js from 95% of pages

prefer:

slider page
→ enqueue slider.js

Example of correct conditional enqueueing

add_action(
    'wp_enqueue_scripts',
    function () {
        if ( ! is_page( 'gallery' ) ) {
            return;
        }

        wp_enqueue_script(
            'my-gallery',
            get_theme_file_uri(
                '/assets/js/gallery.js'
            ),
            array(),
            '1.0.0',
            array(
                'in_footer' => true,
            )
        );
    }
);

This is much easier to maintain than globally loading the script and then creating removal rules.

Blocks should load assets only where appropriate

Custom blocks can have their own frontend script requirements.

If a JavaScript component belongs only to one block, loading it across every page can be wasteful.

Modern WordPress block registration APIs allow assets to be associated with individual blocks rather than with the entire site.

If your project uses blocks extensively, see WordPress Block Editor CSS Explained for the related asset-context distinctions.

Script Modules are another modern WordPress asset system

Modern WordPress also supports JavaScript modules through APIs such as:

wp_enqueue_script_module()

The official wp_enqueue_script_module() documentation explains that module identifiers and dependencies are managed through WordPress’s script-module infrastructure.

This means not every modern WordPress JavaScript dependency is necessarily managed through the traditional WP_Scripts registry.

Do not assume wp_dequeue_script() controls script modules

Traditional scripts and script modules are separate systems.

If a JavaScript resource is registered as a script module, investigate its module registration and dependency graph rather than assuming a traditional script handle exists.

Modern script loading strategies can reduce cost without removing the asset

Sometimes the script is necessary but does not need to block page parsing.

Current wp_enqueue_script() supports loading strategies such as:

defer
async

For example:

wp_enqueue_script(
    'analytics-helper',
    get_theme_file_uri(
        '/assets/js/analytics.js'
    ),
    array(),
    '1.0.0',
    array(
        'strategy'  => 'defer',
        'in_footer' => true,
    )
);

Removing the script and scheduling the script are different optimizations.

Do not use defer or async blindly either

A script may depend on another script or need to execute before inline code.

WordPress evaluates loading strategies in relation to the dependency tree.

Use the native enqueue system rather than manually adding attributes to generated script tags wherever possible.

Reducing page weight is more than reducing request count

Modern HTTP means fewer requests are not automatically better in every scenario.

See Reducing WordPress Front-End Page Weight for the broader optimization model.

The useful questions are:

  • Is the JavaScript necessary?
  • How large is it?
  • How much executes?
  • Is it loaded on the correct templates?
  • Can it be cached?
  • Can it be deferred?
  • Can the feature be removed?

Removing one small script may have negligible impact

If a script is:

2 KB
+
cached
+
deferred
+
rarely executed

removing it may have almost no measurable user-facing effect.

Meanwhile a single third-party widget could add hundreds of kilobytes and significant execution time.

Prioritize meaningful bottlenecks.

Large JavaScript can affect more than download time

JavaScript has several costs:

download
↓
decompress
↓
parse
↓
compile
↓
execute

On slower devices, CPU cost can become particularly important.

This is why removing a truly unnecessary JavaScript bundle can provide benefits beyond transfer size alone.

Do not optimize only the homepage

Different WordPress templates can load completely different scripts.

Audit at least:

  • homepage;
  • blog article;
  • archive;
  • landing page;
  • contact page;
  • product page;
  • cart;
  • checkout;
  • account page.

A script that is unused on the homepage may be essential elsewhere.

Create a script inventory

A useful audit table might contain:

Handle
Owner
File
Size
Pages loaded
Purpose
Dependencies
Required?
Action

For example:

contact-form
Form plugin
form.js
45 KB
All pages
Form validation
jquery
Only on contact
Load conditionally

Classify scripts instead of simply deleting them

Useful classifications include:

Required globally

Required conditionally

Required but should be deferred

Legacy dependency

Duplicate library

Third-party optional feature

Completely unused

Each category suggests a different solution.

Duplicate JavaScript deserves investigation

A site may accidentally load multiple versions of:

  • jQuery;
  • Swiper;
  • Slick;
  • GSAP;
  • lightbox libraries;
  • validation libraries.

This can happen when independent plugins bundle their own copies.

WordPress handles can prevent some duplication

If multiple components depend on the same registered handle, WordPress can coordinate the dependency.

But if two plugins register physically equivalent libraries under unrelated handles, WordPress cannot necessarily know they are duplicates.

This is covered in more detail in wp_enqueue_scripts Explained.

Do not merge two libraries merely because their filenames look similar

They may be:

  • different versions;
  • different builds;
  • configured differently;
  • extended by plugins;
  • not API-compatible.

Verify versions and usage before consolidating them.

Cache plugins can complicate testing

After changing script loading, clear relevant caches.

A WordPress site may involve:

  • page cache;
  • server cache;
  • CDN cache;
  • browser cache;
  • asset optimization cache.

You may remove a script correctly in PHP while still seeing an old cached page containing it.

Minification and concatenation can hide ownership

An optimization plugin may combine:

plugin-a.js
plugin-b.js
theme.js

into something like:

autoptimize_123abc.js

That makes the final network request less useful for identifying the source.

During an audit, temporarily testing without combination can make ownership easier to trace.

Do not permanently disable optimization just to inspect assets

The objective is to understand the original dependency structure, then re-enable the production optimization layer and verify the final result.

Removing plugin scripts after an update can become fragile

Suppose your custom code contains:

wp_dequeue_script(
    'plugin-old-handle'
);

A plugin update might:

  • rename the handle;
  • split the bundle;
  • change conditional loading;
  • introduce new dependencies.

Your optimization code may silently stop doing what you expect.

Document every custom asset rule

For each custom dequeue, record:

handle
owner
reason
templates affected
date tested

This makes future maintenance much safer.

Use staging for significant script removal

If a script’s dependencies are unclear, test the change on staging.

See WordPress Staging Site Best Practices.

Script removal can create failures that are not immediately visible from the first page load.

Test the complete user workflow

After removal, test:

  • navigation;
  • search;
  • forms;
  • modals;
  • accordions;
  • tabs;
  • sliders;
  • galleries;
  • login;
  • registration;
  • password reset;
  • cart;
  • checkout;
  • payment methods;
  • account pages;
  • mobile menu;
  • cookie consent;
  • analytics where applicable.

Watch the browser console

After removing a dependency, open the JavaScript console.

Errors such as:

ReferenceError:
SomeLibrary is not defined

or:

TypeError:
Cannot read properties of undefined

can indicate that another script expected the removed dependency.

Console silence does not guarantee success

A feature can fail without producing a clear JavaScript error.

Functional testing still matters.

Review server and application logs too

Frontend script changes normally affect the browser, but related AJAX or REST workflows may expose errors in:

  • WordPress debug logs;
  • PHP logs;
  • web-server logs;
  • plugin logs.

Do not remove scripts solely for SEO

Search engines do care about page experience and performance, but:

one fewer JavaScript file
≠
automatic ranking improvement

Script cleanup is primarily a performance and maintainability exercise.

SEO benefits, if any, come indirectly through better user experience and technical performance.

Security is not simply “fewer scripts = secure”

Removing genuinely unnecessary code reduces software exposure and complexity.

But deleting a frontend script does not fix vulnerabilities in:

  • PHP plugin code;
  • REST endpoints;
  • database operations;
  • authentication;
  • server configuration.

Keep performance cleanup and security remediation conceptually separate.

A safer removal workflow

For every candidate script:

  1. Identify the script in DevTools.
  2. Find its WordPress handle.
  3. Identify the theme or plugin that owns it.
  4. Check whether it is registered or enqueued.
  5. Inspect its dependencies.
  6. Check whether other scripts depend on it.
  7. Identify which templates actually use its feature.
  8. Test interactive code paths.
  9. Check logged-in states if relevant.
  10. Check desktop and mobile.
  11. Prefer fixing the enqueue source where possible.
  12. Otherwise dequeue conditionally.
  13. Avoid deregistering unless necessary.
  14. Clear caches.
  15. Retest the frontend.
  16. Check the console.
  17. Compare performance before and after.
  18. Document the custom rule.

WordPress script-removal checklist

  • Registered scripts are not necessarily downloaded.
  • Enqueued scripts are candidates for frontend output.
  • A registered dependency can be loaded automatically by another script.
  • Do not remove a script without checking its dependency graph.
  • Unused JavaScript in a performance report does not automatically mean the whole script is unnecessary.
  • Test user interactions before interpreting code coverage.
  • Use browser DevTools to identify JavaScript requests.
  • Use the request path to identify the owning theme or plugin.
  • Find the actual WordPress handle before dequeuing.
  • Search source code for wp_enqueue_script() and wp_register_script().
  • Use wp_script_is() to inspect script state.
  • wp_dequeue_script() removes a previously enqueued script from the queue.
  • wp_deregister_script() removes the script registration.
  • Dequeue and deregister solve different problems.
  • Prefer dequeueing when you only want to prevent loading on selected pages.
  • Use a sufficiently late hook priority when removing scripts enqueued by other components.
  • Do not strip script tags from generated HTML when the WordPress enqueue API can manage them.
  • Conditional loading is usually better than global removal.
  • Fix global enqueueing at its source when you control the code.
  • Use conditional tags to load feature-specific assets only where needed.
  • Do not remove jQuery without auditing dependencies.
  • jQuery and jQuery Migrate are separate dependency questions.
  • Do not replace WordPress-managed libraries with CDN copies without understanding compatibility.
  • Audit third-party JavaScript separately.
  • One external script can generate many downstream requests.
  • Removing an unused feature may be better than maintaining dequeue rules.
  • Check plugin settings before writing custom removal code.
  • Traditional scripts and WordPress Script Modules are separate systems.
  • Removing a script and deferring a script are different optimizations.
  • Do not blindly apply defer or async to dependency-sensitive scripts.
  • Do not optimize only the homepage.
  • Check pages, posts, archives, forms and ecommerce templates separately.
  • Test logged-in and logged-out states.
  • Test mobile navigation and touch interactions.
  • Test hidden components such as modals and accordions.
  • Clear all relevant caches after changing script loading.
  • Optimization plugins can obscure original script ownership through concatenation.
  • Plugin updates can change handles and dependency graphs.
  • Document custom dequeue rules.
  • Use staging for risky changes.
  • Check browser console errors after removal.
  • Test real functionality, not only whether the page visually loads.
  • Measure performance before and after each meaningful optimization.

Related guides

Final recommendation

Removing unused WordPress scripts is most effective when it is treated as an asset-architecture problem rather than a hunt for the smallest possible number of JavaScript files.

Start with the actual browser requests.

For every script, determine:

Who owns it?
Why is it loaded?
Which pages need it?
What does it depend on?
What depends on it?
Can the feature be removed?
Can the script be loaded conditionally?
Can it be deferred instead?

If you control the plugin or theme, fix the source so feature-specific JavaScript is enqueued only where the feature exists.

If you do not control the source, use WordPress’s native asset system and conditionally wp_dequeue_script() the known handle after the original component has enqueued it.

Use wp_deregister_script() only when you genuinely need to remove the registration itself, especially when replacing or restructuring a dependency.

Most importantly, never equate:

unused during one performance test

with:

safe to delete everywhere

The best WordPress JavaScript optimization is not the site with the fewest script tags.

It is the site where every remaining script has a clear purpose, loads only where it is required and does not force visitors to download or execute code unrelated to the page they are using.

Simplify your WordPress stack

A modular WordPress toolkit. 104 focused tools.

Ultimately, you can build cleaner workflows, maintain fewer plugins and enable only the features each website actually needs.