wp_enqueue_script Dependencies and What Breaks Without Them

A missing dependency makes WordPress drop your script tag with no warning. How $deps, handles, defer and versions really work, and how to debug it.

You wrote a script that uses jQuery, the browser says $ is not a function, and the page source shows your file loading before jQuery. Or worse, your file is not in the page at all.

The short answer: list every script your file needs in the third argument of wp_enqueue_script, the $deps array, and WordPress prints those handles first. If any handle in that array is not registered, WordPress silently drops your script tag, with no warning and no error. Most “my script loads in the wrong order” and “my script vanished” reports come down to one of those two facts.

The rest of this article is about the second one, because it is the one nobody expects.

What the $deps argument actually does

The function signature, as shown in the WordPress developer reference for wp_enqueue_script (read 2026-09-11, changelog running through WordPress 7.0.0; the current release is 7.1):

wp_enqueue_script( string $handle, string $src = '', string[] $deps = array(), string|bool|null $ver = false, array|bool $args = array() )

The reference describes $deps as “An array of registered script handles this script depends on.” Two words in that sentence do all the work.

Handles, not file names. You pass 'jquery', the name WordPress registered the library under, not a URL and not jquery.min.js. A dependency is a relationship between names in WordPress’s script registry.

Registered. A handle only counts if something has registered it by the time scripts are printed. WordPress core registers its bundled libraries for you. Anything else, including a script from another plugin, has to be registered by that plugin first.

When the dependencies are satisfied, WordPress sorts the output so every dependency prints before the script that needs it. You do not control order by the sequence of your wp_enqueue_script calls. You control it through $deps.

A typical front-end enqueue, composed from that signature:

add_action( 'wp_enqueue_scripts', 'acme_enqueue_assets' );

function acme_enqueue_assets() {
    wp_enqueue_script(
        'acme-slider',
        plugins_url( 'js/slider.js', __FILE__ ),
        array( 'jquery' ),
        '1.4.0',
        array( 'in_footer' => true, 'strategy' => 'defer' )
    );
}

The silent failure: an unmet dependency drops your script

This is the sentence from the reference that explains most of the confusing bug reports: “If dependencies (3rd argument) are not met, the script tag is just not printed and no warnings nor errors are shown.”

Read it again. The script you enqueued is not printed late, or printed with a console warning. It is not printed at all.

A typo in a dependency handle removes your script from the page without a single message. array( 'jQuery' ) instead of array( 'jquery' ), or a dependency on a handle from a plugin that is deactivated on this site, or a dependency on a handle that another plugin registers only on certain screens. Each produces the same symptom: your code simply is not there.

It gets harder to see because the failure cascades. If script B depends on A, and A has an unmet dependency, A is dropped, so B’s dependency is now unmet, so B is dropped too. One wrong handle at the bottom of a chain can remove a whole bundle.

This is a textbook silent failure: no error, just behavior that is missing. The general approach for that class of bug, checking your assumptions at each step instead of waiting for a crash, is covered in debugging code that runs but gives the wrong result.

When the error does appear, it points at the wrong file

Sometimes the dependency is met, but the order is still wrong for the code. The classic case: your script uses jQuery or a global from another library, you never listed it in $deps, and on this particular page your file happens to print first.

The browser then reports something like Cannot read properties of undefined or $ is not a function inside your file, on a line that is perfectly correct. The bug is not on that line. It is in the PHP call that enqueued the file without declaring what it needs. How to find which value is undefined, and why, is in finding which property is undefined in JavaScript, and the broader pattern of a reported line that is innocent is explained in why the error line is often not where the bug is.

The fix is always the same: add the handle your code uses to $deps, even if it “already works” on your test page. Implicit order is an accident that holds until a different plugin changes what loads first.

Hooks: enqueue at the right moment

The reference is direct about where the call belongs: “The function should be called using the wp_enqueue_scripts action hook if you want to call it on the front-end of the site.” For admin screens it is admin_enqueue_scripts, and for the login screen login_enqueue_scripts. It also warns that “Calling it outside of an action hook can lead to problems.”

The common version of that problem is calling it too early, at plugin load time, before WordPress is ready to track scripts, or too late, after the head has already printed. Where those hooks sit relative to everything else in a request is laid out in the WordPress execution order.

Registering versus enqueueing, and the handle collision

wp_enqueue_script registers and enqueues in one call. The reference puts it this way: it “Registers the script if $src provided (does NOT overwrite), and enqueues it.”

“Does NOT overwrite” matters more than it looks. If another plugin has already registered the same handle, your $src is ignored and their file loads under your name. A generic handle such as 'slider' or 'main' is an invitation for this. Prefix every handle you register: 'acme-slider', not 'slider'.

Registering separately is still useful. Register a script once, early, and enqueue it only on the screens that need it. Dependencies declared at registration travel with the handle.

The other arguments that decide what breaks

$ver. Per the reference, false appends the current WordPress version and null appends nothing. With false, the version on your file’s URL only changes when WordPress itself updates, so a browser or CDN may keep serving your old script after you deploy a new one. Pass your plugin’s own version string and bump it when the file changes.

$args['strategy']. Since WordPress 6.3, $args accepts 'defer' or 'async'. The reference states that deferred scripts “are executed in the same order they were printed/added in the DOM”, while asynchronous scripts “do not have a guaranteed execution order.” If your script has dependencies, or other scripts depend on it, async is the wrong choice: order is exactly what you are giving up.

$args['in_footer']. Defaults to false. Moving a script to the footer is fine, but it has to be consistent with what depends on it. A head script that needs a footer script is a dependency WordPress has to resolve, and it is cleaner not to create that shape at all.

The same reference records two newer keys: fetchpriority (since 6.9) and module_dependencies (since 7.0). If you are reading older tutorials, they will not mention either.

Passing data to a script without breaking order

A frequent reason for load-order hacks is needing a PHP value in JavaScript: an AJAX URL, a nonce, a setting. The reference for wp_add_inline_script (read 2026-09-11) shows the signature:

wp_add_inline_script( string $handle, string $data, string $position = 'after' ): bool

Attach the data to your own handle with 'before', and it prints immediately ahead of your file, wherever WordPress ends up placing it. The reference notes the code only runs if the script is already queued, so call it after the enqueue.

Styles follow the same rules

wp_enqueue_style (reference read 2026-09-11, function since WordPress 2.6.0) takes $deps in the same position, described as “An array of registered stylesheet handles this stylesheet depends on.” The fifth argument is $media instead of $args. If your stylesheet must override another one, declare that other handle as a dependency so yours prints after it, rather than raising selector specificity until it wins.

How to debug a missing or misordered script

Work from the registry, not the page.

  1. View the page source and search for your handle. WordPress prints an id on script tags derived from the handle. Not there at all points to an unmet dependency or an enqueue that never ran. There but in the wrong place points to a missing entry in $deps.
  2. Ask WordPress what it knows. wp_script_is (reference read 2026-09-11) accepts a status of 'enqueued', 'registered', 'queue', 'to_do' or 'done'. Check each of your dependencies with 'registered' on the same hook where you enqueue. A false is your culprit.
  3. Check the handle spelling character by character. Handles are exact strings.
  4. Check whether the dependency is conditional. A plugin that registers its script only on its own settings screen will satisfy your dependency there and nowhere else.
  5. Only then look at your JavaScript. If the tag prints in the right order and the code still fails, the problem has finally moved into the file itself.

FAQ

Why is my enqueued script not showing up at all? The most likely cause is an unmet dependency. The WordPress reference states that if dependencies are not met, the script tag is not printed and no warnings or errors are shown. Check every handle in $deps with wp_script_is( $handle, 'registered' ).

Does the order of my wp_enqueue_script calls control load order? No. Output order is decided by the $deps array. Declare what each script needs and WordPress sorts the tags so dependencies print first.

Should I use async or defer for a script with dependencies? Use defer, available since WordPress 6.3. The reference says deferred scripts run in the order they were printed, while async scripts have no guaranteed execution order, which breaks any dependency relationship.

Why does my old JavaScript keep loading after I deploy? If $ver is false, WordPress appends its own version number, which does not change when your file does. Pass your plugin’s version string and bump it on each release.

Written by

Shah Alom

Shah Alom is the founder and writer behind Ebuhu, where he covers PHP, WordPress development, plugin and theme development, debugging, practical programming techniques, and AI-assisted coding. Drawing on hands-on web development experience, he focuses on clear, practical guidance that helps developers understand how things work, avoid common mistakes, and write more reliable code.

Leave a Reply

Your email address will not be published. Required fields are marked *