Search code examples
javascriptphpnode.jswordpress

Importing node modules in a WordPress plugin


I'm using wp_register_script and wp_enqueue_script to bring in some custom JavaScript logic for the admin screen of a WordPress plugin I'm developing.

The problem comes when I try to add import statements at the top of my JavaScript in order to bring in a couple node modules. Understandably, this gives me the following browser console message:

import declarations may only appear at top level of a module

What is the standard way to tell WordPress to treat a custom bit of JavaScript as a module? And are there other steps I need to follow in order to make sure that my node modules can be imported?


Solution

  • What is the standard way to tell WordPress to treat a custom bit of JavaScript as a module?

    All you need is type="module" on the <script> tag and the browser will treat this script as ECMAScript module.

    With wordpress, to add the type attribute on a script, first enqueue the script

    function enqueue_plugin_scripts() {
        wp_enqueue_script('module_handle', get_template_directory_uri() . '/path/to/module.js')
    }
    add_action( 'wp_enqueue_scripts', 'enqueue_plugin_scripts' );
    

    Then Add type="module" to module_handle using script_loader_tag hook

    function set_scripts_type_attribute( $tag, $handle, $src ) {
        if ( 'module_handle' === $handle ) {
            $tag = '<script type="module" src="'. $src .'"></script>';
        }
        return $tag;
    }
    add_filter( 'script_loader_tag', 'set_scripts_type_attribute', 10, 3 );
    

    And are there other steps I need to follow in order to make sure that my node modules can be imported?

    You can't use bare import, for example : import $ from "jquery" will fail in the browser. To import from the node_modules, you must provide the full path to the module otherwise the browser will complain with Relative references must start with either "/", "./", or "../"

    Here is some examples:

    This won't work

    import $ from "jquery";
    import Swiper from "swiper";
    

    This will work

    import "./node_modules/jquery/dist/jquery.js" //because jquery doesn't have browser-compatible ES module
    import Swiper from "./node_modules/swiper/js/swiper.esm.browser.bundle.js";
    import Swiper from 'https://unpkg.com/swiper/js/swiper.esm.browser.bundle.min.js'; //from external source
    console.log($, Swiper) //will output jquery and swiper
    

    Here is a good article on ECMAScript modules in browsers