X

wp enqueue script – Chargement du dernier fichier de module javascript de dépendance dans functions.php


Le problème

Importer une déclaration comme :

import { export1 } from "./module-name.js";

est appelé statique import déclaration.

La chaîne de requête dynamique (pour forcer le chargement du dernier fichier) ne peut pas être utilisée en statique import déclarations. Ainsi, pour résoudre ce problème, vous devrez choisir l’une des quatre options suivantes :

  1. Retirer export et import instructions de tous les fichiers JavaScript et les mettre en file d’attente en tant que JavaScript non-module.

  2. Ne pas mettre en file d’attente ads.js dans WordPress, ne transmettez que le numéro de version de ads.js fichier en tant que variable globale JavaScript avec wp_add_inline_script() fonction à la page, et importer dynamiquement ads.js en tant que module de banners.js et ads-search.js.

  3. Mettre en file d’attente ads.js en tant que module, passez le numéro de version de ads.js fichier en tant que variable globale JavaScript avec wp_add_inline_script() fonction à la page, mise en file d’attente banners.js et ads-search.js comme JavaScript non-module (avec ads.js dans le tableau de dépendances), et importez dynamiquement ads.js en tant que module de banners.js et ads-search.js. Ceci est légèrement différent de l’option 2 et peut présenter certains avantages en fonction de la mise en œuvre.

  4. Utilisez un bundle comme Rollup ou Webpack et créez un seul script minifié à l’aide d’un observateur de fichiers et mettez en file d’attente le fichier JavaScript minifié de construction dans WordPress en tant que fichier JavaScript non-module. Je recommanderais cette méthode, mais je ne l’expliquerais pas ici car elle sort du cadre de cette question.

Option 1 : Rendre tous les fichiers JS non modules

Supprimez simplement export et import déclarations de tous les fichiers JavaScript, comme ci-dessous :

// in ads.js
// removed the export declaration
async function selectADS(adNumber, element, adsArray) {
  let usedNum = [];
  let i = 0;
  while (1) {
    var randomNum = Math.floor(Math.random() * adsArray.length);

    if (!usedNum.includes(randomNum)) {
      let link = document.createElement("a");
      link.setAttribute("href", adsArray[randomNum].link);
      link.setAttribute("target", "_blank");

      let ad = document.createElement("img");
      ad.setAttribute("alt", adsArray[randomNum].alt);
      ad.setAttribute("src", adsArray[randomNum].src);

      element.appendChild(link);
      link.appendChild(ad);

      usedNum.push(randomNum);
      i++;
      if (i == adNumber) break;
    }
  }
}

// in banners.js
// call selectADS function normally, no import declaration
selectADS();

Ensuite, à la fin de WordPress, mettez-les en file d’attente dans my_custom_theme_scripts() comme vous l’avez écrit dans la question.

Option-2 : passer ads.js version en JS et importation dynamique ads.js

Si pour une raison quelconque vous devez garder le export déclaration en ads.jset que vous souhaitez toujours importer le dernier fichier dans banners.js et ads-search.jsvous devrez apporter quelques modifications au code de mise en file d’attente WordPress et au code JavaScript de banners.js et ads-search.js.

Par exemple, votre my_custom_theme_scripts() la fonction peut ressembler à ceci :

function my_custom_theme_scripts() {
    $ads_version = filemtime( get_stylesheet_directory() . '/js/ads.js' );
    $banners_version = filemtime( get_stylesheet_directory() . '/js/banners.js' );

    wp_enqueue_script(
        'banners',
        get_stylesheet_directory_uri() . '/js/banners.js',
        array(),
        $banners_version,
        true
    );
    wp_add_inline_script(
        'banners',
        'const My_Custom_Ads_Version = "' . $ads_version . '";',
        'before'
    );
}

Dans ce cas, ads.js le fichier peut être comme avant avec export déclaration, et banners.js fichier peut dynamiquement import c’est comme ci-dessous:

(async () => {  
    if( typeof My_Custom_Ads_Version !== 'undefined' ) {
        const adsModule = await import( `./ads.js?ver=${My_Custom_Ads_Version}` );
        const selectADS = adsModule.selectADS;
        selectADS();
    }
})();

Vous devrez apporter des modifications similaires à ads-search.js. Après cela, votre code fonctionnera.

Rappelez-vous, dans ce cas export les déclarations peuvent être comme avant (en ads.js), mais les instructions d’importation dans banners.js et ads-search.js devrait être changé de statique import déclaration à la dynamique import déclarations comme indiqué dans le code ci-dessus.

Option 3 : mettre en file d’attente ads.js en tant que module, passer ads.js version en JS et importation dynamique ads.js

Cette option est très similaire à Option 2 au-dessus de. Cependant, l’option-2 importe ads.js en cours d’exécution. Donc, si une implémentation veut retarder l’exécution de ads.js objets de module, mais veut toujours charger le ads.js module avec chargement de page, alors cette implémentation sera préférable.

Pour ce faire, vous devrez d’abord vous connecter à script_loader_tag filtre, pour que WordPress ajoute type="module" dans <script> étiqueter.

Voici un exemple de code WordPress qui l’implémente :

add_filter( 'script_loader_tag', 'my_custom_module_support', PHP_INT_MAX, 2 );
function my_custom_module_support( $tag, $handle ) {
    if( strpos( $handle, 'my_custom_module_' ) === 0 ) {
        if( current_theme_supports( 'html5', 'script' ) ) { 
            return substr_replace( $tag, '<script type="module"', strpos( $tag, '<script' ), 7 );
        }
        else {
            return substr_replace( $tag, 'module', strpos( $tag, 'text/javascript' ), 15 );
        }
    }

    return $tag;
}
function my_custom_theme_scripts() {
    $ads_version = filemtime( get_stylesheet_directory() . '/js/ads.js' );
    $banners_version = filemtime( get_stylesheet_directory() . '/js/banners.js' );

    // we are loading ads.js as a module.
    // my_custom_module_support() function checks any handle
    // that begins with "my_custom_module_" and adds type="modle"
    // to print it as a ES6 module script 
    wp_enqueue_script(
        'my_custom_module_ads',
        get_stylesheet_directory_uri() . '/js/ads.js',
        array(),
        $ads_version,
        true
    );
    wp_add_inline_script(
        'my_custom_module_ads',
        'const My_Custom_Ads_Version = "' . $ads_version . '";'
    );
    wp_enqueue_script(
        'banners',
        get_stylesheet_directory_uri() . '/js/banners.js',
        array( 'my_custom_module_ads' ),
        $banners_version,
        true
    );
}
add_action( 'wp_enqueue_scripts', 'my_custom_theme_scripts' );

Avec cette option également, ads.js le fichier peut être comme avant avec export déclaration, et banners.js et ads-search.js peut dynamiquement import depuis ads.js comme indiqué dans l’option-2 ci-dessus.

Cependant, avec cette option, le navigateur chargera ads.js fichier de module avant son importation dynamique dans banners.js. Ainsi, lorsque l’importation dynamique est effectuée, le navigateur utilise uniquement le fichier déjà chargé.

Dans la plupart des cas, ce n’est pas significatif. Cependant, cela peut être important lorsque vous effectuez l’importation dynamique sur un événement comme le code ci-dessous (surtout si ads.js fichier prend beaucoup de temps à charger):

// sample ads.js code
console.log( 'ads.js loaded:START' );
export async function selectADS( adNumber, element, adsArray ) {
    console.log( 'ads.js as a module loaded' );
};
console.log( 'ads.js loaded:END' );

// banners.js code
console.log( 'banners.js load:START' );

let clicked = false;
document.addEventListener( 'click', async (event) => {   
    if( ! clicked && typeof My_Custom_Ads_Version !== 'undefined' ) {
        const adsModule = await import( `./ads.js?ver=${My_Custom_Ads_Version}` );
        const selectADS = adsModule.selectADS;
        selectADS();
    }
    clicked = true;
});

console.log( 'banners.js load:END' );

Avec cette implémentation, si le ads.js est considérablement volumineux et n’est importé dynamiquement que lors d’un événement, le code devient plus simple sans avoir à attendre le fichier importé.

Cependant, ce n’est pas l’avantage le plus important, car vous pouvez réécrire ce code JS pour l’importer encore plus tôt. L’avantage le plus important de cette implémentation est que vous utilisez un système de mise en cache ou un groupeur qui surveille les modifications du code HTML. Avec cette option, il est plus facile de gérer un tel scénario par opposition à l’option-2 (car avec l’option-2 adj.js n’est pas visible depuis HTML).