Rimanda javascript e mostra contenuti provvisori al caricamento iniziale della pagina

Che ne dici di: Differire gli script di Discourse

Aggiungi attributi defer a tutti gli script, se possibile. Differire il caricamento e l’esecuzione di JavaScript consente al browser di iniziare l’analisi HTML, il rendering e la pittura.

Quindi, alcuni contenuti statici intermedi potrebbero essere visualizzati abbastanza presto (o anche prima) del processo di avvio di Discourse. Questo dovrebbe essere sufficiente per una velocità di caricamento della pagina percepita dall’utente più rapida al primo caricamento della pagina.

Idee per contenuti statici intermedi:

  • schermata di avvio con logo e indicatore di caricamento
  • visualizzazione dell’argomento con post dal backend

POC e PR

Per l’ultima prova di concetto e PR, dai un’occhiata a questo post.


Attualmente, gli script JavaScript del fornitore e tutti gli script precedenti non vengono differiti.
@vedi: https://github.com/rr-it/discourse/commit/328efd5c055f5f2a4d93b5e52268cfe92913faf7

Le idee su come risolvere questo problema sono molto benvenute.


JavaScript async vs. defer vs. none

Maggiori informazioni sulle opzioni di caricamento di JavaScript, incluso defer: Efficiently load JavaScript with defer and async
(Questo non riguarda l’accelerazione del vero avvio di Discourse.)


Fastboot/rehydration

Ho letto questo articolo:
La conclusione sembra essere un’implementazione di Fastboot/rehydration.
C’è una scadenza per questo?

4 Mi Piace

Ciò causerebbe il LCP (Largest Contentful Paint) ancora dopo che EmberJS si avvia e re-renderizza, non affrontando il problema principale relativo alle nuove classifiche di Google.

Questo è il nostro attuale piano a medio termine per affrontare il LCP in Discourse.

2 Mi Piace

A partire da Chrome 88, fortunatamente non è più così! :rocket:
Non lo sapevo nemmeno io fino ad ora. :))

“Prima di questa modifica, un elemento che veniva rimosso non veniva più considerato un candidato LCP valido. […] Dopo questa modifica, un elemento che viene rimosso è ancora considerato un candidato LCP valido.”

“La modifica per includere contenuti che vengono successivamente rimossi dal DOM come possibili largest contentful paint migliorerà i tempi di Largest Contentful Paint sui siti che hanno immagini [per Discourse: elementi di testo] delle stesse dimensioni inseriti più volte. Questo è un pattern comune per i caroselli, così come per alcuni framework JavaScript che fanno server-side rendering.”


LCP Changelog

Potrebbero esserci altre buone modifiche in futuro:

1 Mi Piace

Ecco alcune statistiche simulate per una pagina di argomento con il POC implementato.

Lighthouse: “I valori sono stimati e possono variare.”

WebPageTest

webpagetest.org

Simulazione Moto4G


Nota: noi siamo la freccia nera in alto.


Note:

  • 0s-2s - schermo bianco:
    WebPageTest ignora defer per JavaScript e scarica tutti gli script prima di eseguire una prima visualizzazione - questo funziona correttamente su un dispositivo reale.
  • 2.5s - LCP: contenuto statico dal rendering del server
  • 3.5s - Cambiamento visivo: caricato il logo
  • 6.5s - Cambiamento visivo: contenuto dal rendering di EmberJs
  • 7s - Completamento visivo

PageSpeed Insights

Elemento Largest Contentful Paint

PageSpeed identifica correttamente il nodo di testo statico dal rendering del server come elemento FCP LCP:
div.row > div.topic-body > div.post > p

Nodo di testo renderizzato da EmberJs:
div.row > div.topic-body > div.regular.contents > div.cooked > p

Ma sembra che PageSpeed non utilizzi il nodo di testo statico correttamente identificato per il suo risultato simulato: FCP e LCP simulati sono troppo grandi.

Dati utente reali

Aspettiamo altri 14-28 giorni per ottenere dati “reali” da Chrome UX Report con il POC implementato.

Statistiche senza POC implementato per la pagina di argomento testata:
(I dati si riferiscono a questo singolo URL di argomento – e non all’intero dominio.)

4 Mi Piace

Oh, questa è una scoperta molto interessante! Ottimo lavoro!

Cosa ottieni con questa estensione https://chrome.google.com/webstore/detail/web-vitals/ahfhijdlegdabablpippeagghigmibma?

3 Mi Piace

Tramite l’estensione Chrome Web Vitals

  • sul desktop
  • Versione Chromium 90.0.4430.212
  • primo caricamento in una nuova finestra di navigazione in incognito


Nota sul First Input Delay: Ho aspettato che la pagina fosse completamente caricata e poi ho cliccato sullo sfondo - quindi dopo che il rendering di EmberJs è terminato.


Nota sul First Input Delay: Qui ho cliccato sullo sfondo immediatamente quando il contenuto statico è diventato visibile per la prima volta. Aggiungi il mio tempo di reazione :sloth: sopra questo FID.

Nota aggiuntiva sui percentili sotto le barre in questi grafici:
I percentili non sono molto rilevanti in quanto confrontano solo i valori misurati con i valori di origine. L’origine è una pagina web TYPO3 con un’installazione di Discourse in una sottocartella.

2 Mi Piace

Ottima idea! @rrit

Concordo pienamente che Discourse sia un’applicazione web molto lenta e pesante in JS. Se potessimo posticipare i file CSS/JS, aiuterebbe enormemente ad accelerare LCP, FCP, FID, CLS.

Sarebbe davvero utile vedere questo diventare realtà, noi e molte altre persone stiamo affrontando questo problema. Tutti i siti Discourse stanno fallendo nei Core Web Vitals. Se serviamo una pagina HTML STATICA veloce agli utenti la prima volta e/o posticipiamo tutta la logica JS/CSS nel primo caricamento iniziale, in questo modo possiamo velocizzare tutte le pagine e superare i punteggi CWV! Non vedo l’ora di vederlo attivo nel prossimo aggiornamento di Discourse.

Tutte le classifiche dei siti Discourse su Google stanno diminuendo a causa dei siti che non superano i Core Web Vitals.

2 Mi Piace

Siamo aperti a sperimentare questo nel core. Il “flash” di contenuti stilizzati in modo diverso può essere un po’ sconcertante, quindi vorremmo iniziare con esso dietro un’impostazione del sito “sperimentale” disabilitata per impostazione predefinita. In questo modo, gli amministratori del sito possono scegliere di abilitarlo se lo desiderano.

Sei in grado di provare ad aggiungere un’impostazione del sito nel tuo PR @rrit? Sarebbe anche utile aggiungere alcuni test RSpec per verificare il comportamento con l’impostazione abilitata/disabilitata.

5 Mi Piace

Non significa che possiamo semplicemente mettere uno spinner a schermo intero (che ha il 100% di larghezza e il 100% di altezza) sulla pagina renderizzata dal server e sostituirlo con l’app Ember quando finalmente si avvia per ottenere un LCP estremamente basso?

Potremmo rendere questo spinner un SVG che imita l’interfaccia utente di Discourse in modo che la transizione sia più fluida e meno simile a FOUC.

2 Mi Piace

Penso che la parte fondamentale sia LCP “candidate

Sarà considerato il largest contentful paint solo se è effettivamente il più grande (o almeno, delle stesse dimensioni) di ciò che viene infine renderizzato?

Quindi l’uso della vista crawler funziona abbastanza bene perché il contenuto (cioè il testo) è in gran parte lo stesso?

(Sto principalmente ipotizzando qui, basandomi sugli screenshot sopra - non ho provato uno spinner a schermo intero)

1 Mi Piace

Il feature flag è implementato.

Non sono affatto uno sviluppatore Ruby, su questo ho decisamente bisogno di aiuto.

Forse dovrei caricare il mio POC in un nuovo branch nel repository discourse/discourse, prima di fare un PR su main?

Questo è il mio PR su questa funzionalità:

@david Puoi darmi una mano nello sviluppo di test Rspec per queste modifiche:

app/helpers/application_helper.rb: spec/helpers/application_helper_spec.rb

Non vedo test unitari fattibili qui. Sembra testabile solo tramite test di integrazione.
app/models/theme.rb
app/models/theme_field.rb

Ho dovuto disabilitare il defer tag per QUnit Test Runner: app/views/qunit/index.html.erb
Prima i test QUnit venivano eseguiti anche con il feature flag "javascript defer" = false. E ora i test vengono eseguiti anche con "javascript defer" = true.

2 Mi Piace

Questo è probabilmente già bloccato da https://chromium.googlesource.com/chromium/src/+/master/docs/speed/metrics_changelog/2020_11_lcp.md:

Le immagini a schermo intero, che sono visivamente equivalenti alle immagini di sfondo, non sono più considerate come il largest contentful paint


Buon punto: vedi Largest Contentful Paint (LCP)  |  Articles  |  web.dev

Per gli elementi di testo, viene considerata solo la dimensione dei loro nodi di testo (il rettangolo più piccolo che racchiude tutti i nodi di testo).

Per tutti gli elementi, eventuali margini, padding o bordi applicati tramite CSS non vengono considerati.

  • Ecco perché il nodo di testo statico deve essere renderizzato esattamente della stessa dimensione del nodo di testo EmberJs.
  • O anche leggermente più grande aumentando il line-height.
    Ad esempio, se la larghezza dei nodi di testo non corrisponde, ci sono molti casi geometrici introdotti da diverse interruzioni di riga in cui il nodo di testo statico diventa più piccolo di quello EmberJs.

Vedi: Esempi LCP


In realtà ho usato il rendering noscript dei post all’interno di una pagina argomento. Le classi CSS corrispondono leggermente a quelle reali, quindi l’aspetto è uguale.

Vedi: Modifiche a app/views/layouts/application.html.erb

Modifica: Colpa mia, questa è in realtà la vista crawler: app/views/topics/show.html.erb

2 Mi Piace

Nel POC ci sono due funzionalità combinate - le dividiamo in due flag di funzionalità sperimentali?

  • JavaScript con tag defer (flag di funzionalità nella dashboard delle impostazioni)
    (flag di funzionalità nascosto poiché è necessaria una ricompilazione del container o una pulizia della cache del tema)Correzione: hot-switching con cache
  • Visualizzazione di contenuti statici nella vista argomento (flag di funzionalità nella dashboard delle impostazioni)

Ecco qui: flag di funzionalità


Naturalmente, l’impatto completo su LCP si ottiene solo utilizzando entrambi: FCP: contenuti statici

Potrebbero esserci istanze di Discourse in cui i plugin o i componenti del tema falliscono con il differimento del JS. Dividendo queste funzionalità, possono ottenere un piccolo guadagno sui contenuti statici senza differire il JS: FCP: contenuti statici senza differimento JS

2 Mi Piace

Prime impressioni da Google Search Console con il POC applicato dal 30/01/2022:

Desktop

Ci è voluto un po’ perché i risultati del desktop arrivassero:


Nota: la vecchia linea di base verde rappresenta le pagine web non-Discourse sullo stesso dominio.

Mobile


Nota: la vecchia linea di base verde rappresenta le pagine web non-Discourse sullo stesso dominio.

Aspettiamo altri 7-14 giorni per vedere, si spera, ulteriori miglioramenti per le pagine mobile poiché i valori vengono mediati negli ultimi 28 giorni - attualmente sono trascorsi solo 12 giorni con il POC applicato.

5 Mi Piace

Riepilogo LCP sulla Prova di Concetto

La POC è applicata dal 30/01/2022 e ci sono volute oltre 4 settimane per influenzare tutte le pagine nel report “Core Web Vitals” di Google Search Console, basato sui dati CrUX.

Tutte le pagine tematiche sono nella zona verde LCP (misurata da CrUX):

  • Desktop: LCP 1,7 sec
  • Mobile: LCP 2,0 sec

Dati LCP: Google Search Console/CrUX

Impressione da Google Search Console con la POC applicata dal 30/01/2022:

Desktop


Nota: la vecchia linea di base verde rappresenta le pagine web non-Discourse sullo stesso dominio.

URL Buoni

Mobile


Nota: la vecchia linea di base verde rappresenta le pagine web non-Discourse sullo stesso dominio.

URL Buoni

Problema LCP: più lungo di 2,5s (mobile)


Nota: solo le pagine tematiche mostrano contenuti statici prima del contenuto EmberJS


Approvazione PR con feature flags necessaria

@sam Potresti delegare questo PR a qualcuno per dare un’occhiata per l’approvazione, per favore.

3 Mi Piace

Certamente lo esamineremo attentamente, è un cambiamento molto grande e potrebbe volerci un po’ per arrivarci.

5 Mi Piace

@rrit grazie per aver condiviso i dati dal tuo sito! Ne abbiamo discusso internamente e temo che al momento non aggiungeremo questa funzionalità al core di Discourse.

Sebbene le metriche Web Vital che hai condiviso siano molto impressionanti, il lampo di contenuto “vista crawler” non offre una buona esperienza utente. Le modifiche di stile che hai apportato certamente aiutano, ma dovranno essere adattate per ogni sito Discourse con stile personalizzato.

Il nostro obiettivo a lungo termine è implementare il vero rendering lato server utilizzando qualcosa come Ember FastBoot. Teoricamente, ciò fornirebbe gli stessi miglioramenti statistici che hai misurato, offrendo al contempo un’esperienza utente senza interruzioni. Preferiremmo concentrare i nostri sforzi verso tale obiettivo.


Detto questo, Discourse è super estensibile, quindi penso che dovrebbe essere assolutamente possibile implementare la tua idea in un plugin Discourse e poi condividerla qui in Plugin.

La modifica più importante che hai apportato nel PR principale è l’aggiunta dell’attributo defer ai tag script. Sovrascrivere tutti quei punti da un plugin sarebbe molto difficile. Tuttavia, penso che lo stesso risultato potrebbe essere ottenuto con un approccio basato su middleware. Ho trovato questo post del blog che descrive un problema simile:

Utilizzando questa tecnica, potresti scrivere un middleware che controlla le risposte text/html, le analizza e quindi aggiunge gli attributi defer dove necessario.

L’aggiunta di middleware da un plugin può essere fatta in questo modo:

# name: my-plugin
# about: La descrizione del mio plugin
# version: 1.0
# url: https://example.org

require_relative "lib/script_defer_middleware"

on(:after_initializers) do
  Rails.configuration.middleware.use(ScriptDeferMiddleware)
end

Se incontri ostacoli con un approccio basato su plugin, non esitare a postare qui e saremo felici di provare a indicarti la giusta direzione.

10 Mi Piace

Se avrò tempo per questo, probabilmente implementerò un plugin.

Ma per ora cerco di cavarmela con un approccio di patching in web_only.yml:

# pseudo-codice non testato!
hooks:
  after_code:
    - exec:
        cd: $home
        cmd:
          - curl https://patch-diff.githubusercontent.com/raw/discourse/discourse/pull/15858.diff | git apply
4 Mi Piace

Ember FastBoot sembra un approccio a lungo termine perfetto. Nel frattempo, l’argomento LCP rimane caldo:

2 Mi Piace

Grazie per averci lavorato @rrit :+1:

Ho buone notizie, abbiamo implementato una nuova funzionalità in Discourse, che dovrebbe aiutare parecchio in questo senso

5 Mi Piace