Cosa c'è di veramente sbagliato in un endpoint che restituisce HTML piuttosto che dati JSON?

75

Quando ho iniziato a studiare PHP (circa 5 o 6 anni fa) ho imparato a conoscere Ajax , e ho passato "le fasi":

  1. Il tuo server restituisce dati HTML e lo metti in un DOM innerHTML
  2. Scopri i formati di trasferimento dei dati come XML (e dì "oooh così CHE è quello per cui è usato) e poi JSON.
  3. Si restituisce JSON e si costruisce l'interfaccia utente utilizzando il codice JavaScript vaniglia
  4. Passi a jQuery
  5. Scopri le API, le intestazioni, i codici di stato HTTP, REST , CORS e Bootstrap
  6. Si apprende SPA e i framework frontend ( Reagire , Vue.js e AngularJS ) e lo standard API JSON.
  7. Ricevi un codice legacy aziendale e, dopo averlo controllato, scopri che fanno ciò che è descritto nel passaggio 1.

Mentre lavoravo con questo codebase legacy, non pensavo nemmeno che potesse restituire HTML (voglio dire, ora siamo professionisti, giusto?), quindi ho avuto difficoltà a cercare l'endpoint JSON che stava tornando i dati che le chiamate Ajax popolano. Non è stato fino a quando ho chiesto "al programmatore" che mi ha detto che stava restituendo HTML e che veniva aggiunto direttamente al DOM con innerHTML.

Certo, era difficile da accettare. Ho iniziato a pensare ai modi per rifattorizzare questo in endpoint JSON, pensando al test unitario sugli endpoint e così via. Tuttavia, questo codebase non ha test. Non uno solo. Ed è oltre 200k linee. Ovviamente uno dei miei compiti include la proposta di approcci per testare il tutto, ma al momento non lo stiamo ancora affrontando.

Quindi non sono da nessuna parte, in un angolo, a chiedermi: se non abbiamo alcun test, quindi non abbiamo alcun motivo particolare per creare questo endpoint JSON (poiché non è "riutilizzabile": restituisce letteralmente i dati che si adattano solo a quello parte dell'applicazione, ma penso che questo fosse già implicito dal momento che ... restituisce dati HTML).

Cosa esattamente è sbagliato nel fare questo?

    
posta Christopher Francisco 14.03.2017 - 14:47
fonte

12 risposte

112

What's actually wrong with an endpoint returning HTML rather than JSON data?

Niente, davvero. Ogni applicazione ha requisiti diversi e potrebbe essere che la tua applicazione non sia stata progettata per essere una SPA.

Può darsi che questi bellissimi framework che hai citato (Angular, Vue, React, ecc ...) non fossero disponibili al momento dello sviluppo, o che non fossero "enterprisey thingy" approvati da utilizzare nella tua organizzazione.

Sto per dirti questo: un endpoint che restituisce HTML riduce la tua dipendenza dalle librerie JavaScript e riduce il carico sul browser dell'utente poiché non avrà bisogno di interpretare / eseguire codice JS per creare oggetti DOM - l'HTML è già lì, è solo questione di analizzare gli elementi e renderli. Ovviamente, questo significa che stiamo parlando di una quantità ragionevole di dati. 10 megabyte di dati HTML non sono ragionevoli.

Ma dal momento che non c'è niente di sbagliato nel restituire l'HTML, ciò che stai perdendo non usando JSON / XML è fondamentalmente la possibilità di usare il tuo endpoint come API. E qui sta la domanda più grande: ha davvero bisogno di essere un'API?

Correlati: Va bene per tornare HTML da un'API JSON?

    
risposta data 14.03.2017 - 15:29
fonte
50

JSON e HTML soddisfano due diversi scopi semantici.

Se si sta compilando una pagina Web con dati, utilizzare JSON. Se stai costruendo una pagina web da porzioni di pagine web, usa HTML.

Potrebbero sembrare come se fossero la stessa cosa, ma non lo sono affatto. Per prima cosa, quando crei una parte di una pagina Web utilizzando l'HTML restituito dal server, stai lavorando su lato server. Quando stai vincolando i dati a una pagina web, stai lavorando < em> sul lato client.

Inoltre, devi stare attento con HTML per non vincolare strettamente a una pagina specifica. L'intero punto di rendering delle pagine parziali in questo modo è che i partial siano riutilizzabili e se si rende il partial troppo specifico, non si comporrà su altre pagine. JSON non ha questo problema, perché è solo dati, non struttura della pagina web.

    
risposta data 14.03.2017 - 17:08
fonte
21

Il problema principale è che associa strettamente il server al client, che deve conoscere la struttura HTML. Rende anche più difficili da riutilizzare gli endpoint in nuovi modi o nuove applicazioni.

Restituire dati semplici e consentire al client di eseguire il rendering diminuisce l'accoppiamento e aumenta la flessibilità e la testabilità- è possibile eseguire test unitari sul client per dati simulati ed eseguire test di unità sul server per testare i dati desiderati.

    
risposta data 14.03.2017 - 17:03
fonte
14

Penso che tu sia un po 'indietro. Tu dici:

we have no test whatsoever, so we have no particular reason to create this JSON endpoint

Un motivo per utilizzare un endpoint appropriato sarebbe che potrebbe verificarlo. Direi che non avere test è un'ottima ragione per iniziare a scriverne alcuni. Cioè, se c'è una logica che sarebbe adatta a testare.

Le linee di 200k di codice sono molto da refactoring e sono probabilmente difficili da mantenere. Interrompere alcuni endpoint e testarli potrebbe essere un buon punto di partenza.

Un altro motivo potrebbe essere separare il server dal client. Se, in un lontano futuro, la progettazione dell'applicazione o il layout cambiano, è più semplice lavorare con un formato dati appropriato rispetto all'output HTML. In un mondo ideale, dovresti solo cambiare il client e non toccare affatto il server.

    
risposta data 14.03.2017 - 15:06
fonte
6

Ci sono 3 modi (almeno?) per creare una pagina web:

  • Genera l'intero lato del server di pagine.
  • Restituisci una pagina di bare bare dal server più codice (JavaScript), e ottieni la pagina per il recupero dei dati e il rendering nel lato client HTML.
  • Restituisce una pagina parziale più il codice e il codice recupera i blocchi pre-renderizzati di HTML che può rilasciare nella pagina.

Il primo va bene. Anche il secondo va bene. È l'ultimo problema.

Il motivo è semplice: ora hai diviso la costruzione della pagina HTML in parti completamente disconnesse. Il problema è di manutenzione. Ora hai due entità separate responsabili della gestione dei dettagli dell'interfaccia utente. Quindi devi mantenere CSS e altri dettagli simili sincronizzati tra i due pezzi separati. Hai cambiato la larghezza della barra laterale? Grande. Ora il frammento HTML che viene restituito causa lo scrolling orizzontale perché le sue ipotesi sulla larghezza della barra laterale non sono più valide. Hai cambiato il colore di sfondo per quel blocco? Bene, ora il colore del tuo frammento HTML si scontra perché assume un colore di sfondo diverso e qualcuno ha dimenticato di testare quell'endpoint.

Il punto è che ora hai suddiviso le conoscenze che dovrebbero essere centralizzate in un singolo luogo (cioè la logica di presentazione), e questo rende più difficile assicurarsi che tutti i pezzi combacino correttamente. Usando un'API JSON, puoi invece mantenere tutta quella logica solo nel front-end, oppure puoi conservare tutto nei modelli lato server se rendi i tuoi dati in HTML all'inizio. Si tratta di mantenere la conoscenza / logica della presentazione in un unico posto, in modo che possa essere gestita in modo coerente e come parte di un singolo processo. HTML / CSS / JS è abbastanza difficile da rimanere dritto senza suddividerlo in molti piccoli pezzi.

Le API JSON hanno anche il vantaggio aggiuntivo di rendere i dati disponibili completamente indipendenti dalla logica di presentazione. Ciò consente a più relatori diversi , come ad esempio un'app mobile e una pagina Web, di utilizzare gli stessi dati. In particolare, consente di consumare i dati senza un browser (come app mobili o processi cron notturni); questi consumatori potrebbero nemmeno essere in grado di analizzare l'HTML. (Questo naturalmente si basa necessariamente sul fatto di avere una situazione in cui i dati sono gli stessi tra i diversi consumatori, o si può usare un sottoinsieme dell'altro.) Se avete bisogno di questa abilità dipende dai requisiti della vostra particolare applicazione, mentre gestite la vostra presentazione la logica è necessaria a prescindere. Dirò che se lo implementerai in anticipo, sarai comunque preparato per una crescita futura.

    
risposta data 15.03.2017 - 06:31
fonte
4

Non c'è niente di sbagliato in linea di principio . La domanda è: cosa vuoi raggiungere?

JSON è perfetto per la trasmissione di dati. Se invece si invia HTML e si aspetta che il client estragga i dati dall'HTML, è spazzatura.

D'altra parte, se vuoi per trasmettere HMTL che verrà reso come HTML, quindi inviarlo come HTML - invece di impacchettare l'HTML in una stringa, trasformando la stringa in JSON , trasmettendo JSON, decodificandolo dall'altra parte, ottenendo una stringa ed estraendo l'HTML dalla stringa.

E proprio ieri mi sono imbattuto nel codice che ha messo due elementi in un array, trasformato l'array in JSON, inserito il JSON in una stringa, inserito la stringa all'interno di un array, trasformato l'intero array in JSON, inviato al client , che decodifica il JSON, ha ottenuto un array contenente una stringa, preso la stringa, estratto il JSON dalla stringa, decodificato il JSON e ottenuto un array con due elementi. Non farlo.

    
risposta data 16.03.2017 - 15:55
fonte
3

Direi che non c'è niente di sbagliato con il server che restituisce un frammento HTML e l'interfaccia utente che lo assegna a .innerHTML di qualche elemento. Questo è, a mio avviso, il modo più semplice per sviluppare codice JavaScript asincrono. Il vantaggio è che il meno possibile viene fatto usando JavaScript e il più possibile è fatto in un ambiente back-end controllato. Ricorda che il supporto JavaScript nei browser varia ma il tuo back-end ha sempre la stessa versione dei componenti di back-end, il che significa che fare il più possibile nel back-end significherà il minor numero possibile di incompatibilità di versione.

Ora, a volte vuoi più di un semplice frammento HTML. Ad esempio, un codice di stato e un frammento HTML. Quindi puoi usare un oggetto JSON che ha due membri, statusCode e HTML di cui il secondo può essere assegnato a .innerHTML di qualche elemento dopo aver controllato lo statusCode. Quindi, usare JSON e usare innerHTML non sono affatto approcci esclusivi alternativi; possono essere usati insieme.

Usando JSON puoi persino avere più frammenti HTML nella stessa risposta che vengono assegnati al .innerHTML di più elementi.

In sintesi: usa .innerHTML. Rende il tuo codice compatibile con il maggior numero possibile di versioni del browser. Se ne hai bisogno di più, usa JSON e .innerHTML insieme. Evita XML.

    
risposta data 14.03.2017 - 15:14
fonte
3

Tutto dipende dallo scopo dell'API, ma in genere ciò che descrivi è una violenta violazione della separazione delle preoccupazioni :

In un'applicazione moderna, il codice API dovrebbe essere responsabile dei dati e il codice client dovrebbe essere responsabile della presentazione.

Quando la tua API restituisce HTML, stai accoppiando strettamente i tuoi dati e la tua presentazione. Quando l'API restituisce l'HTML, l'unica cosa che puoi fare (facilmente) con quell'HTML è mostrarla come parte di una pagina più grande. Da una diversa angolazione, l'unica cosa per cui l'API è utile è fornire la tua pagina con HTML. Inoltre, hai diffuso il codice HTML sia sul codice client che sul codice server. Questo può rendere la manutenzione un mal di testa.

Se la tua API restituisce JSON, o qualche altra forma di puro dato, diventa molto più utile. L'app esistente può ancora consumare quei dati e presentarli in modo appropriato. Ora, però, altre cose possono usare l'API per accedere agli stessi dati. Anche in questo caso, la manutenzione è più semplice: tutto il codice HTML si trova in un unico posto, quindi se si desidera ridisegnare l'intero sito, non è necessario modificare l'API.

    
risposta data 15.03.2017 - 00:26
fonte
2

L'HTML è legato a un design e a un utilizzo specifici.

Con HTML, se vuoi cambiare il layout della pagina devi cambiare il modo in cui l'html viene generato dalla chiamata al server. Di solito, ciò richiede un programmatore di back-end. Ora hai programmatori di back-end, che per definizione non sono i tuoi migliori scrittori html, gestendo questi aggiornamenti.

Con JSON, se il layout della pagina cambia, la chiamata al server JSON esistente non deve necessariamente cambiare. Invece, lo sviluppatore front-end, o anche il progettista, aggiorna il modello per produrre il diverso codice HTML che desideri dagli stessi dati di base.

Inoltre, il JSON può diventare la base per altri servizi. Potresti avere ruoli diversi che hanno bisogno di vedere gli stessi dati di base in modi diversi. Ad esempio, potresti avere un sito Web del cliente che mostra i dati relativi a un prodotto in una pagina di ordine e una pagina di vendita interna per rappresentanti che mostra gli stessi dati in un layout molto diverso, magari insieme ad altre informazioni non disponibili per i clienti generali. Con JSON, è possibile utilizzare la stessa chiamata server in entrambe le visualizzazioni.

Infine, JSON può scalare meglio. Negli ultimi anni abbiamo in qualche modo esagerato con i framework javascript lato client. Penso che sia ora di fare un passo indietro e iniziare a pensare a quale javascript stiamo usando, e come influisce sulle prestazioni del browser ... specialmente sui dispositivi mobili. Detto questo, se stai eseguendo un sito abbastanza grande da richiedere una server farm o un cluster, invece di un singolo server, JSON può scalare meglio. Gli utenti ti daranno il tempo di elaborazione nei loro browser gratuitamente, e se ne approfitti puoi ridurre il carico del server in una grande distribuzione. Anche JSON usa meno larghezza di banda, quindi ancora, se sei abbastanza grande e usalo in modo appropriato, JSON è misurabilmente più economico. Ovviamente, può anche peggiorare la scala, se si finisce per alimentare le librerie da 40 KB per analizzare 2 KB di dati in 7 KB di html, quindi ancora una volta: è necessario essere consapevoli di ciò che si sta facendo. Ma il potenziale è lì per JSON per migliorare le prestazioni e i costi.

    
risposta data 16.03.2017 - 17:15
fonte
1

Non c'è nulla di sbagliato in un simile endpoint se soddisfa i suoi requisiti. Se è necessario sputare html che un utente noto può analizzare in modo efficace, certo, perché no?

Il problema è che, nel caso generale, vuoi che i tuoi endpoint sputino un payload che è ben formato ed efficacemente analizzabile da un parser standard. E in modo efficace analizzabile, intendo, analizzabile in modo dichiarativo.

Se il tuo cliente è obbligato a leggere il carico utile e ad aprire i bit di informazione da esso con loop e if-statement, allora non è efficacemente analizzabile. E l'HTML, essendo così, è molto perdonato nel non richiedere di essere ben formato.

Ora, se assicurati che il tuo html sia conforme a xml, allora sei d'oro.

Detto questo, ho un problema significativo con questo:

I'm gonna tell you this: an endpoint that returns HTML reduces your dependency on JavaScript libraries and reduces the load on the user browser since it won't need to interpret/execute JS code to create DOM objects - the HTML is already there, it's just a matter of parsing the elements and rendering them. Of course, this means we're talking about a reasonable amount of data. 10 megabytes of HTML data isn't reasonable.

Questa è una cattiva idea, non importa come la tagli. Decenni di esperienza industriale collettiva ci hanno mostrato che, in generale, è una buona idea separare i dati (o il modello) dal suo display (o vista).

Qui si confondono i due allo scopo di velocizzare l'esecuzione del codice JS. E questa è una micro ottimizzazione.

Non l'ho mai visto come una buona idea se non in sistemi molto banali.

Il mio consiglio? Non farlo HC SVNT DRACONES , YMMV, ecc.

    
risposta data 17.03.2017 - 14:00
fonte
0

JSON è solo una presentazione testuale di dati strutturati. Un cliente ha naturalmente bisogno di avere un parser per elaborare i dati, ma praticamente tutte le lingue hanno funzioni di parser JSON. È molto più efficiente usare parser JSON piuttosto che usare parser HTML. Ci vuole poco ingombro. Non così con un parser HTML.

In PHP, basta usare json_encode($data) e spetta al client dall'altra parte analizzarlo. E quando recuperi i dati JSON da un servizio web, usi solo $data=json_decode($response) e puoi decidere come utilizzare i dati come faresti con le variabili.

Supponiamo di sviluppare un'app per un dispositivo mobile, perché è necessario il formato HTML quando le app mobili utilizzano raramente il browser Web per analizzare i dati? Molte app mobili utilizzano JSON (il formato più comune) per lo scambio di dati.

Considerando che i dispositivi mobili sono spesso su piani misurati, perché vuoi utilizzare l'HTML che richiede molta più larghezza di banda rispetto a JSON?

Perché usare HMTL quando HTML è limitato nel suo vocabolario e JSON può definire i dati? {"person_name":"Jeff Doe"} è più informativo di quanto HTML possa fornire sui suoi dati poiché definisce solo la struttura per i parser HTML, non definisce i dati.

JSON non ha nulla a che fare con HTTP. Puoi inserire JSON in un file. Puoi usarlo per le configurazioni. Il compositore usa JSON. Puoi usarlo per salvare anche semplici variabili nei file.

    
risposta data 17.03.2017 - 00:17
fonte
0

È difficile classificare un giusto o uno sbagliato. IMO, le domande che ti pongo sono: " dovrebbe " o " può farlo con meno? ".

Ogni endpoint dovrebbe cercare di comunicare con il minor contenuto possibile. Il rapporto segnale-rumore è in genere i codici HTTP < JSON < XHTML. Nella maggior parte delle situazioni, è bene scegliere il protocollo meno rumoroso.

Differisco sul punto in cui il browser del client viene caricato da @machado, poiché con i browser moderni questo non è un problema. Molti di loro sono equipaggiati per gestire i codici HTTP e le risposte JSON piuttosto bene. E anche se al momento non hai test, la manutenzione a lungo termine di un protocollo meno rumoroso sarebbe più economica rispetto a quella precedente.

    
risposta data 15.03.2017 - 10:16
fonte

Leggi altre domande sui tag