使用 type="module" 将 javascript 入队

问题描述 投票:0回答:7

我想在 Wordpress 中的自定义主题上使用

countUp.js

当我使用

wp_enqueue_script()
添加文件时,出现错误:

Uncaught SyntaxError: Unexpected token 'export'

我读到它可以在

<script>
标签
type="module"
上进行固定设置,但我不知道该怎么做,因为
wp_enqueue_script()
中不存在该选项...

有人可以帮助我吗?

javascript wordpress es6-modules
7个回答
56
投票

可以通过应用过滤器“script_loader_tag”向脚本添加属性。

使用

add_filter('script_loader_tag', 'add_type_attribute' , 10, 3);
添加过滤器。

定义回调函数,如上面链接中给出的示例:

function add_type_attribute($tag, $handle, $src) {
    // if not your script, do nothing and return original $tag
    if ( 'your-script-handle' !== $handle ) {
        return $tag;
    }
    // change the script tag by adding type="module" and return it.
    $tag = '<script type="module" src="' . esc_url( $src ) . '"></script>';
    return $tag;
}

1
投票

这是一个有点复杂的方法...但是我使用了以下方法来添加延迟,跨域等...

我认为这还不是那么正式,但从我读到的内容来看,这并不是一个坏方法(而且我已经在几个插件的生产中看到了这种方法)。

因此,(调整您的参数/变量以适应显然)需要脚本注册(不仅仅是排队)(参见https://developer.wordpress.org/reference/functions/wp_script_add_data/):

wp_register_script('countup-js', 'https://cdnjs.cloudflare.com/ajax/libs/countup.js/2.0.0/countUp.min.js', ['jquery'], $js_version, true);
wp_enqueue_script('countup-js');

wp_scripts()->add_data('countup-js', 'type', 'module');

然后是你的过滤器(就像这里的最佳答案,但我认为这概述了如何将其设置为更加可重用、灵活等)

add_filter('script_loader_tag', 'moduleTypeScripts', 10, 2);
function moduleTypeScripts($tag, $handle)
{
    $tyype = wp_scripts()->get_data($handle, 'type');

    if ($tyype) {
        $tag = str_replace('src', 'type="' . esc_attr($tyype) . '" src', $tag);
    }

    return $tag;
}


1
投票

为了进一步补充@Zeldri所说的内容,您不需要使用

wp_localize_script()
,我们可以保留该功能用于翻译,因为它最初的目的是。

如果您不想丢失使用

wp_add_inline_script()

添加的代码,以下是您需要的代码
function make_scripts_modules( $tag, $handle, $src ) {
    
            if ( 'your-script-handle' !== $handle ) {
                return $tag;
            }
    
            $id = $handle . '-js';
    
            $parts = explode( '</script>', $tag ); // Break up our string
    
            foreach ( $parts as $key => $part ) {
                if ( false !== strpos( $part, $src ) ) { // Make sure we're only altering the tag for our module script.
                    $parts[ $key ] = '<script type="module" src="' . esc_url( $src ) . '" id="' . esc_attr( $id ) . '">';
                }
            }
    
            $tags = implode( '</script>', $parts ); // Bring everything back together
    
            return $tags;
}
add_filter('script_loader_tag', 'make_scripts_modules' , 10, 3);

这会将所需的脚本转换为模块,并保留内联脚本。


0
投票

我想针对 Paul Naveda 的回答提出一个具体问题。 是的,它可以工作,但是这样你基本上就失去了任何额外的内联脚本。

我的意思是,当使用

wp_add_inline_script()
函数时,它基本上会获取您所提供的内容,并将其添加到当前句柄之前或之后:

wp-includes/class.wp-scripts.php:393(github)

$tag  = $translations . $cond_before . $before_handle;
$tag .= sprintf( "<script%s src='%s' id='%s-js'></script>\n", $this->type_attr, $src, esc_attr( $handle ) );
$tag .= $after_handle . $cond_after;
$tag = apply_filters( 'script_loader_tag', $tag, $handle, $src );

所以通过这样做:

$tag = '<script type="module" src="' . esc_url( $src ) . '"></script>';

您丢失了之前和之后的标签。 为了确保您不会丢失它,请使用

wp_localize_script()
(不过它应该只用于翻译) 或添加这些代码行:

function add_type_attribute($tag, $handle, $src) {
    if ('your_handle_here' === $handle) {
        /** @var WP_Scripts $wp_scripts */
        global $wp_scripts;
        $before_handle = $wp_scripts->print_inline_script( $handle, 'before', false );
        $after_handle  = $wp_scripts->print_inline_script( $handle, 'after', false );
        if ( $before_handle ) {
            $before_handle = sprintf( "<script type='text/javascript' id='%s-js-before'>\n%s\n</script>\n", esc_attr( $handle ), $before_handle );
        }
        if ( $after_handle ) {
            $after_handle = sprintf( "<script type='text/javascript' id='%s-js-after'>\n%s\n</script>\n", esc_attr( $handle ), $after_handle );
        }
        $tag = $before_handle;
        $tag .= sprintf( "<script type='module' src='%s' id='%s-js'></script>\n", $src, esc_attr( $handle ));
        $tag .= $after_handle;
    }
    return $tag;
}
add_filter('script_loader_tag', 'add_type_attribute' , 10, 3);

它保留之前和之后并打印它(如果存在)

请记住,由于

$translations
变量,这仍然不完美,但如果您使用
wp_add_inline_script()

,这是另一种方法

0
投票

对我来说,彼得的答案更简单,所以这纠正了答案存在的问题。

// enqueue the scripts however you like
wp_register_script('countup-js', 'https://cdnjs.cloudflare.com/ajax/libs/countup.js/2.0.0/countUp.min.js', ['jquery'], $js_version, true);
wp_enqueue_script('countup-js');

// explicitly set the type based on the id
wp_scripts()->add_data('countup-js', 'type', 'module');

// add our function to use the explicitly set type.
add_filter('script_loader_tag', 'custom_script_types', 10, 2);
function custom_script_types($tag, $handle) {
    $type = wp_scripts()->get_data($handle, 'type');
        
    if ($type) {
        // only replace the type and nothing else.
        $tag = preg_replace('/ type="(.*?)" /', 
            ' type="' . esc_attr($type) . '" ', 
            $tag);
    }
        
    return $tag;
}

这可以用于其他类型,并且仅替换“类型”并且不会重复它等。

<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/countup.js/2.0.0/countUp.min.js" id="countup-js"></script>

成为

<script type="module" src="https://cdnjs.cloudflare.com/ajax/libs/countup.js/2.0.0/countUp.min.js" id="countup-js"></script>


0
投票

wp_script_attributes
过滤器对此也很方便,而且如果您只需添加一个属性,它会更干净一些。

https://developer.wordpress.org/reference/hooks/wp_script_attributes/

add_filter( 'wp_script_attributes', 'add_type_attribute', 10, 1 );

function add_type_attribute( $attributes ) {
  // Only do this for a specific script.
  if ( isset( $attributes['id'] ) && $attributes['id'] === 'my-handle-js' ) {
    $attributes['type'] = 'module';
  }

  return $attributes;
}

id
来自您在将脚本排队时设置的句柄。格式为
<handle>-js
。在这种情况下,排队可能类似于:

wp_enqueue_script(
  'my-handle',
  'https://cdn.jsdelivr.net/some/url',
  array(),
  null,
  false
);

-1
投票

受到@PaulNaveda、@peter 和@zeldri

的启发

一个演示 JS 模块支持的小插件,包括本地化和内联脚本。


wp-content/plugins/js-module-support-demo/js-module-support-demo.php 的内容

<?php
/*
Plugin Name: Javascript Module Support - Demo
Plugin URI: https://froger.me/
Description: Javascript Module Support - Demo
Version: 0.1
Author: Alexandre Froger
Author URI: https://froger.me/
*/

/* ---------------------------------------------------------------
 * Below is the main logic - it can be used in plugins or a theme
 * --------------------------------------------------------------- */

add_filter( 'script_loader_tag', 'add_type_attribute', 10, 3 );
function add_type_attribute( $tag, $handle, $src ) {
    $type = wp_scripts()->get_data( $handle, 'type' );

    if ( $type && is_string( $type ) ) {
        $tag = str_replace( ' src=', 'type="' . esc_attr( $type ) . '" src=', $tag );
    }

    return $tag;
}

/* ---------------------------------------------------------------------------------------
 * Below is the demo code - it adds the demo scripts (main, module, localization, inline)
 * --------------------------------------------------------------------------------------- */

add_action( 'wp_enqueue_scripts', 'demo_scripts', 10, 1 );
function demo_scripts() {
    $inline_script = '
        console.log(\'this is an inline script added to demo.js\');
    ';

    wp_enqueue_script( 'demo', plugin_dir_url( __FILE__ ) . 'js/demo.js', array(), false, true );
    wp_scripts()->add_data( 'demo', 'type', 'module' );
    wp_add_inline_script( 'demo', $inline_script );
    wp_localize_script( 'demo', 'LocalizationVar', array( 'key' => 'value' ) );
}

内容

wp-content/plugins/js-module-support-demo/js/demo.js

import moduleVar from './module.js'

console.log(moduleVar);
console.log(window.LocalizationVar);

内容

wp-content/plugins/js-module-support-demo/js/module.js

const moduleVar = 'This is a variable from module.js';

export default moduleVar;

执行完整演示代码后,控制台中会显示以下内容:

this is an inline script added to demo.js
This is a variable from module.js
{"key":"value"}
© www.soinside.com 2019 - 2024. All rights reserved.