wp_register_script ¿múltiples identificadores?

2

Para evitar un bajo rendimiento con varias etiquetas <script> hago concatenación de scripts con regularidad y produzco un solo archivo bundle.min.js JS y 'jsbundle' identifier.

El problema es que las cosas agregadas posteriormente, como los complementos, pueden depender de una o más bibliotecas registradas que están presentes , pero empaquetadas en 'jsbundle' genérico.

¿Hay alguna manera de informar a Wordpress que 'jsbundle' implica, por ejemplo, 'jquery' , 'backbone' , ... para que 1) el recurso no se cargue dos veces 2) las cosas no fallen debido a una dependencia no satisfecha ?

Probé con la fuente de wp_register_script , encontré WP_Scripts() class y traté de "mentir" WP sobre los scripts disponibles, pero no tuve suerte.

    
pregunta Miloš Đakonović 24.10.2017 - 15:31

3 respuestas

4

Para que las bibliotecas de JavaScript no se carguen ya que ya creaste un paquete de ellas, haz lo siguiente:

Asumiendo lo siguiente, encolado habitual:

function the_js() {
    wp_enqueue_script('bundle_js', get_template_directory_uri() . '/js/bundle.js', array(), false, false);
}

add_action('wp_enqueue_scripts', 'the_js');

y digamos que tiene en su paquete las siguientes bibliotecas (con una lista de los controladores):

  1. jquery
  2. backbone
  3. colorpicker
  4. bootstrap_js

1,2,3 ya están en el núcleo, 4 es un tercero, agrupaste los 4 porque no quieres que el 4 se cargue como recursos separados.

Usted debe cancelar el registro (si están registrados, los principales ya lo estarían) y registrar cada uno de ellos, cada una de las bibliotecas que están en su paquete:

function the_js() {
    wp_enqueue_script('bundle_js', get_template_directory_uri() . '/js/bundle.js', array(), false, false);

    //DEREGISTER the SCRIPTS THAT ARE IN YOUR BUNDLE
    wp_deregister_script('jquery'); //because its a Core-Registered Script
    wp_deregister_script('backbone'); //because its a Core-Registered Script
    wp_deregister_script('colorpicker'); //because its a Core-Registered Script

    //REGISTER THEM THIS TIME USING YOUR BUNDLE AS DEPENDENCY
    wp_register_script('jquery', FALSE, array('bundle_js'), '', FALSE);//THE KEY HERE IS THE SRC BEING FALSE
    wp_register_script('backbone', FALSE, array('bundle_js'), '', FALSE);
    wp_register_script('colorpicker', FALSE, array('bundle_js'), '', FALSE);

}

add_action('wp_enqueue_scripts', 'the_js');

la clave aquí es establecer $src como FALSE para que el script registrado sea un alias, verifique esta línea en el código del núcleo:

// A single item may alias a set of items, by having dependencies, but no source.
if ( ! $obj->src ) {
   return true;
}

es lo que hace actualmente jquery , al poner jquery como una dependencia, no carga jquery carga jquery-core y jquery-migrate , este es el objeto registrado para jquery :

object(_WP_Dependency)#329 (6) {
  ["handle"]=>
  string(6) "jquery"
  ["src"]=>
  bool(false)
  ["deps"]=>
  array(2) {
    [0]=>
    string(11) "jquery-core"
    [1]=>
    string(14) "jquery-migrate"
  }
  ["ver"]=>
  string(6) "1.12.4"
  ["args"]=>
  NULL
  ["extra"]=>
  array(0) {
  }
}

por lo tanto, bundle_js se cargará cuando una secuencia de comandos dependa de cualquiera de las bibliotecas ( jquery , backbone , colorpicker ) y se cargará 1 vez, ya que la lógica en WP_Dependencies comprueba si ya está en la matriz queue .

Si desea comprobar si un script ya está registrado, utilice:

global $wp_scripts;
$wp_scripts->query('jquery'); //jquery as example handle

devolverá un objeto WP_dependency si está registrado, false si no lo está.

Algunos enlaces para una mayor comprensión:
class.wp-dependencies.php
class.wp-scripts.php
functions.wp-scripts.php

    
respondido por el David Lee 31.10.2017 - 20:25
0

La solución propuesta por Alexander parece razonable. Puede mantener todas las dependencias minimizadas (libs.js en mi ejemplo) en un archivo y sus scripts en el segundo archivo, de este modo:

wp_enqueue_script( 'libs', get_template_directory_uri() . '/assets/js/libs.js', [], '1.0.0', true );

// third parameter here will make sure that libs.js is loaded before jsbundle:

wp_enqueue_script( 'jsbundle', get_template_directory_uri() . '/assets/js/jsbundle.min.js', [ 'libs' ], '1.0.0', true );

A pesar de que agrupar scripts es una práctica bien conocida para optimizar la velocidad de carga de la página y es una buena idea la mayor parte del tiempo, puede que no siempre sea la solución más eficaz. Siempre consideraría otras opciones y decidiría qué funciona mejor para un caso de uso particular.

CDN

Es posible que desee utilizar uno de los CDN disponibles para sus bibliotecas de terceros para obtener todas las ventajas que se enumeran en en esta respuesta .

Por ejemplo, Si utiliza el CDN de Google o de Facebook, existe una gran posibilidad de que sus visitantes ya tengan scripts populares en caché en sus navegadores y que no necesiten volver a descargarlos.

En ese caso, la combinación de scripts de terceros elimina esta ventaja, y todo el paquete debe descargarse, incluso si el usuario ya tiene una parte guardada en el caché del navegador.

Puede poner en cola fácilmente secuencias de comandos de CDN con wp_enqueue_script() , simplemente omita el parámetro $ver , porque no desea actualizar la secuencia de comandos en caché:

wp_enqueue_script( 'jquery', 'https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js', [], null, true );

Etiquetas condicionales

La otra cosa que consideraría es registrar más scripts y llamarlos solo en las páginas donde realmente se usan. Esto funciona bien, especialmente si actualiza sus scripts a menudo.

Si mantienes todos los scripts en un paquete, la aplicación de unos pequeños cambios requiere el almacenamiento en caché de todo el script. A veces puede ser mejor mantener partes de sus scripts separados, para que pueda cambiar la versión solo por el fragmento que realmente editó.

Digamos que uso el script foo.js en mi página de inicio y no hay mucho que hacer, por lo que no pienso cambiarlo en el corto plazo, pero al mismo tiempo tengo un script bar.js complicado que necesito mantener y actualizar a menudo. En ese caso, podría ser mejor registrar los scripts por separado.

Además, algunas de sus bibliotecas pueden usarse solo en subpáginas que no se visitan con mucha frecuencia (digamos que uso masonry en una subpágina menos popular), por lo que cargarlas en su página de inicio tal vez no sea el camino a seguir. . En ese caso yo haría:     // Registre la mampostería pero aún no la encolar     wp_register_script ('mampostería', get_template_directory_uri (). '/assets/js/masonry.min.js', [], 1.0, true);

// foo.js is my implementation of masonry.js
wp_register_script( 'foo.js', get_template_directory_uri() . '/assets/js/masonry.min.js', [ 'masonry' ], 1.0, true );

// in bar.js I keep functions used all over my page so I enqueue it everywhere immediately
wp_enqueue_script( 'bar.js', get_template_directory_uri() . '/assets/js/masonry.min.js', [], 1.0, true );

// masonry.js and foo.js can wait until the user reaches my less popular subpage as it won't be needed most of the time
if ( is_post_type_archive( 'unpopular-posts' ) ){
    wp_enqueue_script( 'foo.js' );
}
    
respondido por el Levi Dulstein 31.10.2017 - 17:59
0

El intercambio rápido con @janh en mi respuesta anterior me inspiró a pensar en un enfoque diferente. Seguiría minimizando todas las bibliotecas de terceros en un archivo de paquete separado ( bundlejs ), y luego trabajaré con la variable global $wp_scripts (el crédito por esa idea va a este hilo )

Nunca se va a automatizar completamente; como Janh se dio cuenta, es imposible predecir cómo otras personas llamarían los scripts en sus complementos o temas. En mi función, uso una matriz de nombres de script que contiene mi archivo de paquete. Para duplicar las posibilidades de llegar a posibles duplicados, agregué también la compatibilidad con nombres de archivos de script en lugar de solo identificadores.

Tenga en cuenta que algunos scripts de administración no deben tocarse en absoluto (consulte codex )

La solución es bastante simple, estoy seguro de que se puede perfeccionar de muchas maneras, definitivamente se podría usar un poco de refactorización y compatibilidad con caché WP. Además, no estoy seguro de cómo afecta el rendimiento en el caso de la vida real. Pero está aquí para que puedas tener una idea general y quizás algo de inspiración:

function switch_dependencies_to_bundle(){
    global $wp_scripts;

    /**
     * array of scripts that our bundle file contains - can be either script name or handle name
     * it's never going to be bulletproof tho', as plugin authors can change file names, i.e.
     * include other version of script
     */
    $bundled = [
        'jquery',
        'masonry',
        'masonry-js',
        'masonry.js',
        'masonry.min.js', //we can use file name too
        'backbone',
        'backbone.min.js'
    ];

    $deps_to_remove = [];

    // register our bundle script
    wp_register_script( 'bundlejs', get_template_directory_uri() . '/assets/js/bundle.min.js', [], '1.0.0', true );
    wp_enqueue_script( 'bundlejs' );

    // get registered scripts that our bundle file would duplicate
    foreach( $wp_scripts->registered as $handle => $script ){
        $file_name = substr( $script->src , strrpos( $script->src, "/" ) + 1 );
        if ( in_array( $handle, $bundled, true ) || in_array( $file_name, $bundled, true ) ){
            $deps_to_remove[] = $handle;
        }
    }

    //get rid of redundant scripts with deregister and dequeue.
    //NOTE: does not work for some admin scripts, see codex
    foreach( $deps_to_remove as $script ){
        wp_deregister_script( $script );
        wp_dequeue_script( $script );
    }

    // take care of remaining scripts' dependencies (they wouldn't load with deps missing)
    // add our bundle as dependency, as it contains the same scripts that we just removed
    foreach( $wp_scripts->registered as $script ){
        if ( ! empty( array_intersect( $deps_to_remove, $script->deps ) ) ) {
            $script->deps[] = 'bundlejs';
            $script->deps = array_diff( $script->deps, $deps_to_remove );
        }
    }
}

// load the function with high priority so it kickes in after other plugins registered their scripts
add_action('wp_enqueue_scripts', 'switch_dependencies_to_bundle', 9999);
    
respondido por el Levi Dulstein 01.11.2017 - 01:30

Lea otras preguntas en las etiquetas