How to enqueue react resources in WordPress

Sometimes you might need to make a react app built in isolation available to a CMS user of a WordPress site. This might seem like a giant faff. WordPress has it's own React dependancy and tooling now right? Well we're going to ignore all of that and go a super simple option. Taking a built and hosted react app, and making it available as a shortcode by rendering the root element the app expects and enqueueing the built JS and CSS files.

*N.B* These days a shortcode would be an unusual approach for initilisation, and a custom Gutenberg block would be an alternative to consider. However the simplicity of a shortcode does make it useful for demonstrating the approach.

One thing to keep in mind about this approach is that the app will not be running inside of a node environment, so you will need to find your own way to make environment variables available to the app if needed.

Here's the shortcode bit:

add_shortcode( 'my_shortcode', 'my_shortcode_definition' );

function my_shortcode_definition() {
    return '<div id="my-app-root-id"></div>';
}

This will render <div id="my-app-root-id"></div> whenever the shortcode is used: [my_shortcode]. Swap the id value on the div for the root id of your own app.

OK, now we have that, let's get the actual app JS setup for use in WordPress and ensure it is only enqueued when the shortcode is used.

add_action( 'wp_enqueue_scripts', 'enqueue_my_app' );

function enqueue_my_app() {
    global $post;

    if ( has_shortcode( $post->post_content, 'my_shortcode' ) ) {
        $build_directory     = '/path/to/apps/build';
        $build_directory_uri = 'https://example.com/url/to/apps/build';
        $asset_manifest      = json_decode( file_get_contents( $build_directory . '/asset-manifest.json' ) );

        foreach ( $asset_manifest->entrypoints as $entrypoint ) {
            $resource_uri = $build_directory_uri . '/' . $entrypoint;
            if ( str_ends_with( $entrypoint, '.css' ) ) {
                wp_enqueue_style( 'app_styles', $resource_uri, [], '1.0.0' );
            }
            if ( str_ends_with( $entrypoint, '.js' ) ) {
                wp_enqueue_script( 'app_script', $resource_uri, [], '1.0.0', true );
            }
        }
    }
}

This part is a bit more interesting and there are few things happening:

  • Checking whether the current post content contains the app shortcode we created earlier.
  • Creating some necessary file paths and urls so we can get the resources we need.
  • Using the asset-manifest.json file from the react app to get the list of resources we need.
  • Looping over those values and enqueueing them as either JS or CSS based on the file extension.

You'll need to change the obvious bits here to be more relevant for your app, but also you'll especially want to change the $build_directory_uri assignment to be more dynamic. The WordPress/PHP functions you'll want to use here will vary depending on where you're creating this functionality. Here are some links that should give you what you need to make those build directory variables dynamic:

Side note: using the asset-manifest.json to get the react JS and other resources is handy because every time you build the app, the string of characters at the end of the resource file path will be different, so we get automatic cache busting whether you update the enqueue version number or not