Make WordPress Core

Opened 14 months ago

Last modified 5 days ago

#56313 new enhancement

wp_enqueue_script needs to be able to handle modules (ES6/ES2020)

Reported by: idad5's profile idad5 Owned by:
Milestone: Future Release Priority: normal
Severity: normal Version:
Component: Script Loader Keywords: needs-patch
Focuses: javascript, performance Cc:

Description

wp_enqueue_script should be augmented to add scripts with type="module" to pages.
Or a new function like wp_enqueue_module etc. should be created.

Also having the ability to ad a nomodule scrip-tag should be considered, even though ES6 ans ES2020 module support is very wide spread.

Especially ES2020 dynamic modules are a feature that really should be available for theme developers, as it is the best (standard conform) way to handle dynamically loading JS at runtime.

Change History (6)

#1 @costdev
14 months ago

  • Focuses javascript added
  • Keywords 2nd-opinion added
  • Severity changed from major to normal

Hi @idad5, welcome back to Trac!

I think it makes sense that this is in Core territory rather than a third-party plugin. This should be reasonably straightforward. - it can even just be done through filters:

<?php
// In Core, functions.php or a plugin:
add_filter( 'script_loader_tag', 'slug_add_module_support', 999, 2 );
function slug_add_module_support( $tag, $handle ) {
        if ( str_contains( $handle, 'nomodule' ) ) {
                return str_replace( '<script', '<script nomodule', $tag );
        }

        if ( str_contains( $handle, 'module' ) ) {
                if ( current_theme_supports( 'html5', 'script' ) ) {
                        return str_replace( '<script', '<script type="module"', $tag );
                } else {
                        return str_replace( 'text/javascript', 'module', $tag );
                }
        }

        return $tag;
}

// Then when a developer needs to enqueue module and nomodule scripts:
add_filter( 'wp_enqueue_scripts', 'slug_enqueue_scripts' );
function slug_enqueue_scripts() {
        $modules = array(
                'module-say-hello' => '/js/say-hello.js',
                'module-app'       => '/js/app.js',
                'nomodule-app'     => '/js/app.nomodule.js',
        );

        foreach ( $modules as $handle => $src ) {
                wp_enqueue_script( "slug-$handle", get_template_directory_uri() . $src );
        }
}
// say-hello.js
export const sayHello = () => console.log('hello')

// app.js
import { sayHello } from './say-hello.js'
sayHello()

// app.nomodule.js
function sayHello() {
        console.log('hello')
}
sayHello()

For now, I'll add the 2nd-opinion keyword to get some thoughts on the enhancement from other contributors.

#2 @neffff
7 months ago

I came here looking for this! I wanted to add an additional concern/wrinkle. In supporting modules (which as noted can be done with a simple filter). It seems adding support for the `importmap` script type would make this a great addition to the script loader.

This would allow modules to have configurable imports -- enabling sharing modules between front/back ends without having to transpile. I'm sure there are other benefits, but this was the one that sent me looking for that support.

#3 @joemcgill
3 months ago

  • Focuses performance added
  • Keywords needs-patch added; 2nd-opinion removed
  • Milestone changed from Awaiting Review to Future Release

I think we should consider implementing this. Browser support for this is already in a good place. Having an official way to register modules will allow us to dynamically keep unused javascript from being sent to clients.

Related:

#4 follow-up: @joostdevalk
3 months ago

+1 for implementing this in core, find myself working around it.

#5 @thomasprice61
5 weeks ago

+1
Any chance this can be added to the 6.4 scope?

#6 in reply to: ↑ 4 @Latz
5 days ago

+1

Took me almost one hour to find the needed filter ("script_loader_tag") and the code doesn't look too professional neither.

Note: See TracTickets for help on using tickets.