Contents
Why split JavaScript by pages?
Performance: delivering only the code that a page needs reduces payload, lowers TTFB and time-to-interactive, and reduces render-blocking. Maintainability: smaller modules are easier to reason about and test. Caching and versions: targeted files change less often, so caches stay valid longer.
How WordPress script loading works (quick fundamentals)
- Use wp_register_script() to register a script handle and path, then wp_enqueue_script() to add it to the page.
- Hook your enqueue logic into the correct action: wp_enqueue_scripts for frontend, admin_enqueue_scripts for admin, login_enqueue_scripts for the login page, enqueue_block_editor_assets for the block editor.
- Conditional template tags (is_page, is_single, is_singular, is_post_type_archive, is_page_template, is_front_page, etc.) only work reliably after the main query is set — i.e. inside the wp_enqueue_scripts hook (or later).
- Provide dependencies (array) and a version number to avoid broken ordering and caching issues. Use filemtime() for automatic cache-busting during development.
- Use the in_footer argument to avoid render-blocking where possible (set true to print before lt/bodygt).
General pattern: register once, enqueue conditionally
The simplest and safest pattern: register all scripts (or at least the common/global ones), then call wp_enqueue_script() only when the conditions match a given page or context.
Basic example: register and conditionally enqueue by slug, template, CPT
Common page conditions and examples
Condition | When to use |
---|---|
is_page( slug_or_id ) | Specific static pages by slug or ID |
is_page_template( template.php ) | When pages use a particular page template |
is_singular( cpt ) | Single post of a custom post type |
is_post_type_archive( cpt ) | Archive page for a CPT |
is_front_page() / is_home() | Homepage or posts page |
is_category() / is_tag() / is_tax() | Taxonomy archive pages |
is_search() / is_404() | Search or 404 pages |
Example: conditionals for taxonomy, archives, and search
Admin, login, block editor and customizer contexts
- Admin: use admin_enqueue_scripts and check hook to limit to particular screens.
- Block editor: use enqueue_block_editor_assets for editor-only scripts (blocks), or enqueue_block_assets for both editor frontend blocks.
- Customizer: use customize_controls_enqueue_scripts and customize_preview_init appropriately.
- Login page: use login_enqueue_scripts for custom login page assets.
Admin example: load only on a plugin settings page
Advanced: asset manifests and hashed/compiled builds
Modern build tools (Webpack, Vite, Rollup) produce hashed filenames. Keep a simple manifest.json and a PHP helper to map logical names to hashed filenames. This ensures you can change chunk names without changing PHP code.
Sample manifest helper and usage
Client-side dynamic imports vs server-side conditional enqueuing
Server-side conditional enqueuing is the canonical approach for WordPress: only output ltscriptgt tags for the pages that need them. However, you can combine that with client-side dynamic imports for even finer-grained lazy-loading inside a page (e.g., loading a heavy modal or chart library only when a user interacts).
Example: JS dynamic import for an on-demand feature
// This script can be enqueued on pages that MIGHT open a modal. // Actual heavy modal code is dynamically loaded only on interaction. document.querySelectorAll([data-open-modal]).forEach(btn => { btn.addEventListener(click, function () { import(./modal.js).then(module => { module.openModal() }).catch(err => { console.error(Failed to load modal:, err) }) }) })
Adding async or defer attributes
WordPress provides helpers to flag scripts as async or defer. Use wp_script_add_data() after registering or enqueuing.
Passing server values to conditional scripts
Use wp_localize_script() or wp_add_inline_script() to pass configuration or URLs to your JS modules (ajax url, nonce, localized strings). Always attach localization to the script handle that will be enqueued conditionally.
admin_url( admin-ajax.php ), nonce => wp_create_nonce( contact_nonce ), strings => array( submit => __( Send message, mytheme ) ), ) ) } ?>
Tips, gotchas and best practices (exhaustive)
- Hook timing: use wp_enqueue_scripts. Conditional template tags will not work if you hook too early (e.g., plugins_loaded or init without a global query).
- Check admin vs frontend: avoid loading frontend scripts in admin and vice versa. Use is_admin() and proper enqueue action hooks.
- Use filemtime() for development: automatic cache-busting while editing. For production hashed filenames or build manifests are better.
- Use dependencies: ensure ordering by listing handles your script needs WordPress will print them in the proper order.
- Load in footer: pass true to wp_enqueue_script to reduce render-blocking.
- Avoid printing too many small files: splitting is good but creating dozens of tiny requests can be counterproductive. Balance splitting and HTTP overhead (HTTP/2 mitigates this).
- Be careful with jQuery: dont deregister core jQuery unless you understand consequences many plugins rely on it.
- Use wp_script_add_data to add defer or async where appropriate.
- Dont use conditional tags in plugins hooked on init to decide frontend enqueueing: use wp_enqueue_scripts or template_redirect for accurate conditions.
- Test plugin/theme interactions: other plugins may expect global scripts document dependencies or include safe fallbacks.
- Security: always pass nonces for AJAX endpoints and escape/sanitize any data passed to script output.
- Editor vs frontend: block editor assets must be enqueued via enqueue_block_editor_assets (or enqueue_block_assets), not wp_enqueue_scripts.
Real-world progressive strategy (step-by-step)
- Audit current pages and identify heavy scripts and features used per page type.
- Group JavaScript into logical bundles: global/common, page-specific, component-specific (modal, charts), editor/admin.
- Update functions.php or plugin code: register global bundle and register page/component bundles.
- Use conditional checks in wp_enqueue_scripts and admin_enqueue_scripts to enqueue only the bundles needed for each context.
- Introduce filemtime() or a manifest for build outputs to handle versioning.
- Test on staging with tools (Lighthouse) and check network tab for unwanted files being loaded.
- Consider client-side dynamic imports for very rarely used, large modules to further shave initial payload.
- Monitor and iterate based on real user metrics (RUM) or analytics for perceived performance improvements.
Example: comprehensive functions.php snippet tying multiple concepts together
admin_url( admin-ajax.php ), nonce => wp_create_nonce( contact ), ) ) wp_script_add_data( theme-contact, defer, true ) } // Product pages: single product if ( is_singular( product ) ) { wp_enqueue_script( theme-product, mytheme_asset_manifest_path( product.js ), array( theme-base ), null, true ) } // Events archive - maybe needs maps if ( is_post_type_archive( events ) ) { wp_enqueue_script( events-archive, mytheme_asset_manifest_path( events.js ), array( theme-base ), null, true ) } } add_action( wp_enqueue_scripts, mytheme_register_and_conditional_enqueue ) ?>
Debugging tips
- Check the page source (view-source) for generated ltscriptgt tags and verify paths/versions.
- Open the network panel and filter by JS to see loaded chunks and their sizes and initiation types (defer/async).
- If a conditional branch isnt firing, ensure your hook is attached at an appropriate time — template tags rely on the query.
- Enable SCRIPT_DEBUG in wp-config.php to avoid minified builds when debugging: define( SCRIPT_DEBUG, true )
- Look for 404s in the network tab — wrong get_template_directory_uri() vs get_stylesheet_directory_uri() mistakes are common.
Checklist before shipping
- All page-specific scripts are enqueued only on pages that need them.
- Common dependencies are properly registered and not duplicated by plugins.
- Versioning is handled (hashed filenames or filemtime during deploy process).
- Scripts are loaded in footer or marked defer/async where safe.
- Localization and nonces are passed only to scripts that need them.
- Editor/admin pages are not loading unnecessary frontend bundles.
Useful links
Final note
Splitting JS by pages in WordPress is a combination of careful registration, correct use of conditional template tags inside the proper hooks, and a build/distribution strategy (filemtime or manifest) for versioning. Follow the patterns above, test thoroughly across pages and devices, and iterate — usually a few targeted splits produce the most worthwhile performance wins without overcomplicating the asset pipeline.
|
Acepto donaciones de BAT's mediante el navegador Brave 🙂 |