How do you enqueue script tags for ReactDOM in WordPress’ functions.php?

I’m torn where the best place for this question to go but when researching the React crossorigin purpose I found the answer on MDN:

crossorigin
Normal script elements pass minimal information to the
window.onerror for scripts which do not pass the standard CORS checks.
To allow error logging for sites which use a separate domain for
static media, use this attribute. See CORS settings attributes for a
more descriptive explanation of the valid arguments.

— MDN

and in looking at using ReactDOM I’ve seen the script tags at the bottom of:

<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<script>window.ReactDOM || document.write('<script crossorigin src="path/to/react-dom.development.js"><\/script>')</script>

In WordPress I am familiar with a basic enqueue:

function theme_js() {
    wp_enqueue_script( 'bootstrap_js', get_template_directory_uri() . '/js/bootstrap.min.js', array( 'jquery' ), '1.0', true );
}
add_action( 'wp_enqueue_scripts', 'theme_js' );

and with WordPress I’ve attached scripts to the footer with:

function inline_script() {
    ?>
    <script type="text/javascript">
    // js code goes here
    </script>
    <?php
}
add_action( 'wp_footer', 'inline_script' );

When running a query through previous questions with the params of [wordpress] crossorigin I didn’t see this question asked. Is there a proper way to code for ReactDOM in a WordPress theme besides calling it in the footer with something like:

function react_dom() {
    ?>
        <script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
        <script>window.ReactDOM || document.write('<script crossorigin src="https://wordpress.stackexchange.com/questions/302526/<?php get_template_directory_uri() ?>/react-dom.development.js"><\/script>')</script>
    <?php
}
add_action( 'wp_footer', 'react_dom' );

How should ReactDOM be wp_enqueue_scripts or should it be added to the footer?


For reference this was mentioned in chat: How to add defer=“defer” tag in plugin javascripts?

1 Answer
1

So I’m thinking you can use the script_loader_tag filter to replace HTML as the script is being loaded in. This will allow you to control where you’re enqueueing the script as usual via wp_enqueue_scripts hook while still allowing you to add in any script attributes.

The Enqueue

/**
 * Enqueue whatever script we may need
 *
 * @return void
 */
function wpse302526_enqueue_react() {

    wp_enqueue_script(
        'react',    // File handle/slug
        $file_url,      // URL to file
        array(),        // Dependencies
        false,          // Version
        true            // Add to Header ( false ) or Footer ( true )
    );

}
add_action( 'wp_enqueue_scripts', 'wpse302526_enqueue_react' );

We’ll target the script specifically by the handle/script slug.

The Find / Replace

/**
 * Modify the enqueue script tag
 *
 * @param String $html      - Generated script HTML
 * @param String $handle    - Script slug/handle
 *
 * @return $html
 */
function wpse302526_modify_script_tags( $html, $handle ) {

    /** Add script attribute **/
    if( 'react' === $handle ) {

        /* Add `crossorigin` attribute */
        $html = str_replace(
            '<script',
            '<script crossorigin',
            $html
        );

        /* Initialize ReactDOM */
        $html = str_replace(
            '</script>',
            'window.ReactDOM</script>',
            $html
        );

    }

    return $html;

}
add_filter( 'script_loader_tag', 'wpse302526_modify_script_tags', 10, 2 );

I feel like if you can you should avoid doing this part outside your enqueue as it could be confusing to any developers who run across it. Keeping all your enqueues and script URLs in one place ( instead of torn between the two filters ) seems for the best. If you can’t avoid it then feel free to add it in.

document.write('<script crossorigin src="https://wordpress.stackexchange.com/questions/302526/<?php get_template_directory_uri() ?>/react-dom.development.js"><\/script>')

If you absolutely need the above line, then I would go with the wp_footer approach to keep everything in one place.

Leave a Comment