Inicio - Documentación - POM Theme - 11 Developers - Load assets only where they are needed

Load assets only where they are needed

POM exposes a conditional asset registry so components can request a known frontend handle or feature instead of loading every optional stylesheet and script on every page. WordPress remains responsible for dependency resolution, localization, inline code, script translations, and final HTML output.

What site owners and editors should expect

The loading decision is automatic. A Page Builder component, shortcode, WooCommerce template, or supported plugin declares the feature it needs when it renders. Pages that do not use that feature do not request its files.

Examples include Modal, Tooltip, Datepicker, PhotoSwipe, Isotope, accordion behavior, post likes, Quick View, and Bootstrap ScrollSpy. Cached signed-out pages and dynamic signed-in pages use the same feature declarations.

Public helpers

Helper Purpose
pom_get_conditional_front_asset_registry() Return the request-local normalized conditional handle registry
pom_get_conditional_front_asset_feature_map() Return the request-local feature-to-handle mappings
pom_require_front_asset( string $handle ) Require one registered conditional handle
pom_require_front_assets( array $handles ) Require several registered conditional handles
pom_require_front_asset_feature( string $feature ) Require every handle associated with a feature
pom_maybe_enqueue_block_scripts( ... ) Resolve scripts declared by a component
pom_maybe_enqueue_block_styles( ... ) Resolve styles declared by a component
pom_maybe_enqueue_block_assets( ... ) Resolve both scripts and styles

Use a feature when the component needs a complete group of scripts and styles:

if (function_exists('pom_require_front_asset_feature')) {
    pom_require_front_asset_feature('modal');
}

Only registered handles and features are accepted. The built-in feature slugs are jarallax, photoswipe, isotope, datepicker, tooltip, modal, collapse, tabs, accordion, scrollspy, feed_fullpage, share, page_nav, author_page, rating, advanced_filters, social_icons, woocommerce_product_modal, woocommerce_quick_view, request_info_popup, form_controls, header_sign_form, post_display_rules, and post_likes.

Register an integration asset

A plugin or child theme can extend the registry and feature map. Register both filters before wp_enqueue_scripts; POM normalizes and reuses one snapshot for the rest of the request.

add_filter(
    'pom_conditional_front_asset_registry',
    static function (array $registry): array {
        $registry['styles']['example-panel-style'] = array(
            'uri'   => plugins_url('assets/panel.css', __FILE__),
            'deps'  => array(),
            'media' => 'all',
        );

        $registry['scripts']['example-panel-script'] = array(
            'uri'      => plugins_url('assets/panel.js', __FILE__),
            'deps'     => array('web-theme-js'),
            'footer'   => true,
            'strategy' => 'defer',
        );

        return $registry;
    }
);

add_filter(
    'pom_conditional_front_asset_feature_map',
    static function (array $features): array {
        $features['example_panel'] = array('example-panel-style', 'example-panel-script');

        return $features;
    }
);

Use different handles for separate script and stylesheet resources. A handle must not appear in both registry sections.

Traditional WordPress enqueueing remains supported. After POM registers a handle, a plugin may call wp_enqueue_script() or wp_enqueue_style() directly. Do not create a second browser-side dependency loader for these handles.

Choose safe delivery metadata

Styles that control geometry, visibility, responsive layout, or the initial appearance must use normal stylesheet delivery. This includes visible form controls, inline calendars, Modal structure, and other component CSS that would cause a flash or layout shift if it arrived late.

A stylesheet may declare load_strategy => 'preload' only when it cannot change the initial visual state. POM then emits preload/onload markup and a noscript stylesheet fallback. fetchpriority may be high, low, auto, or empty.

A script may declare WordPress's strategy => 'defer' or strategy => 'async'. Keep dependency order in mind: use async only for a resource that is truly independent.

$registry['styles']['example-enhancement'] = array(
    'uri'           => plugins_url('assets/enhancement.css', __FILE__),
    'load_strategy' => 'preload',
    'fetchpriority' => 'low',
    'media'         => 'all',
);

If a renderer requests a stylesheet after the head has already been printed, POM prints it once in the footer with its WordPress dependencies. This is a compatibility fallback, not a substitute for declaring visible component requirements during discovery.

PhotoSwipe loading

PhotoSwipe is the intentional exception to direct runtime enqueueing. A page with an enlargable POM gallery loads a small, feature-specific loader. That loader starts downloading PhotoSwipe CSS and JavaScript on pointer down or keyboard focus and reuses the same Promise when the image is opened. The complete PhotoSwipe runtime is not loaded on pages without a compatible gallery.

This behavior belongs to the PhotoSwipe loader itself. It does not expose or require a general-purpose interaction asset API.

Datepicker and Tooltip after AJAX insertion

Pages that can initially render or later insert Datepicker or Tooltip markup must require the corresponding feature in the parent document. An AJAX response cannot add a stylesheet to a head that the browser has already received.

After inserting compatible markup, emit pom:ajaxComplete with the narrow inserted container:

document.dispatchEvent(new CustomEvent('pom:ajaxComplete', {
    detail: {
        container: insertedContainer,
        scope: insertedContainer,
        source: 'example_results'
    }
}));

The conditional Datepicker and Tooltip runtimes initialize only that scope and ignore elements that were already initialized. Visible inline datepickers reserve their expected geometry in the main stylesheet to reduce layout movement while the runtime initializes.

Add ScrollSpy to a template or archive

Bootstrap ScrollSpy is not part of theme.min.js. Require it only on a document that contains the matching navigation and scroll container:

if (function_exists('pom_require_front_asset_feature')) {
    pom_require_front_asset_feature('scrollspy');
}

The web-bootstrap-scrollspy handle depends on web-bootstrap-util. Util already lives in the shared theme bundle, so this dependency does not download another copy. A plugin may also enqueue web-bootstrap-scrollspy through the traditional WordPress API.

Keep using Bootstrap's data-spy="scroll", data-target, and navigation-link contract. POMScrollSpy.init(scope, config) initializes a document or inserted scope, POMScrollSpy.refresh(scope) recalculates existing instances after layout changes, and POMScrollSpy.dispose(scope) removes their listeners.

Fenómenus category navigation owns its separate archive navigation behavior and does not require this Bootstrap feature.

Open a built-in modal

Require the Modal feature in PHP and keep Bootstrap's standard data attributes:

if (function_exists('pom_require_front_asset_feature')) {
    pom_require_front_asset_feature('modal');
}
<button type="button" data-toggle="modal" data-target="#example-modal">
    Open
</button>

<div id="example-modal" class="modal" tabindex="-1" role="dialog" aria-hidden="true">
    <div class="modal-dialog" role="document">
        <div class="modal-content">...</div>
    </div>
</div>

POM conditionally enqueues the Modal stylesheet and Bootstrap behavior in the initial document. Automatic, delayed, scheduled, tab-return, open-only-once, backdrop, Escape, focus, dismiss, and programmatic Bootstrap behaviors remain available. Non-native elements using role="button" retain Enter and Space activation through the conditional Modal data API.

Discovery, caching, and regeneration

POM can build per-post and per-request discovery manifests from builder and template content. A renderer must still call the matching asset helper as a fallback because saved discovery data can be stale or a template can render conditionally.

POM Cache may store the final tags like any other part of the static HTML. The asset registry contains no visitor-specific state. Personalized account, cart, checkout, permission-controlled, and other dynamic responses keep their normal cache boundaries.

When a compiled theme resource changes, rebuild the theme assets, regenerate affected site assets, and purge the relevant page/CDN caches as part of the normal release process. Do not deploy changed compiled files under an unchanged public theme version.

Verification

For every conditional integration:

  1. Verify the page that contains the component requests every required handle once.
  2. Verify a page without the component does not request those handles.
  3. Test signed-out cached and signed-in dynamic requests.
  4. Test keyboard behavior and any no-JavaScript fallback the action requires.
  5. For dynamic results, insert the fragment, emit the scoped completion event, and verify existing components are not initialized twice.
  6. Check automatic Modal and visible inline Datepicker behavior separately because neither may wait for user interaction.