Get the list of enqueued/registered scripts for a specific post?

I am exploring how to build a theme where most of the pages are loaded using the Rest API. I can load the index page and from there make GET requests to get posts json data and after build its content in the current page. Basically a SPA, at least to some extent.

The problem comes when trying to load a single post and its scripts/styles. As an example, Gutenberg permits loading a script or/and a style for each registered block using the enqueue_block_assets hook.

I am trying to figure out a way to get the registered styles and scripts url for a specific post. My idea is to register a rest route or a field that returns the url of each script/style. I can then attach each script/style to the DOM, after the single post json data has been mounted.

global $wp_scripts; returns the registered scripts and also the enqueued ones in the current page load. So I could not find a way to get that info specifying the post id from outside the single page load flow.

How can I get the list of enqueued/registered scripts and styles url for any specific post id?

or

Is there a better approach?

1 Answer
1

I’m not familiar with Gutenberg, but as you mentioned it as an example, I assume you didn’t mean “only” Gutenberg.

The wp_enqeue_script() or wp_enqueue_style() functions do not accept arguments regarding posts or pages. The script are registered and rendered globally. If a script is output on certain posts only, then it has to be a native PHP conditional, which is not easy to determine.

One idea would be to include only a index.php file in your theme, and add only wp_head() and wp_footer() in it. Then on each rest request, fetch the content of the real HTML page using wp_remote_get() and run a preg_match_all() to extract all the scripts from that page, and add it to your rest fields. It’s kind of messy, but reliable.

Don’t forget to cache the results in either a transient, or an object cache for increased performance.

Here’s a basic example about how to do so:

// Let's register a new field for returning the script srcs
add_action( 'rest_api_init', 'wpse320065_register_rest_field' );

function wpse320065_register_rest_field() {

    register_rest_field( 
      'post', 
      'your-field-name', 
      [
        'get_callback'    => 'wpse320065_fetch_post_cont',
        'schema'          => null,
      ]
    );
}

// Callback function to actually retrieve the data
function wpse320065_fetch_post_cont( $object ) {

    // Get the id of the post object array
    $post_id = $object['id'];

    // Let's get the content of post number 123
    $response = wp_remote_get( "http://example.com/?p={$post_id}" );

    if ( is_array( $response ) ) {

      $content = $response['body'];

      // Extract the src attributes. You can also use preg_match_all
      $document = new DOMDocument();
      $document->loadHTML( $content );

      // An empty array to store all the 'srcs'
      $scripts_array = [];

      // Store every script's source inside the array
      foreach( $document->getElementsByTagName('script') as $script ) {
        if( $script->hasAttribute('src') ) {
          $scripts_array[] = $script->getAttribute('src');
        }
      }
    }

    return $scripts_array

}

Leave a Comment