WordPress senza testa: gli alti e bassi della creazione di un WordPress disaccoppiato

Pubblicato: 2022-03-10
Riassunto veloce ↬ Tutti sanno che se un sito web è lento, gli utenti lo abbandoneranno. Molti studi dimostrano la connessione tra le prestazioni del sito Web e i tassi di conversione. In questo articolo, Denis Zoljom condivide la sua esperienza e le basi della creazione di un WordPress disaccoppiato.

WordPress ha fatto molta strada dal suo inizio come semplice strumento di scrittura di blog. Dopo 15 anni, è diventata la scelta numero uno per i CMS sia per gli sviluppatori che per i non sviluppatori. WordPress ora alimenta circa il 30% dei primi 10 milioni di siti sul web.

Da quando l'API REST è stata inclusa nel core di WordPress, gli sviluppatori possono sperimentarla e utilizzarla in modo disaccoppiato, ad esempio scrivendo la parte front-end utilizzando framework o librerie JavaScript. In Infinum, usavamo (e stiamo ancora) WordPress in un modo "classico": PHP per il frontend così come il backend. Dopo un po', abbiamo voluto provare l'approccio disaccoppiato. In questo articolo, condividerò una panoramica di ciò che volevamo ottenere e di ciò che abbiamo incontrato mentre cercavamo di implementare i nostri obiettivi.

Esistono diversi tipi di progetti che possono trarre vantaggio da questo approccio. Ad esempio, semplici siti di presentazione o siti che utilizzano WordPress come back-end sono i principali candidati per l'approccio disaccoppiato.

Negli ultimi anni, per fortuna, l'industria ha iniziato a prestare maggiore attenzione alle prestazioni. Tuttavia, essendo un software inclusivo e versatile di facile utilizzo, WordPress viene fornito con una miriade di opzioni che non sono necessariamente utilizzate in ogni singolo progetto. Di conseguenza, le prestazioni del sito Web possono risentirne.

Letture consigliate : Come utilizzare le mappe di calore per tenere traccia dei clic sul tuo sito Web WordPress

Se i lunghi tempi di risposta del sito Web ti tengono sveglio la notte, questo è un how-to per te. Tratterò le basi della creazione di un WordPress disaccoppiato e alcune lezioni apprese, tra cui:

  1. Il significato di "WordPress disaccoppiato"
  2. Lavorare con l'API REST di WordPress predefinita
  3. Miglioramento delle prestazioni con l'approccio JSON disaccoppiato
  4. Problemi di sicurezza
Altro dopo il salto! Continua a leggere sotto ↓

Quindi, cos'è esattamente un WordPress disaccoppiato?

Quando si tratta di come è programmato WordPress, una cosa è certa: non segue il modello di progettazione Model-View -C ontroller ( MVC ) con cui molti sviluppatori hanno familiarità. A causa della sua storia e per essere una sorta di fork di una vecchia piattaforma di blogging chiamata "b2" (maggiori dettagli qui), è in gran parte scritto in modo procedurale (usando codice basato su funzioni). Gli sviluppatori principali di WordPress hanno utilizzato un sistema di hook che ha consentito ad altri sviluppatori di modificare o estendere determinate funzionalità.

È un sistema all-in-one dotato di un'interfaccia di amministrazione funzionante; gestisce la connessione al database e ha un sacco di utili API esposte che gestiscono l'autenticazione dell'utente, il routing e altro.

Ma grazie all'API REST, puoi separare il back-end di WordPress come una sorta di modello e controller raggruppati insieme che gestiscono la manipolazione dei dati e l'interazione del database e utilizzare il controller API REST per interagire con un livello di visualizzazione separato utilizzando vari endpoint API. Oltre alla separazione MVC, possiamo (per motivi di sicurezza o miglioramenti della velocità) posizionare l'app JS su un server separato come nello schema seguente:

Immagine raffigurante un diagramma WordPress disaccoppiato con parti PHP e JS separate
Diagramma WordPress disaccoppiato. (Grande anteprima)

Vantaggi dell'utilizzo dell'approccio disaccoppiato

Una cosa per cui potresti voler utilizzare questo approccio è garantire una separazione delle preoccupazioni. Il frontend e il backend interagiscono tramite endpoint; ciascuno può trovarsi su un server separato che può essere ottimizzato in modo specifico per ciascuna rispettiva attività, ad esempio eseguendo separatamente un'app PHP ed eseguendo un'app Node.js.

Separando il frontend dal backend, è più facile riprogettarlo in futuro, senza modificare il CMS. Inoltre, gli sviluppatori front-end devono solo preoccuparsi di cosa fare con i dati forniti loro dal back-end. Ciò consente loro di diventare creativi e utilizzare librerie moderne come ReactJS, Vue o Angular per fornire app Web altamente dinamiche. Ad esempio, è più facile creare un'app Web progressiva quando si utilizzano le librerie di cui sopra.

Un altro vantaggio si riflette nella sicurezza del sito web. Sfruttare il sito Web attraverso il back-end diventa più difficile poiché è in gran parte nascosto al pubblico.

Lettura consigliata : La sicurezza di WordPress come processo

Carenze dell'utilizzo dell'approccio disaccoppiato

Innanzitutto, avere un WordPress disaccoppiato significa mantenere due istanze separate:

  1. WordPress per il backend;
  2. Un'app front-end separata, inclusi aggiornamenti di sicurezza tempestivi.

In secondo luogo, alcune delle librerie front-end hanno una curva di apprendimento più ripida. Ci vorrà molto tempo per imparare una nuova lingua (se sei abituato solo a HTML e CSS per la creazione di modelli), o richiederà il coinvolgimento di esperti JavaScript aggiuntivi nel progetto.

Terzo, separando il frontend, stai perdendo la potenza dell'editor WYSIWYG e nemmeno il pulsante "Anteprima dal vivo" in WordPress non funziona.

Lavorare con l'API REST di WordPress

Prima di approfondire il codice, un altro paio di cose sull'API REST di WordPress. La piena potenza dell'API REST in WordPress è arrivata con la versione 4.7 il 6 dicembre 2016.

Ciò che l'API REST di WordPress ti consente di fare è interagire con la tua installazione di WordPress in remoto inviando e ricevendo oggetti JSON.

Impostare un progetto

Dal momento che viene fornito in bundle con l'ultima installazione di WordPress, lavoreremo sul tema Twenty Seventeen. Sto lavorando su Varying Vagrant Vagrants e ho creato un sito di test con un URL https://dev.wordpress.test/ . Questo URL verrà utilizzato in tutto l'articolo. Importeremo anche i post dal repository dei team di revisione dei temi di wordpress.org in modo da avere alcuni dati di test con cui lavorare. Ma prima, acquisiremo familiarità con il lavoro con gli endpoint predefiniti, quindi creeremo il nostro endpoint personalizzato.

Accedi all'endpoint REST predefinito

Come già accennato, WordPress viene fornito con diversi endpoint integrati che puoi esaminare andando al percorso /wp-json/ :

 https://dev.wordpress.test/wp-json/

Inserendo questo URL direttamente nel tuo browser o aggiungendolo nell'app postino, otterrai una risposta JSON dall'API REST di WordPress simile a questa:

 { "name": "Test dev site", "description": "Just another WordPress site", "url": "https://dev.wordpress.test", "home": "https://dev.wordpress.test", "gmt_offset": "0", "timezone_string": "", "namespaces": [ "oembed/1.0", "wp/v2" ], "authentication": [], "routes": { "/": { "namespace": "", "methods": [ "GET" ], "endpoints": [ { "methods": [ "GET" ], "args": { "context": { "required": false, "default": "view" } } } ], "_links": { "self": "https://dev.wordpress.test/wp-json/" } }, "/oembed/1.0": { "namespace": "oembed/1.0", "methods": [ "GET" ], "endpoints": [ { "methods": [ "GET" ], "args": { "namespace": { "required": false, "default": "oembed/1.0" }, "context": { "required": false, "default": "view" } } } ], "_links": { "self": "https://dev.wordpress.test/wp-json/oembed/1.0" } }, ... "wp/v2": { ...

Quindi, per ottenere tutti i post nel nostro sito utilizzando REST, dovremmo andare su https://dev.wordpress.test/wp-json/wp/v2/posts . Si noti che wp/v2/ contrassegna gli endpoint principali riservati come post, pagine, media, tassonomie, categorie e così via.

Quindi, come aggiungiamo un endpoint personalizzato?

Crea un endpoint REST personalizzato

Supponiamo di voler aggiungere un nuovo endpoint o un campo aggiuntivo all'endpoint esistente. Ci sono diversi modi in cui possiamo farlo. Innanzitutto, uno può essere eseguito automaticamente durante la creazione di un tipo di post personalizzato. Ad esempio, vogliamo creare un endpoint di documentazione. Creiamo un piccolo plugin di prova. Crea una cartella di documentazione di prova nella cartella wp-content/plugins e aggiungi il file documentation.php che assomiglia a questo:

 <?php /** * Test plugin * * @since 1.0.0 * @package test_plugin * * @wordpress-plugin * Plugin Name: Test Documentation Plugin * Plugin URI: * Description: The test plugin that adds rest functionality * Version: 1.0.0 * Author: Infinum <[email protected]> * Author URI: https://infinum.co/ * License: GPL-2.0+ * License URI: https://www.gnu.org/licenses/gpl-2.0.txt * Text Domain: test-plugin */ namespace Test_Plugin; // If this file is called directly, abort. if ( ! defined( 'WPINC' ) ) { die; } /** * Class that holds all the necessary functionality for the * documentation custom post type * * @since 1.0.0 */ class Documentation { /** * The custom post type slug * * @var string * * @since 1.0.0 */ const PLUGIN_NAME = 'documentation-plugin'; /** * The custom post type slug * * @var string * * @since 1.0.0 */ const POST_TYPE_SLUG = 'documentation'; /** * The custom taxonomy type slug * * @var string * * @since 1.0.0 */ const TAXONOMY_SLUG = 'documentation-category'; /** * Register custom post type * * @since 1.0.0 */ public function register_post_type() { $args = array( 'label' => esc_html( 'Documentation', 'test-plugin' ), 'public' => true, 'menu_position' => 47, 'menu_icon' => 'dashicons-book', 'supports' => array( 'title', 'editor', 'revisions', 'thumbnail' ), 'has_archive' => false, 'show_in_rest' => true, 'publicly_queryable' => false, ); register_post_type( self::POST_TYPE_SLUG, $args ); } /** * Register custom tag taxonomy * * @since 1.0.0 */ public function register_taxonomy() { $args = array( 'hierarchical' => false, 'label' => esc_html( 'Documentation tags', 'test-plugin' ), 'show_ui' => true, 'show_admin_column' => true, 'update_count_callback' => '_update_post_term_count', 'show_in_rest' => true, 'query_var' => true, ); register_taxonomy( self::TAXONOMY_SLUG, [ self::POST_TYPE_SLUG ], $args ); } } $documentation = new Documentation(); add_action( 'init', [ $documentation, 'register_post_type' ] ); add_action( 'init', [ $documentation, 'register_taxonomy' ] );

Registrando il nuovo tipo di post e la nuova tassonomia e impostando l'argomento show_in_rest su true , WordPress ha creato automaticamente un percorso REST nello spazio dei nomi /wp/v2/ . Ora hai https://dev.wordpress.test/wp-json/wp/v2/documentation e https://dev.wordpress.test/wp-json/wp/v2/documentation-category endpoint disponibili. Se aggiungiamo un post nel nostro post personalizzato della documentazione appena creato andando a https://dev.wordpress.test/?post_type=documentation , ci darà una risposta simile a questa:

 [ { "id": 4, "date": "2018-06-11T19:48:51", "date_gmt": "2018-06-11T19:48:51", "guid": { "rendered": "https://dev.wordpress.test/?post_type=documentation&p=4" }, "modified": "2018-06-11T19:48:51", "modified_gmt": "2018-06-11T19:48:51", "slug": "test-documentation", "status": "publish", "type": "documentation", "link": "https://dev.wordpress.test/documentation/test-documentation/", "title": { "rendered": "Test documentation" }, "content": { "rendered": "

Questo è un contenuto della documentazione

\n", "protetto": falso }, "media_in primo piano": 0, "modello": "", "documentazione-categoria": [ 2 ], "_link": { "se stesso": [ { "href": "https://dev.wordpress.test/wp-json/wp/v2/documentation/4" } ], "collezione": [ { "href": "https://dev.wordpress.test/wp-json/wp/v2/documentation" } ], "di": [ { "href": "https://dev.wordpress.test/wp-json/wp/v2/types/documentation" } ], "cronologia delle versioni": [ { "href": "https://dev.wordpress.test/wp-json/wp/v2/documentation/4/revisions" } ], "wp:allegato": [ { "href": "https://dev.wordpress.test/wp-json/wp/v2/media?parent=4" } ], "wp:termine": [ { "tassonomia": "documentazione-categoria", "incorporabile": vero, "href": "https://dev.wordpress.test/wp-json/wp/v2/documentation-category?post=4" } ], "curiosità": [ { "nome": "wp", "href": "https://api.w.org/{rel}", "templato": vero } ] } } ]

Questo è un ottimo punto di partenza per la nostra applicazione a pagina singola. Un altro modo per aggiungere un endpoint personalizzato è rest_api_init e creando noi stessi un endpoint. Aggiungiamo un percorso custom-documentation un po' diverso da quello che abbiamo registrato. Sempre lavorando nello stesso plugin, possiamo aggiungere:

 /** * Create a custom endpoint * * @since 1.0.0 */ public function create_custom_documentation_endpoint() { register_rest_route( self::PLUGIN_NAME . '/v1', '/custom-documentation', array( 'methods' => 'GET', 'callback' => [ $this, 'get_custom_documentation' ], ) ); } /** * Create a callback for the custom documentation endpoint * * @return string JSON that indicates success/failure of the update, * or JSON that indicates an error occurred. * @since 1.0.0 */ public function get_custom_documentation() { /* Some permission checks can be added here. */ // Return only documentation name and tag name. $doc_args = array( 'post_type' => self::POST_TYPE_SLUG, 'post_status' => 'publish', 'perm' => 'readable' ); $query = new \WP_Query( $doc_args ); $response = []; $counter = 0; // The Loop if ( $query->have_posts() ) { while ( $query->have_posts() ) { $query->the_post(); $post_id = get_the_ID(); $post_tags = get_the_terms( $post_id, self::TAXONOMY_SLUG ); $response[ $counter ]['title'] = get_the_title(); foreach ( $post_tags as $tags_key => $tags_value ) { $response[ $counter ]['tags'][] = $tags_value->name; } $counter++; } } else { $response = esc_html__( 'There are no posts.', 'documentation-plugin' ); } /* Restore original Post Data */ wp_reset_postdata(); return rest_ensure_response( $response ); }

E aggancia il metodo create_custom_documentation_endpoint create_custom_documentation_endpoint() rest_api_init , in questo modo:

 add_action( 'rest_api_init', [ $documentation, 'create_custom_documentation_endpoint' ] );

Ciò aggiungerà una route personalizzata in https://dev.wordpress.test/wp-json/documentation-plugin/v1/custom-documentation con la richiamata che restituirà la risposta per quella route.

 [{ "title": "Another test documentation", "tags": ["Another tag"] }, { "title": "Test documentation", "tags": ["REST API", "test tag"] }]

Ci sono molte altre cose che puoi fare con l'API REST (puoi trovare maggiori dettagli nel manuale dell'API REST).

Risolvi tempi di risposta lunghi quando utilizzi l'API REST predefinita

Per chiunque abbia provato a creare un sito WordPress disaccoppiato, questa non è una novità: l'API REST è lenta.

Io e il mio team abbiamo incontrato per la prima volta la strana API REST in ritardo di WordPress su un sito client (non disaccoppiato), in cui abbiamo utilizzato gli endpoint personalizzati per ottenere l'elenco delle posizioni su una mappa di Google, insieme ad altre metainformazioni create utilizzando Advanced Custom Fields Pro collegare. Si è scoperto che il tempo del primo byte (TTFB), utilizzato come indicazione della reattività di un server Web o di un'altra risorsa di rete, ha richiesto più di 3 secondi.

Dopo un po' di indagine, ci siamo resi conto che le chiamate API REST predefinite erano in realtà molto lente, specialmente quando abbiamo "appesantito" il sito con plug-in aggiuntivi. Quindi, abbiamo fatto un piccolo test. Abbiamo installato un paio di plugin popolari e abbiamo riscontrato dei risultati interessanti. L'app postino ha fornito il tempo di caricamento di 1,97 secondi per 41,9 KB di dimensioni della risposta. Il tempo di caricamento di Chrome è stato di 1,25 secondi (TTFB era di 1,25 secondi, il contenuto è stato scaricato in 3,96 ms). Giusto per recuperare un semplice elenco di post. Nessuna tassonomia, nessun dato utente, nessun meta campo aggiuntivo.

Perché è successo?

Si scopre che l'accesso all'API REST sul WordPress predefinito caricherà l'intero core di WordPress per servire gli endpoint, anche se non viene utilizzato. Inoltre, più plugin aggiungi, peggiori saranno le cose. Il controller REST predefinito WP_REST_Controller è una classe davvero grande che fa molto più del necessario quando si costruisce una semplice pagina web. Gestisce la registrazione dei percorsi, i controlli delle autorizzazioni, la creazione e l'eliminazione di elementi e così via.

Esistono due soluzioni comuni per questo problema:

  1. Intercetta il caricamento dei plugin ed evita di caricarli tutti quando devi servire una semplice risposta REST;
  2. Carica solo il minimo indispensabile di WordPress e archivia i dati in un transitorio, da cui poi recuperiamo i dati utilizzando una pagina personalizzata.

Miglioramento delle prestazioni con l'approccio JSON disaccoppiato

Quando lavori con semplici siti di presentazione, non hai bisogno di tutte le funzionalità offerte dall'API REST. Naturalmente, è qui che una buona pianificazione è fondamentale. Non vuoi davvero creare il tuo sito senza l'API REST e poi dire tra un anno che vorresti connetterti al tuo sito, o magari creare un'app mobile che deve utilizzare la funzionalità dell'API REST. Fai?

Per questo motivo, abbiamo utilizzato due funzionalità di WordPress che possono aiutarti quando fornisci dati JSON semplici:

  • API transitori per la memorizzazione nella cache,
  • Caricamento del minimo necessario WordPress utilizzando la costante SHORTINIT .

Creazione di un semplice endpoint di pagine disaccoppiate

Creiamo un piccolo plugin che dimostrerà l'effetto di cui stiamo parlando. Innanzitutto, aggiungi un file wp-config-simple.php nel tuo plugin json-transient che assomiglia a questo:

 <?php /** * Create simple wp configuration for the routes * * @since 1.0.0 * @package json-transient */ define( 'SHORTINIT', true ); $parse_uri = explode( 'wp-content', $_SERVER['SCRIPT_FILENAME'] ); require_once filter_var( $parse_uri[0] . 'wp-load.php', FILTER_SANITIZE_STRING );

Il define( 'SHORTINIT', true ); impedirà il caricamento della maggior parte dei file core di WordPress, come si può vedere nel file wp-settings.php .

Potremmo ancora aver bisogno di alcune delle funzionalità di WordPress, quindi possiamo richiedere il file (come wp-load.php ) manualmente. Poiché wp-load.php si trova nella radice della nostra installazione di WordPress, lo recupereremo ottenendo il percorso del nostro file utilizzando $_SERVER['SCRIPT_FILENAME'] e quindi esplodendo quella stringa per wp-content string. Questo restituirà un array con due valori:

  1. La radice della nostra installazione;
  2. Il resto del percorso del file (che non ci interessa).

Tieni presente che stiamo utilizzando l'installazione predefinita di WordPress e non modificata, come ad esempio nel boilerplate Bedrock, che divide WordPress in un'organizzazione di file diversa.

Infine, abbiamo bisogno del file wp-load.php , con un po' di sanificazione, per sicurezza.

Nel nostro file init.php , aggiungeremo quanto segue:

* Author URI: https://infinum.co/ * License: GPL-2.0+ * License URI: https://www.gnu.org/licenses/gpl-2.0.txt * Text Domain: json-transient */ namespace Json_Transient; // If this file is called directly, abort. if ( ! defined( 'WPINC' ) ) { die; } class Init { /** * Get the array of allowed types to do operations on. * * @return array * * @since 1.0.0 */ public function get_allowed_post_types() { return array( 'post', 'page' ); } /** * Check if post type is allowed to be save in transient. * * @param string $post_type Get post type. * @return boolean * * @since 1.0.0 */ public function is_post_type_allowed_to_save( $post_type = null ) { if( ! $post_type ) { return false; } $allowed_types = $this->get_allowed_post_types(); if ( in_array( $post_type, $allowed_types, true ) ) { return true; } return false; } /** * Get Page cache name for transient by post slug and type. * * @param string $post_slug Page Slug to save. * @param string $post_type Page Type to save. * @return string * * @since 1.0.0 */ public function get_page_cache_name_by_slug( $post_slug = null, $post_type = null ) { if( ! $post_slug || ! $post_type ) { return false; } $post_slug = str_replace( '__trashed', '', $post_slug ); return 'jt_data_' . $post_type . '_' . $post_slug; } /** * Get full post data by post slug and type. * * @param string $post_slug Page Slug to do Query by. * @param string $post_type Page Type to do Query by. * @return array * * @since 1.0.0 */ public function get_page_data_by_slug( $post_slug = null, $post_type = null ) { if( ! $post_slug || ! $post_type ) { return false; } $page_output = ''; $args = array( 'name' => $post_slug, 'post_type' => $post_type, 'posts_per_page' => 1, 'no_found_rows' => true ); $the_query = new \WP_Query( $args ); if ( $the_query->have_posts() ) { while ( $the_query->have_posts() ) { $the_query->the_post(); $page_output = $the_query->post; } wp_reset_postdata(); } return $page_output; } /** * Return Page in JSON format * * @param string $post_slug Page Slug. * @param string $post_type Page Type. * @return json * * @since 1.0.0 */ public function get_json_page( $post_slug = null, $post_type = null ) { if( ! $post_slug || ! $post_type ) { return false; } return wp_json_encode( $this->get_page_data_by_slug( $post_slug, $post_type ) ); } /** * Update Page to transient for caching on action hooks save_post. * * @param int $post_id Saved Post ID provided by action hook. * * @since 1.0.0 */ public function update_page_transient( $post_id ) { $post_status = get_post_status( $post_id ); $post = get_post( $post_id ); $post_slug = $post->post_name; $post_type = $post->post_type; $cache_name = $this->get_page_cache_name_by_slug( $post_slug, $post_type ); if( ! $cache_name ) { return false; } if( $post_status === 'auto-draft' || $post_status === 'inherit' ) { return false; } else if( $post_status === 'trash' ) { delete_transient( $cache_name ); } else { if( $this->is_post_type_allowed_to_save( $post_type ) ) { $cache = $this->get_json_page( $post_slug, $post_type ); set_transient( $cache_name, $cache, 0 ); } } } } $init = new Init(); add_action( 'save_post', [ $init, 'update_page_transient' ] );

I metodi di supporto nel codice sopra ci consentiranno di eseguire la memorizzazione nella cache:

  • get_allowed_post_types()
    Questo metodo consente ai tipi di post di sapere che vogliamo abilitare la visualizzazione nel nostro "endpoint" personalizzato. Puoi estenderlo e il plug-in che abbiamo effettivamente reso questo metodo filtrabile in modo che tu possa semplicemente utilizzare un filtro per aggiungere elementi aggiuntivi.
  • is_post_type_allowed_to_save()
    Questo metodo controlla semplicemente per vedere se il tipo di post da cui stiamo cercando di recuperare i dati è nell'array consentito specificato dal metodo precedente.
  • get_page_cache_name_by_slug()
    Questo metodo restituirà il nome del transitorio da cui verranno recuperati i dati.
  • get_page_data_by_slug()
    Questo metodo è il metodo che eseguirà WP_Query sul post tramite il suo tipo slug e post e restituirà il contenuto dell'array di post che convertiremo con il JSON usando il metodo get_json_page() .
  • update_page_transient()
    Questo verrà eseguito save_post e sovrascriverà il transitorio nel database con i dati JSON del nostro post. Quest'ultimo metodo è noto come "metodo di memorizzazione nella cache delle chiavi".

Spieghiamo i transitori in modo più approfondito.

API Transitori

L'API Transienti viene utilizzata per archiviare i dati nella tabella delle opzioni del database di WordPress per un periodo di tempo specifico. È una cache di oggetti persistente, il che significa che stai archiviando alcuni oggetti, ad esempio i risultati di query grandi e lente o pagine intere che possono essere mantenute durante i caricamenti di pagina. È simile alla normale cache degli oggetti di WordPress, ma a differenza WP_Cache , i transitori manterranno i dati durante il caricamento della pagina, WP_Cache (memorizzazione dei dati in memoria) conserverà i dati solo per la durata di una richiesta.

È un archivio chiave-valore, il che significa che possiamo recuperare facilmente e rapidamente i dati desiderati, in modo simile a quanto fanno in-memory caching systems come Memcached o Redis. La differenza è che di solito è necessario installarli separatamente sul server (che può essere un problema sui server condivisi), mentre i transitori sono integrati con WordPress.

Come notato nella sua pagina Codex, i transitori sono intrinsecamente accelerati dai plug-in di memorizzazione nella cache. Dal momento che possono memorizzare transitori in memoria anziché in un database. La regola generale è che non dovresti presumere che il transitorio sia sempre presente nel database, motivo per cui è buona norma verificarne l'esistenza prima di recuperarlo

 $transient_name = get_transient( 'transient_name' ); if ( $transient_name === false ) { set_transient( 'transient_name', $transient_data, $transient_expiry ); }

Puoi usarlo senza scadenza (come stiamo facendo noi), ed è per questo che abbiamo implementato una sorta di 'cache-busting' dopo il salvataggio. Oltre a tutte le fantastiche funzionalità che offrono, possono contenere fino a 4 GB di dati, ma non consigliamo di archiviare nulla di così grande in un unico campo di database.

Letture consigliate : Stai attento: funzioni PHP e WordPress che possono rendere insicuro il tuo sito

Endpoint finale: test e verifica

L'ultimo pezzo del puzzle di cui abbiamo bisogno è un "punto finale". Sto usando il termine endpoint qui, anche se non è un endpoint poiché stiamo chiamando direttamente un file specifico per recuperare i nostri risultati. Quindi possiamo creare un file test.php che assomiglia a questo:

 get_page_cache_name_by_slug( $post_slug, $post_type ) ); // Return error on false. if ( $cache === false ) { wp_send_json( 'Error, the page does not exist or it is not cached correctly. Please try rebuilding cache and try again!' ); } // Decode json for output. wp_send_json( json_decode( $cache ) );

Se andiamo su https://dev.wordpress.test/wp-content/plugins/json-transient/test.php , vedremo questo messaggio:

Errore, slug di pagina o tipo mancante!

Quindi, dovremo specificare il tipo di post e il post slug. Quando ora andiamo su https://dev.wordpress.test/wp-content/plugins/json-transient/test.php?slug=hello-world&type=post vedremo:

Errore, la pagina non esiste o non è memorizzata correttamente nella cache. Prova a ricostruire la cache e riprova!

Oh, aspetta! Dobbiamo prima salvare nuovamente le nostre pagine e i nostri post. Quindi, quando inizi, può essere facile. Ma se hai già più di 100 pagine o post, questo può essere un compito impegnativo. Questo è il motivo per cui abbiamo implementato un modo per cancellare i transitori nel plug-in Contenuto JSON disaccoppiato e ricostruirli in batch.

Ma vai avanti e salva nuovamente il post di Hello World , quindi apri di nuovo il collegamento. Quello che dovresti avere ora è qualcosa che assomiglia a questo:

 { "ID": 1, "post_author": "1", "post_date": "2018-06-26 18:28:57", "post_date_gmt": "2018-06-26 18:28:57", "post_content": "Welcome to WordPress. This is your first post. Edit or delete it, then start writing!", "post_title": "Hello world!", "post_excerpt": "", "post_status": "publish", "comment_status": "open", "ping_status": "open", "post_password": "", "post_name": "hello-world", "to_ping": "", "pinged": "", "post_modified": "2018-06-30 08:34:52", "post_modified_gmt": "2018-06-30 08:34:52", "post_content_filtered": "", "post_parent": 0, "guid": "http:\/\/dev.wordpress.test\/?p=1", "menu_order": 0, "post_type": "post", "post_mime_type": "", "comment_count": "1", "filter": "raw" }

E questo è tutto. Il plug-in che abbiamo creato ha alcune funzionalità extra che puoi utilizzare, ma in poche parole, è così che puoi recuperare i dati JSON dal tuo WordPress che è molto più veloce rispetto all'utilizzo dell'API REST.

Prima e dopo: tempi di risposta migliorati

Abbiamo condotto dei test in Chrome, dove abbiamo potuto vedere il tempo di risposta totale e il TTFB separatamente. Abbiamo testato i tempi di risposta dieci volte di seguito: prima senza plug-in e poi con i plug-in aggiunti. Inoltre, abbiamo testato la risposta per un elenco di post e per un singolo post.

I risultati della prova sono illustrati nelle tabelle seguenti:

Grafico di confronto che illustra i tempi di risposta dell'utilizzo dell'API REST di WordPress rispetto all'utilizzo dell'approccio disaccoppiato senza plug-in aggiunti. L'approccio disaccoppiato è da 2 a 3 volte più veloce
Grafico di confronto che illustra i tempi di risposta dell'utilizzo dell'API REST di WordPress rispetto all'utilizzo dell'approccio disaccoppiato senza plug-in aggiunti. L'approccio disaccoppiato è da 2 a 3 volte più veloce. (Grande anteprima)
Grafico di confronto che illustra i tempi di risposta dell'utilizzo dell'API REST di WordPress rispetto all'utilizzo dell'approccio disaccoppiato con plug-in aggiunti. L'approccio disaccoppiato è fino a 8 volte più veloce.
Grafico di confronto che illustra i tempi di risposta dell'utilizzo dell'API REST di WordPress rispetto all'utilizzo dell'approccio disaccoppiato con plug-in aggiunti. L'approccio disaccoppiato è fino a 8 volte più veloce. (Grande anteprima)

Come puoi vedere, la differenza è drastica.

Problemi di sicurezza

Ci sono alcuni avvertimenti che dovrai dare una buona occhiata. Prima di tutto, stiamo caricando manualmente i file core di WordPress, che nel mondo di WordPress è un grande no. Come mai? Bene, oltre al fatto che il recupero manuale dei file core può essere complicato (soprattutto se stai utilizzando installazioni non standard come Bedrock), potrebbe porre alcuni problemi di sicurezza.

Se decidi di utilizzare il metodo descritto in questo articolo, assicurati di sapere come rafforzare la sicurezza del tuo server.

Innanzitutto, aggiungi le intestazioni HTML come nel file test.php :

 header( 'Access-Control-Allow-Origin: your-front-end-app.url' ); header( 'Content-Type: application/json' );

La prima intestazione è un modo per aggirare la misura di sicurezza CORS in modo che solo l'app front-end possa recuperare i contenuti quando si passa al file specificato.

In secondo luogo, disabilita l'attraversamento della directory della tua app. Puoi farlo modificando le impostazioni di nginx o aggiungendo Options -Indexes al tuo file .htaccess se sei su un server Apache.

Anche l'aggiunta di un token check alla risposta è una buona misura che può prevenire accessi indesiderati. Stiamo effettivamente lavorando a un modo per modificare il nostro plug-in JSON disaccoppiato in modo da poter includere queste misure di sicurezza per impostazione predefinita.

Un controllo per un'intestazione di autorizzazione inviata dall'app frontend potrebbe essere simile al seguente:

 if ( ! isset( $_SERVER['HTTP_AUTHORIZATION'] ) ) { return; } $auth_header = $_SERVER['HTTP_AUTHORIZATION'];

Quindi puoi verificare se il token specifico (un segreto condiviso solo dalle app front-end e back-end) è fornito e corretto.

Conclusione

L'API REST è eccezionale perché può essere utilizzata per creare app a tutti gli effetti, creando, recuperando, aggiornando ed eliminando i dati. Lo svantaggio di usarlo è la sua velocità.

Ovviamente creare un'app è diverso dal creare un classico sito web. Probabilmente non avrai bisogno di tutti i plugin che abbiamo installato. Ma se hai solo bisogno dei dati per scopi di presentazione, la memorizzazione nella cache dei dati e la loro pubblicazione in un file personalizzato sembra la soluzione perfetta al momento, quando si lavora con siti disaccoppiati.

Potresti pensare che creare un plug-in personalizzato per accelerare il tempo di risposta del sito Web sia eccessivo, ma viviamo in un mondo in cui ogni secondo conta. Tutti sanno che se un sito web è lento, gli utenti lo abbandoneranno. Esistono molti studi che dimostrano la connessione tra le prestazioni del sito Web e i tassi di conversione. Ma se hai ancora bisogno di convincere, Google penalizza i siti web lenti.

Il metodo spiegato in questo articolo risolve il problema di velocità che incontra l'API REST di WordPress e ti darà una spinta in più quando lavori su un progetto WordPress disaccoppiato. Poiché siamo alla continua ricerca di spremere quell'ultimo millisecondo da ogni richiesta e risposta, prevediamo di ottimizzare ulteriormente il plug-in. Nel frattempo, condividi le tue idee su come velocizzare WordPress disaccoppiato!