wp-plugin-assets-loading
Register and enqueue WordPress plugin scripts/styles with
Install
npx skills add https://github.com/Lonsdale201/wp-agent-skills/tree/main/plugin-scaffold/wp-plugin-assets-loading
claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install lonsdale201-wp-agent-skills@llmmart
git clone https://github.com/Lonsdale201/wp-agent-skills.git
The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole lonsdale201/wp-agent-skills collection as a plugin from our marketplace. Git is the plain clone.
Skill manifest
WordPress Plugin Asset Loading
Use this skill when adding or reviewing plugin JS/CSS enqueue code. The goal is to load the right asset on the right screen, with a correct dependency graph and modern loading hints.
This skill avoids Gutenberg-specific editor development. It covers general WordPress frontend/admin assets.
When to use this skill
Trigger when ANY of the following is true:
- Code calls
wp_enqueue_script(),wp_register_script(),wp_enqueue_style(),wp_script_add_data(),wp_style_add_data(),wp_register_script_module(), orwp_enqueue_script_module(). - A plugin loads assets on every admin page or every frontend request without checking context.
- The task mentions
defer,async,fetchpriority, script modules, module translations,module_dependencies, inline CSS, asset bloat, or frontend performance. - Code uses legacy IE conditional comments or
wp_style_add_data( $handle, 'conditional', ... ).
Runtime placement
| Context | Hook |
|---|---|
| Frontend scripts/styles | wp_enqueue_scripts |
| Admin scripts/styles | admin_enqueue_scripts |
| Login page assets | login_enqueue_scripts |
| Specific plugin settings page | Check $hook_suffix in admin_enqueue_scripts |
Do not enqueue admin assets globally unless the UI appears globally.
add_action( 'admin_enqueue_scripts', static function ( string $hook_suffix ): void {
if ( 'settings_page_myplugin' !== $hook_suffix ) {
return;
}
wp_enqueue_script(
'myplugin-admin',
plugins_url( 'assets/admin.js', MYPLUGIN_FILE ),
array( 'wp-api-fetch' ),
MYPLUGIN_VERSION,
array(
'in_footer' => true,
'strategy' => 'defer',
'fetchpriority' => 'low',
)
);
} );
Script loading args
Since WP 6.3, the fifth wp_enqueue_script() parameter can be an args array. Since WP 6.9, it also accepts fetchpriority.
Since WP 7.0, it also accepts module_dependencies so a classic script can dynamically import registered script modules.
wp_enqueue_script(
'myplugin-frontend',
plugins_url( 'assets/frontend.js', MYPLUGIN_FILE ),
array(),
MYPLUGIN_VERSION,
array(
'in_footer' => true,
'strategy' => 'defer',
'fetchpriority' => 'low', // 'auto', 'low', or 'high'.
)
);
Guidance:
- Use
in_footer => truefor non-critical frontend behavior. - Use
strategy => 'defer'for scripts that can run after parsing and preserve dependency order. - Use
strategy => 'async'only for independent scripts that do not depend on execution order. - Use
fetchpriority => 'high'rarely, only for scripts that are genuinely critical to initial rendering. - Use
fetchpriority => 'low'for behavior that should not compete with LCP resources. - If a classic script uses
module_dependencies, it must either setin_footer => trueorstrategy => 'defer'; otherwise it can run before the import map exists.
wp_enqueue_script(
'myplugin-admin',
plugins_url( 'assets/admin.js', MYPLUGIN_FILE ),
array( 'wp-api-fetch' ),
MYPLUGIN_VERSION,
array(
'in_footer' => true,
'module_dependencies' => array(
'@wordpress/abilities',
),
)
);
Script modules
For ES modules, use the Script Modules API on WP 6.5+:
wp_enqueue_script_module(
'myplugin/frontend',
plugins_url( 'assets/frontend.js', MYPLUGIN_FILE ),
array(),
MYPLUGIN_VERSION,
array(
'in_footer' => true,
'fetchpriority' => 'low',
)
);
In WP 6.9, wp_register_script_module() and wp_enqueue_script_module() accept an $args array with in_footer and fetchpriority. Feature-detect if supporting older WP:
if ( function_exists( 'wp_enqueue_script_module' ) ) {
wp_enqueue_script_module( 'myplugin/frontend', $src, array(), MYPLUGIN_VERSION );
} else {
wp_enqueue_script( 'myplugin-frontend', $fallback_src, array(), MYPLUGIN_VERSION, array( 'in_footer' => true ) );
}
In WP 7.0, registered script modules can have translations:
wp_register_script_module(
'myplugin/admin',
plugins_url( 'assets/admin.js', MYPLUGIN_FILE ),
array(),
MYPLUGIN_VERSION
);
wp_set_script_module_translations(
'myplugin/admin',
'myplugin',
plugin_dir_path( MYPLUGIN_FILE ) . 'languages'
);
wp_enqueue_script_module( 'myplugin/admin' );
Call wp_set_script_module_translations() after the module is registered. Use wp_set_script_translations() for classic scripts and wp_set_script_module_translations() for script modules.
WordPress 7.1 admin design-system assets
WordPress 7.1 registers wp-theme as both a stylesheet handle and a classic
script handle. They are independent assets that happen to share a handle name
in their respective registries:
- depend on the
wp-themestyle to use the--wpds-*semantic design tokens in wp-admin CSS; - depend on the
wp-themescript when code uses the@wordpress/themepackage and itsThemeProvidercomponent; - prefer WordPress UI components over styling directly against low-level tokens when an appropriate component exists.
wp_enqueue_style(
'myplugin-admin',
plugins_url( 'assets/admin.css', MYPLUGIN_FILE ),
array( 'wp-theme' ),
MYPLUGIN_VERSION
);
wp_enqueue_script(
'myplugin-admin',
plugins_url( 'assets/admin.js', MYPLUGIN_FILE ),
array( 'wp-element', 'wp-theme' ),
MYPLUGIN_VERSION,
array( 'in_footer' => true )
);
Do not enqueue either asset solely because it exists, and do not assume the
stylesheet loads with the script. A ThemeProvider can alter color,
roundness, and control-cursor tokens for its subtree. Render at most one root
provider per document, and still verify contrast for custom seed colors.
Styles and legacy conditionals
WP 6.9 removed support for legacy conditional asset loading for Internet Explorer. Do not use wp_style_add_data( $handle, 'conditional', 'IE' ); in WP 6.9, a stylesheet with conditional data is ignored.
// WRONG on WP 6.9+.
wp_style_add_data( 'myplugin-ie', 'conditional', 'IE' );
// RIGHT - drop legacy IE-only styles, or serve a normal stylesheet if still required.
wp_enqueue_style( 'myplugin-admin', plugins_url( 'assets/admin.css', MYPLUGIN_FILE ), array(), MYPLUGIN_VERSION );
Use the path style data only when the stylesheet is registered and the file path is absolute:
wp_register_style( 'myplugin-small', plugins_url( 'assets/small.css', MYPLUGIN_FILE ), array(), MYPLUGIN_VERSION );
wp_style_add_data( 'myplugin-small', 'path', plugin_dir_path( MYPLUGIN_FILE ) . 'assets/small.css' );
wp_enqueue_style( 'myplugin-small' );
Inline data
Use wp_add_inline_script() for boot data and wp_set_script_translations() for translations. Do not use wp_localize_script() as a generic JSON dump.
wp_add_inline_script(
'myplugin-admin',
'window.mypluginSettings = ' . wp_json_encode( $settings ) . ';',
'before'
);
Critical rules
- Register/enqueue on the correct hook for frontend, admin, or login.
- Gate admin assets by screen using
$hook_suffixorget_current_screen(). - Use script args arrays, not the old boolean-only fifth parameter, when setting strategy/footer/fetchpriority.
- Do not use
asyncon dependency-sensitive scripts. - For classic scripts with
module_dependencies, use footer placement ordefer. - Use the matching translation API:
wp_set_script_translations()for classic scripts,wp_set_script_module_translations()for modules. - Declare
wp-themein the correct registry when using WordPress 7.1 design tokens orThemeProvider; the style and script do not imply each other. - Do not use legacy IE
conditionaldata on styles in WP 6.9+. - Do not put
<script>tags insidewp_add_inline_script(). - Prefer dependencies over manual load ordering.
Common mistakes
// WRONG - loads everywhere in wp-admin.
add_action( 'admin_enqueue_scripts', static function (): void {
wp_enqueue_script( 'myplugin-admin', plugins_url( 'admin.js', __FILE__ ) );
} );
// RIGHT - load only where the screen exists.
add_action( 'admin_enqueue_scripts', static function ( string $hook_suffix ): void {
if ( 'settings_page_myplugin' !== $hook_suffix ) {
return;
}
wp_enqueue_script(
'myplugin-admin',
plugins_url( 'admin.js', __FILE__ ),
array( 'wp-api-fetch' ),
'1.0.0',
array( 'in_footer' => true, 'strategy' => 'defer', 'fetchpriority' => 'low' )
);
} );
// WRONG - dependency-sensitive code with async.
wp_enqueue_script( 'myplugin-app', $src, array( 'jquery' ), '1.0.0', array( 'strategy' => 'async' ) );
// RIGHT
wp_enqueue_script( 'myplugin-app', $src, array( 'jquery' ), '1.0.0', array( 'strategy' => 'defer' ) );
Cross-references
- Run
wp-plugin-architecturefor broader placement of enqueue code inside plugin services. - Run
wp-i18n-auditwhen scripts need translations. - Run
wp-security-auditwhen inline boot data contains user/admin-controlled values. - Run
wp-block-editor-iframe-compatibilityfor assets that must load inside the editor canvas. - Run
wp-interactivity-apiwhenviewScriptModuleimplements reactive block behavior.
What this skill does NOT cover
- Gutenberg/block editor component development.
- Build tooling such as Vite, webpack, or
@wordpress/scripts. - CDN/page-cache strategy.
References
- WordPress 6.9 frontend performance field guide: https://make.wordpress.org/core/2025/11/18/wordpress-6-9-frontend-performance-field-guide/
- WordPress 7.1 design-system theming: https://make.wordpress.org/core/2026/07/31/design-system-theming-in-wordpress-7-1/
- Script APIs:
wp-includes/functions.wp-scripts.php - Script Modules API:
wp-includes/script-modules.php - Style APIs:
wp-includes/functions.wp-styles.php - Official documentation: https://developer.wordpress.org/reference/functions/wp_enqueue_script/
- Official documentation: https://developer.wordpress.org/reference/functions/wp_enqueue_style/
Files (wp-agent-skills)
-
SKILL.md 11 KB
--- name: wp-plugin-assets-loading description: Register and enqueue WordPress plugin scripts/styles with modern loading behavior, including WP 7.1 admin design-system assets, WP 7.0 classic-script module dependencies, script module translations, fetchpriority support, script module args, footer placement, inline style limits, and removal of legacy IE conditional asset support. Covers wp_enqueue_script args strategy/in_footer/fetchpriority/module_dependencies, wp_register_script_module / wp_enqueue_script_module args, wp_set_script_module_translations, wp_script_add_data, wp_style_add_data, dependency handles, conditional enqueueing on the right hook, and avoiding global frontend/admin asset bloat. Use when adding or reviewing plugin JS/CSS enqueue code. metadata: wp-skills-author: "Soczó Kristóf" wp-skills-contact: "mailto:lonsdale201@hotmail.com" wp-skills-plugin: "wordpress" wp-skills-plugin-version-tested: "6.3 - 7.1" wp-skills-wp-version-tested: "7.1" wp-skills-php-min: "7.4" wp-skills-last-updated: "2026-08-20" --- # WordPress Plugin Asset Loading Use this skill when adding or reviewing plugin JS/CSS enqueue code. The goal is to load the right asset on the right screen, with a correct dependency graph and modern loading hints. This skill avoids Gutenberg-specific editor development. It covers general WordPress frontend/admin assets. ## When to use this skill Trigger when ANY of the following is true: - Code calls `wp_enqueue_script()`, `wp_register_script()`, `wp_enqueue_style()`, `wp_script_add_data()`, `wp_style_add_data()`, `wp_register_script_module()`, or `wp_enqueue_script_module()`. - A plugin loads assets on every admin page or every frontend request without checking context. - The task mentions `defer`, `async`, `fetchpriority`, script modules, module translations, `module_dependencies`, inline CSS, asset bloat, or frontend performance. - Code uses legacy IE conditional comments or `wp_style_add_data( $handle, 'conditional', ... )`. ## Runtime placement | Context | Hook | |---|---| | Frontend scripts/styles | `wp_enqueue_scripts` | | Admin scripts/styles | `admin_enqueue_scripts` | | Login page assets | `login_enqueue_scripts` | | Specific plugin settings page | Check `$hook_suffix` in `admin_enqueue_scripts` | Do not enqueue admin assets globally unless the UI appears globally. ```php add_action( 'admin_enqueue_scripts', static function ( string $hook_suffix ): void { if ( 'settings_page_myplugin' !== $hook_suffix ) { return; } wp_enqueue_script( 'myplugin-admin', plugins_url( 'assets/admin.js', MYPLUGIN_FILE ), array( 'wp-api-fetch' ), MYPLUGIN_VERSION, array( 'in_footer' => true, 'strategy' => 'defer', 'fetchpriority' => 'low', ) ); } ); ``` ## Script loading args Since WP 6.3, the fifth `wp_enqueue_script()` parameter can be an args array. Since WP 6.9, it also accepts `fetchpriority`. Since WP 7.0, it also accepts `module_dependencies` so a classic script can dynamically import registered script modules. ```php wp_enqueue_script( 'myplugin-frontend', plugins_url( 'assets/frontend.js', MYPLUGIN_FILE ), array(), MYPLUGIN_VERSION, array( 'in_footer' => true, 'strategy' => 'defer', 'fetchpriority' => 'low', // 'auto', 'low', or 'high'. ) ); ``` Guidance: - Use `in_footer => true` for non-critical frontend behavior. - Use `strategy => 'defer'` for scripts that can run after parsing and preserve dependency order. - Use `strategy => 'async'` only for independent scripts that do not depend on execution order. - Use `fetchpriority => 'high'` rarely, only for scripts that are genuinely critical to initial rendering. - Use `fetchpriority => 'low'` for behavior that should not compete with LCP resources. - If a classic script uses `module_dependencies`, it must either set `in_footer => true` or `strategy => 'defer'`; otherwise it can run before the import map exists. ```php wp_enqueue_script( 'myplugin-admin', plugins_url( 'assets/admin.js', MYPLUGIN_FILE ), array( 'wp-api-fetch' ), MYPLUGIN_VERSION, array( 'in_footer' => true, 'module_dependencies' => array( '@wordpress/abilities', ), ) ); ``` ## Script modules For ES modules, use the Script Modules API on WP 6.5+: ```php wp_enqueue_script_module( 'myplugin/frontend', plugins_url( 'assets/frontend.js', MYPLUGIN_FILE ), array(), MYPLUGIN_VERSION, array( 'in_footer' => true, 'fetchpriority' => 'low', ) ); ``` In WP 6.9, `wp_register_script_module()` and `wp_enqueue_script_module()` accept an `$args` array with `in_footer` and `fetchpriority`. Feature-detect if supporting older WP: ```php if ( function_exists( 'wp_enqueue_script_module' ) ) { wp_enqueue_script_module( 'myplugin/frontend', $src, array(), MYPLUGIN_VERSION ); } else { wp_enqueue_script( 'myplugin-frontend', $fallback_src, array(), MYPLUGIN_VERSION, array( 'in_footer' => true ) ); } ``` In WP 7.0, registered script modules can have translations: ```php wp_register_script_module( 'myplugin/admin', plugins_url( 'assets/admin.js', MYPLUGIN_FILE ), array(), MYPLUGIN_VERSION ); wp_set_script_module_translations( 'myplugin/admin', 'myplugin', plugin_dir_path( MYPLUGIN_FILE ) . 'languages' ); wp_enqueue_script_module( 'myplugin/admin' ); ``` Call `wp_set_script_module_translations()` after the module is registered. Use `wp_set_script_translations()` for classic scripts and `wp_set_script_module_translations()` for script modules. ## WordPress 7.1 admin design-system assets WordPress 7.1 registers `wp-theme` as both a stylesheet handle and a classic script handle. They are independent assets that happen to share a handle name in their respective registries: - depend on the `wp-theme` **style** to use the `--wpds-*` semantic design tokens in wp-admin CSS; - depend on the `wp-theme` **script** when code uses the `@wordpress/theme` package and its `ThemeProvider` component; - prefer WordPress UI components over styling directly against low-level tokens when an appropriate component exists. ```php wp_enqueue_style( 'myplugin-admin', plugins_url( 'assets/admin.css', MYPLUGIN_FILE ), array( 'wp-theme' ), MYPLUGIN_VERSION ); wp_enqueue_script( 'myplugin-admin', plugins_url( 'assets/admin.js', MYPLUGIN_FILE ), array( 'wp-element', 'wp-theme' ), MYPLUGIN_VERSION, array( 'in_footer' => true ) ); ``` Do not enqueue either asset solely because it exists, and do not assume the stylesheet loads with the script. A `ThemeProvider` can alter color, roundness, and control-cursor tokens for its subtree. Render at most one root provider per document, and still verify contrast for custom seed colors. ## Styles and legacy conditionals WP 6.9 removed support for legacy conditional asset loading for Internet Explorer. Do not use `wp_style_add_data( $handle, 'conditional', 'IE' )`; in WP 6.9, a stylesheet with `conditional` data is ignored. ```php // WRONG on WP 6.9+. wp_style_add_data( 'myplugin-ie', 'conditional', 'IE' ); // RIGHT - drop legacy IE-only styles, or serve a normal stylesheet if still required. wp_enqueue_style( 'myplugin-admin', plugins_url( 'assets/admin.css', MYPLUGIN_FILE ), array(), MYPLUGIN_VERSION ); ``` Use the `path` style data only when the stylesheet is registered and the file path is absolute: ```php wp_register_style( 'myplugin-small', plugins_url( 'assets/small.css', MYPLUGIN_FILE ), array(), MYPLUGIN_VERSION ); wp_style_add_data( 'myplugin-small', 'path', plugin_dir_path( MYPLUGIN_FILE ) . 'assets/small.css' ); wp_enqueue_style( 'myplugin-small' ); ``` ## Inline data Use `wp_add_inline_script()` for boot data and `wp_set_script_translations()` for translations. Do not use `wp_localize_script()` as a generic JSON dump. ```php wp_add_inline_script( 'myplugin-admin', 'window.mypluginSettings = ' . wp_json_encode( $settings ) . ';', 'before' ); ``` ## Critical rules - **Register/enqueue on the correct hook** for frontend, admin, or login. - **Gate admin assets by screen** using `$hook_suffix` or `get_current_screen()`. - **Use script args arrays**, not the old boolean-only fifth parameter, when setting strategy/footer/fetchpriority. - **Do not use `async` on dependency-sensitive scripts.** - **For classic scripts with `module_dependencies`, use footer placement or `defer`.** - **Use the matching translation API**: `wp_set_script_translations()` for classic scripts, `wp_set_script_module_translations()` for modules. - **Declare `wp-theme` in the correct registry** when using WordPress 7.1 design tokens or `ThemeProvider`; the style and script do not imply each other. - **Do not use legacy IE `conditional` data** on styles in WP 6.9+. - **Do not put `<script>` tags inside `wp_add_inline_script()`.** - **Prefer dependencies over manual load ordering.** ## Common mistakes ```php // WRONG - loads everywhere in wp-admin. add_action( 'admin_enqueue_scripts', static function (): void { wp_enqueue_script( 'myplugin-admin', plugins_url( 'admin.js', __FILE__ ) ); } ); // RIGHT - load only where the screen exists. add_action( 'admin_enqueue_scripts', static function ( string $hook_suffix ): void { if ( 'settings_page_myplugin' !== $hook_suffix ) { return; } wp_enqueue_script( 'myplugin-admin', plugins_url( 'admin.js', __FILE__ ), array( 'wp-api-fetch' ), '1.0.0', array( 'in_footer' => true, 'strategy' => 'defer', 'fetchpriority' => 'low' ) ); } ); // WRONG - dependency-sensitive code with async. wp_enqueue_script( 'myplugin-app', $src, array( 'jquery' ), '1.0.0', array( 'strategy' => 'async' ) ); // RIGHT wp_enqueue_script( 'myplugin-app', $src, array( 'jquery' ), '1.0.0', array( 'strategy' => 'defer' ) ); ``` ## Cross-references - Run **`wp-plugin-architecture`** for broader placement of enqueue code inside plugin services. - Run **`wp-i18n-audit`** when scripts need translations. - Run **`wp-security-audit`** when inline boot data contains user/admin-controlled values. - Run **`wp-block-editor-iframe-compatibility`** for assets that must load inside the editor canvas. - Run **`wp-interactivity-api`** when `viewScriptModule` implements reactive block behavior. ## What this skill does NOT cover - Gutenberg/block editor component development. - Build tooling such as Vite, webpack, or `@wordpress/scripts`. - CDN/page-cache strategy. ## References - WordPress 6.9 frontend performance field guide: <https://make.wordpress.org/core/2025/11/18/wordpress-6-9-frontend-performance-field-guide/> - WordPress 7.1 design-system theming: <https://make.wordpress.org/core/2026/07/31/design-system-theming-in-wordpress-7-1/> - Script APIs: `wp-includes/functions.wp-scripts.php` - Script Modules API: `wp-includes/script-modules.php` - Style APIs: `wp-includes/functions.wp-styles.php` - Official documentation: <https://developer.wordpress.org/reference/functions/wp_enqueue_script/> - Official documentation: <https://developer.wordpress.org/reference/functions/wp_enqueue_style/>
Comments (0)
Sign in to join the conversation.
Reviews (0)
No reviews yet.
No comments yet.