Soluzioni per la generazione di JavaScript / CSS dinamici


15

Diciamo che è necessario generare codice javascript o CSS che dipende dal contesto corrente.

Ad esempio, nella pagina iniziale è presente un modulo che genera una richiesta Ajax al momento dell'invio e un modulo diverso nella singola pagina. O nel caso dei CSS, vuoi creare un tema che consenta ai suoi utenti di costruire il proprio layout, cambiare i colori ecc.

Soluzioni che vedo finora:

  1. Includi il codice nella sezione head del documento (o alla fine nel caso di JS)

  2. Esegui una richiesta speciale che genera il codice, ad esempio site.com?get_assets . Questo è lento perché WP viene caricato due volte.

  3. Conservalo in file temporanei per un certo periodo di tempo e caricalo da lì. Non molto affidabile per temi o plugin pubblici.

  4. Solo Javascript: rendilo statico inserendolo in un normale file che viene caricato ogni volta. In questo caso dovresti fare in modo che il tuo codice gestisca qualsiasi situazione

Conosci altri? In che direzione andresti?


un problema che ho riscontrato con la soluzione 1 è la memorizzazione nella cache da parte del browser, il codice non viene aggiornato al ricaricamento della pagina.
Aurovrata,

Risposte:


9

Un'opzione aggiuntiva, a seconda del tipo di parametri che devi passare. Chiamiamola (2a). Puoi anche creare script PHP che generano dinamicamente text/csso text/javascriptpiuttosto che text/htmle fornire loro i dati di cui hanno bisogno usando i parametri GET piuttosto che caricando WordPress. Naturalmente questo funziona solo se è necessario passare un numero relativamente piccolo di parametri relativamente compatti. Quindi, ad esempio, supponi di dover passare solo l'URL di un post o la directory di un file o simili, puoi fare qualcosa del genere:

In header.php:

 <script type="text/javascript" src="<?php print get_stylesheet_directory_uri(); 
 ?>/fancy-js.php?foo=bar&amp;url=<?php print urlencode(get_permalink($post->ID)); ?>"></script>

In fancy-js.php:

 <?php
 header("Content-type: text/javascript");
 ?>
 foo = <?php print json_encode($_GET['foo']); ?>;
 url = <?php print json_encode($_GET['url']); ?>;

eccetera.

Ma questo ti consente solo di accedere ai dati passati direttamente nei parametri GET; e funzionerà solo se il numero di cose che devi passare è relativamente piccolo e la rappresentazione di quelle cose è relativamente compatta. (Fondamentalmente una manciata di valori stringa o numerici - un nome utente, per esempio, o una directory; non un elenco di tutti i post recenti di un utente o qualcosa del genere.)

Per quanto riguarda quale di queste opzioni sia la migliore - non lo so; dipende dal caso d'uso. L'opzione (1) ha il merito di essere semplice e di consentire chiaramente l'accesso a tutti i dati WordPress di cui potresti aver bisogno, senza il colpo di prestazioni del caricamento di WordPress due volte. È quasi certamente quello che dovresti fare a meno che tu non abbia una forte ragione per non farlo (ad esempio a causa delle dimensioni del foglio di stile o dello script che devi usare).

Se la dimensione diventa abbastanza grande da causare un problema in termini di peso della tua pagina, puoi provare (2) o (2a).

Altrimenti, questa è probabilmente l'idea migliore, puoi provare a separare le parti dello script o il foglio di stile che utilizzano effettivamente i dati dinamici dalle parti che possono essere specificate staticamente. Puoi dire che hai un foglio di stile che deve passare una directory da WordPress per impostare un parametro di sfondo per l'elemento # my-fancy. Potresti mettere tutto questo nell'elemento head:

 <style type="text/css">
 #my-fancy-element {
      background-image: url(<?php print get_stylesheet_directory_uri(); ?>images/fancy.png);
      padding: 20px;
      margin: 20px;
      font-weight: bold;
      text-transform: uppercase;
      font-size: 12pt;
      /* ... KB and KB of additional styles ... */
 }
 #another-fancy-element {
     /* ... KB and KB of additional styles ... */
 }
 /* ... KB and KB of additional styles ... */
 </style>

Ma perché dovresti farlo? C'è solo una riga qui che dipende dai dati di WordPress. Meglio dividere solo le linee che dipendono da WordPress:

 <style type="text/css">
 #my-fancy-element {
      background-image: url(<?php print get_stylesheet_directory_uri(); ?>images/fancy.png);
 }
 </style>

Inserisci tutto il resto in un foglio di stile statico che carichi con un elemento di collegamento standard (style.css o altro):

 #my-fancy-element {
      /* background-image provided dynamically */
      padding: 20px;
      margin: 20px;
      font-weight: bold;
      text-transform: uppercase;
      font-size: 12pt;
      /* ... KB and KB of additional styles ... */
 }
 #another-fancy-element {
     /* ... KB and KB of additional styles ... */
 }
 /* ... KB and KB of additional styles ... */

E lascia che la cascata faccia il lavoro.

Lo stesso vale per JavaScript: anziché farlo:

 <script type="text/javascript">
 // Here comes a huge function that uses WordPress data:
 function my_huge_function () {
     // Do a million things ...

     jQuery('#my-fancy').append('<a href="'+<?php json_encode(get_permalink($GLOBALS['post']->ID)); ?>+'">foo</a>);

     // Do a million more things ...

     my_other_function(<?php print json_encode(get_userdata($GLOBALS['post']->post_author); ?>);
 }

 function my_other_function (user) {
     // Do a million things ...
 }
 </script>

Metti invece qualcosa di simile nell'elemento head:

 <script type="text/javascript">
 var WordPressPostData = {
 url: <?php print json_encode(get_permalink($GLOBALS['post']->ID)); ?>,
 author: <?php print json_encode(get_userdata($GLOBALS['post']->post_author)); ?>
 }
 </script>

Quindi rilascia il resto in un file JavaScript statico, riscrivendo my_huge_function () e my_other_function () per utilizzare i globali WordPressPostData.url e WordPressPostData.author.

40K di CSS o 40K di JS possono quasi sempre essere suddivisi in <1K che in realtà dipende da dati dinamici, e il resto, che può essere specificato in un file esterno statico e quindi ricombinato utilizzando la cascata (per CSS) o accessibile a livello globale variabili (globuli, elementi DOM o qualsiasi altro cubby-hole che preferisci, per JS).


Risposta brillante!
scribu,

2
Solo una piccola aggiunta: nel caso di JS, possiamo usare wp_localize_sciprt per aggiungere variabili dinamiche.
Anh Tran,

6

Il caso CSS dinamico è abbastanza semplice.

Basta creare una funzione che genera le definizioni CSS dinamiche all'interno dei <style type="text/css"></style>tag, quindi agganciarla wp_print_styles. per esempio

<?php
function mytheme_dynamic_css() {
    $options = get_option( 'mytheme_options' );
    ?>
    <style type="text/css">
    /* Dynamic H1 font family */
    h1 { font-family: <?php echo $options['h1_font_family']; ?>;
    </style>
    <?php
}
add_action( 'wp_print_styles', 'mytheme_dynamic_css' );
?>

Oppure, supponiamo di avere combinazioni di colori preconfigurate; puoi accodare il foglio di stile appropriato in base alle impostazioni utente correnti:

<?php
function mytheme_enqueue_colorscheme_stylesheet() {
    $options = get_option( 'mytheme_options' );
    $color_scheme = $options['color_scheme'];
    wp_enqueue_style( $colorscheme, get_template_directory_uri() . '/css/' . $color_scheme . '.css' );
}
add_action( 'wp_enqueue_scripts', 'mytheme_enqueue_colorscheme_stylesheet' );
?>

Si noti che, in questo caso, la funzione si aggancia wp_enqueue_scripts, poiché WordPress non ha un wp_enqueue_styleshook di azione.


1
come 1). Questo è quello che sto facendo ora, ma se hai circa 40K di CSS ottieni un documento html voluminoso
onetrickpony,

1
Ma quei 40K di CSS devono essere emessi da qualche parte , giusto? E sicuramente lo stesso del numero 1, ma è il modo giusto per iniettare CSS dinamico in WordPress. :)
Chip Bennett,

2

Lo stavo pensando da un po 'di tempo. La tua domanda mi fa tornare indietro. Non sono sicuro che sia una buona idea o no, quindi vorrei commenti degli esperti su questo.

Che cosa succede se ho scritto il file javascript / css tramite php durante il salvataggio di amministrazione dei dati. Ci vorrà una sola volta finché l'utente non cambierà nuovamente il layout (che l'utente potrebbe non fare troppo spesso). In questo modo accediamo al database per le impostazioni dell'utente solo una volta quando l'utente salva i dati.

Dopo aver scritto il file sarà un normale file javascript / css, quindi non dovremo chiamare il database ogni volta che si carica il tema.

Una domanda a cui è necessario rispondere: cosa succederà quando un visitatore tenta di accedere al sito nell'istante in cui php scrive il file?

Fatemi sapere cosa ne pensate.


Se si generano quei file in wp-content/uploads(l'unica directory garantita per essere scrivibile dal codice WP), potrebbe essere un approccio praticabile. Penso che anche WP Core usi questa tecnica per un file js.
scribu,

Lo svantaggio è che non è molto dinamico, ovvero è uguale per tutti su tutte le pagine. Per ogni variante, dovresti generare un nuovo file. È ancora un buon approccio per le opzioni di temi / plugin, come hai detto.
scribu,

@scribu: sì, è vero. può essere un casino per qualcosa del genere. se diamo agli utenti una pagina di profilo personalizzata e dobbiamo scrivere file ciascuno di essi. Ma potrebbe essere un buon approccio per qualcosa come se facciamo un creatore di siti Web visivi (trascina e rilascia) in cui l'utente cambia i colori e aggiunge vari effetti (a partire da questa domanda) ecc. E può essere combinato con WPMU;)
Sisir

1

Per piccoli script, che potresti non voler includere in un file separato, ad esempio perché generati dinamicamente, WordPress 4.5 e altre offerte wp_add_inline_script. Questa funzione fondamentalmente aggancia lo script a un altro script. Supponiamo, ad esempio, che stai sviluppando un tema e desideri che il tuo cliente sia in grado di inserire i propri script (come Google Analytics o AddThis) attraverso la pagina delle opzioni. Esempio .

Per gli stili c'è wp_add_inline_style, che sostanzialmente funziona allo stesso modo. Lo utilizzeresti, ad esempio, per scorrere in sequenza tutte le tue mod di personalizzazione e raggrupparle in una stringa chiamata $all_mods, che quindi aggiungerebbe così al tuo foglio di stile principale:

if (!empty($all_mods)) wp_add_inline_style ('main-style', $all_mods);

-2

Crea un file JS.php dinamico e inviagli query_vars importanti. Queste variabili $_GETaiuteranno il file a determinare il contesto e in esso è possibile memorizzare nella cache e utilizzarereadfile() per richieste future ... fare qualunque cosa.

Assicurati solo che il file carichi wp-load.phpprima di ogni altra cosa, in modo da avere accesso alle funzioni di WP. Usa il percorso relativo alla cartella corrente (dirname(__FILE__))o digg semplicemente decrescente nella struttura delle cartelle per individuarewp-load.php indipendentemente dal posizionamento del plug-in.

Codice per cercare wp-load.php da qualsiasi luogo

// Ensure single declaration of function!
if(!function_exists('wp_locate_loader')):
    /**
     * Locates wp-load.php looking backwards on the directory structure.
     * It start from this file's folder.
     * Returns NULL on failure or wp-load.php path if found.
     * 
     * @author EarnestoDev
     * @return string|null
     */
    function wp_locate_loader(){
        $increments = preg_split('~[\\\\/]+~', dirname(__FILE__));
        $increments_paths = array();
        foreach($increments as $increments_offset => $increments_slice){
            $increments_chunk = array_slice($increments, 0, $increments_offset + 1);
            $increments_paths[] = implode(DIRECTORY_SEPARATOR, $increments_chunk);
        }
        $increments_paths = array_reverse($increments_paths);
        foreach($increments_paths as $increments_path){
            if(is_file($wp_load = $increments_path.DIRECTORY_SEPARATOR.'wp-load.php')){
                return $wp_load;
            }
        }
        return null;
    }
endif;
// Now try to load wp-load.php and pull it in
$mt = microtime(true);
if(!is_file($wp_loader = wp_locate_loader())){
    header("{$_SERVER['SERVER_PROTOCOL']} 403 Forbidden");
    header("Status: 403 Forbidden");
    echo 'Access denied!'; // Or whatever
    die;
}
require_once($wp_loader); // Pull it in
unset($wp_loader); // Cleanup variables

Saluti, Scribu!

PS : per strutture complicate in cui le cartelle non seguono la normale struttura decrementale del WP, i plugin principali possono condividere informazioni con file direttamente accessibili. Un plugin genitore che viene fornito con un file PHP dinamico che rende i CSS / JS può scrivere in un file del realpath()del wp-load.phpe il file standalone può usare quella. Questo sarebbe un problema per lo 0,1% degli utenti WP. Penso che coloro che spostano le cartelle e non seguono la normale struttura sappiano cosa stanno facendo e probabilmente possono plug-in PIMP che devono essere caricati wp-load.phpdirettamente.


Carino! Haters, per favore aggiungi spiegazioni. Illuminami. Grazie;) xoxo
EarnestoDev,

È una cattiva pratica includere wp-load.phpda un tema o un file plugin, poiché le directory wp-contente / o pluginspotrebbero trovarsi ovunque rispetto alla directory WP root. Ricorda WP_CONTENT_DIR e WP_PLUGINS_DIR.
scribu,

1
@scribu E il file autonomo può collaborare con un plug-in padre. Il plugin genitore può memorizzare wp-load.php nella cartella in cui si trova e il generatore js dinamico può leggerlo da lì. Semplice ...
EarnestoDev,

1
Sì, l'approccio del plugin genitore potrebbe funzionare. Scrivilo nella tua risposta e rimuoverò il mio voto negativo. PS: questo sito è in inglese; potresti avere problemi se continui a lasciare commenti in rumeno.
scribu,

5
Taglia l'atteggiamento. Il caricamento manuale del core è una tecnica praticabile, ma lungi dall'essere una buona prima scelta per la maggior parte delle cose. Nessuno dubita che tu possa farlo funzionare. I voti riguardano la qualità della tua risposta, non il tuo cervello.
Rarst
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.