La modalità headless di Chrome è migliorata molto.
La modalità headless di Chrome è migliorata molto. Questo articolo presenta una panoramica dei recenti sforzi di progettazione per rendere Headless più utile per gli sviluppatori avvicinando Headless alla modalità "headful" standard di Chrome.
Contesto
Nel 2017, in Chrome 59 è stata introdotta la cosiddetta modalità headless, che consente di eseguire il browser in un ambiente automatico senza UI visibile. Essenzialmente, uso Chrome senza Chrome.
La modalità headless è una scelta popolare per l'automazione del browser tramite progetti come Puppeteer o ChromeDriver. Di seguito è riportato un esempio minimo della riga di comando relativo all'utilizzo della modalità headless per creare un file PDF di un determinato URL:
chrome --headless --print-to-pdf https://developer.chrome.com/
Novità di Headless
Prima di addentrarci nei recenti miglioramenti di Headless, è importante capire come funzionava il "vecchio" modello Headless. Lo snippet della riga di comando che abbiamo mostrato in precedenza utilizza il flag della riga di comando --headless
, a indicare che Headless è solo una modalità di funzionamento del normale browser Chrome. Forse, sorprendentemente, questo non era vero. Tecnicamente, il vecchio Headless era un'implementazione separata del browser alternativo che veniva fornita come parte dello stesso file binario di Chrome. Il codice non condivide nessuno del codice del browser Chrome in //chrome
.
Come puoi immaginare, l'implementazione e la gestione di questo browser headless separato comportava un grande sovraccarico tecnico, ma non era l'unico problema. Poiché Headless era un'implementazione separata, aveva i propri bug e le proprie funzionalità non presenti in Chrome headless. Questo creava una situazione poco chiara in cui qualsiasi test automatico del browser poteva passare in modalità headful ma non riuscire in modalità headless o viceversa, un problema grave per gli ingegneri dell'automazione. Sono inoltre esclusi i test automatici basati sull'installazione di un'estensione del browser, ad esempio. Lo stesso vale per qualsiasi altra funzionalità a livello di browser: a meno che Headless non avesse una propria implementazione separata, non era supportata.
Nel 2021, il team di Chrome ha deciso di risolvere questo problema e unificare le modalità Headless e Headful una volta per tutte.
Siamo lieti di annunciare che la nuova modalità headless è ora disponibile in Chrome 112. In questa modalità Chrome crea, ma non visualizza le finestre della piattaforma. Tutte le altre funzionalità, esistenti e future, sono disponibili senza limitazioni.
Prova il nuovo Headless
Per provare la nuova modalità headless, passa il flag della riga di comando --headless=new
:
chrome --headless=new
Per il momento, la vecchia modalità headless è ancora disponibile tramite:
chrome --headless=old
Al momento, il passaggio del flag della riga di comando --headless
senza un valore esplicito attiva comunque la vecchia modalità Headless, ma abbiamo in programma di cambiare questa impostazione predefinita in nuova modalità Headless nel tempo.
Prevediamo di rimuovere completamente il vecchio Headless dal programma binario di Chrome e interrompere il supporto di questa modalità in Puppeteer entro la fine dell'anno. Nell'ambito di questa rimozione, renderemo disponibile la versione precedente di Headless come file binario autonomo separato per gli utenti che non possono ancora eseguire l'upgrade.
Nuovo Headless in Puppeteer
Per attivare la nuova modalità headless in Puppeteer:
import puppeteer from 'puppeteer';
const browser = await puppeteer.launch({
headless: 'new',
// `headless: true` (default) enables old Headless;
// `headless: 'new'` enables new Headless;
// `headless: false` enables "headful" mode.
});
const page = await browser.newPage();
await page.goto('https://developer.chrome.com/');
// …
await browser.close();
Nuovo Headless in Selenium-WebDriver
Per utilizzare la nuova modalità headless in Selenium-WebDriver:
const driver = await env
.builder()
.setChromeOptions(options.addArguments('--headless=new'))
.build();
await driver.get('https://developer.chrome.com/');
// …
await driver.quit();
Consulta il post del blog del team di Selenium per ulteriori informazioni, inclusi esempi di associazioni di lingue.
Flag della riga di comando specifici per headless
Per la nuova modalità headless sono disponibili i seguenti flag della riga di comando.
--dump-dom
Il flag --dump-dom
stampa il DOM serializzato della pagina di destinazione su stdout. Esempio:
chrome --headless=new --dump-dom https://developer.chrome.com/
Tieni presente che questa operazione è diversa dalla semplice stampa del codice sorgente HTML (operazione che potresti fare con curl
). Per ottenere l'output di --dump-dom
, Chrome analizza prima il codice HTML in un DOM, esegue qualsiasi <script>
che potrebbe alterare il DOM, quindi trasforma nuovamente questo DOM in una stringa serializzata di HTML.
--screenshot
Il flag --screenshot
acquisisce uno screenshot della pagina di destinazione e lo salva come screenshot.png
nella directory di lavoro corrente. È particolarmente utile in combinazione con il flag --window-size
. Esempio:
chrome --headless=new --screenshot --window-size=412,892 https://developer.chrome.com/
--print-to-pdf
Il flag --print-to-pdf
salva la pagina di destinazione come PDF denominato output.pdf
nella directory di lavoro corrente. Esempio:
chrome --headless=new --print-to-pdf https://developer.chrome.com/
Se vuoi, puoi aggiungere il flag --no-pdf-header-footer
per omettere l'intestazione di stampa (con la data e l'ora correnti) e il piè di pagina (con l'URL e il numero di pagina).
chrome --headless=new --print-to-pdf --no-pdf-header-footer https://developer.chrome.com/
--timeout
Il flag --timeout
definisce il tempo di attesa massimo (in millisecondi) dopo il quale i contenuti della pagina vengono acquisiti da --dump-dom
, --screenshot
e --print-to-pdf
anche se la pagina è ancora in fase di caricamento.
chrome --headless=new --print-to-pdf --timeout=5000 https://developer.chrome.com/
Il flag --timeout=5000
indica a Chrome di attendere fino a 5 secondi prima di stampare il PDF. Pertanto, l'esecuzione di questo processo richiede al massimo 5 secondi.
--virtual-time-budget
Il --virtual-time-budget
consente il viaggio nel tempo. Beh, in una certa misura. Virtual Time agisce come un "avanzamento veloce" per qualsiasi codice dipendente dal tempo (ad esempio, setTimeout
/setInterval
). Forza il browser a eseguire il codice della pagina il più velocemente possibile, facendo credere alla pagina che il tempo passi effettivamente.
Per illustrarne l'utilizzo, prendi in considerazione questa pagina demo che incrementa, registra e visualizza un contatore ogni secondo utilizzando setTimeout(fn, 1000)
. Ecco il codice pertinente:
<output>0</output>
<script>
const element = document.querySelector('output');
let counter = 0;
setInterval(() => {
counter++;
console.log(counter);
element.textContent = counter;
}, 1_000);
</script>
Dopo un secondo, la pagina contiene "1"; dopo due secondi, "2" e così via. Ecco come acquisire lo stato della pagina dopo 42 secondi e salvarla in formato PDF:
chrome --headless=new --print-to-pdf --virtual-time-budget=42000 https://mathiasbynens.be/demo/time
--allow-chrome-scheme-url
Il flag --allow-chrome-scheme-url
è necessario per accedere a chrome://
URL. Questo flag è disponibile a partire da Chrome 123. Esempio:
chrome --headless=new --print-to-pdf --allow-chrome-scheme-url chrome://gpu
Debug
Poiché Chrome è effettivamente invisibile in modalità headless, potrebbe sembrare difficile capire cosa sta succedendo in caso di problemi. Fortunatamente, è possibile eseguire il debug di Chrome headless in un modo molto simile a Chrome headful. Il trucco consiste nell'avviare Chrome in modalità headless con il flag della riga di comando --remote-debugging-port
.
chrome --headless=new --remote-debugging-port=0 https://developer.chrome.com/
Viene visualizzato un URL WebSocket univoco su stdout, ad esempio:
DevTools listening on ws://127.0.0.1:60926/devtools/browser/b4bd6eaa-b7c8-4319-8212-225097472fd9
In una normale istanza di Chrome headless, possiamo quindi utilizzare il debug remoto di Chrome DevTools per stabilire la connessione alla destinazione headless e ispezionarla. Per farlo, vai a chrome://inspect
, fai clic sul pulsante Configura... e inserisci l'indirizzo IP e il numero di porta dall'URL di WebSocket. Nell'esempio riportato sopra, ho inserito 127.0.0.1:60926
. Fai clic su Fine. Dovresti vedere un target remoto con tutte le relative schede e gli altri target elencati di seguito. Fai clic su inspect per poter accedere a Chrome DevTools che ispeziona il target headless remoto, inspect.
Feedback
Non vediamo l'ora di ricevere il tuo feedback sulla nuova modalità headless. Se riscontri problemi, segnalali.