Le mode sans interface graphique de Chrome bénéficie d'une amélioration : --headless=new

Le mode headless de Chrome s'est encore amélioré !

Peter Kvitek
Peter Kvitek

Le mode headless de Chrome s'est encore amélioré ! Cet article présente les récents efforts d'ingénierie visant à rendre le mode headless plus utile pour les développeurs en rapprochant le mode headless du mode headless habituel de Chrome.

Contexte

En 2017, Chrome 59 a lancé le mode headless, qui vous permet d'exécuter le navigateur dans un environnement autonome, sans interface utilisateur visible. En bref, vous pouvez exécuter Chrome sans Google Chrome !

Le mode sans interface graphique est un choix populaire pour l'automatisation des navigateurs à l'aide de projets tels que Puppeteer ou ChromeDriver. Voici un exemple minimal de ligne de commande qui illustre l'utilisation du mode headless pour créer un fichier PDF à partir d'une URL donnée:

chrome --headless --print-to-pdf https://developer.chrome.com/

Nouveautés de Headless

Avant de nous plonger dans les récentes améliorations sans interface graphique, il est important de comprendre comment fonctionnait l'ancienne version. L'extrait de ligne de commande que nous avons montré précédemment utilise l'indicateur de ligne de commande --headless, suggérant que Headless n'est qu'un mode de fonctionnement du navigateur Chrome standard. Étonnamment, ce n'était peut-être pas vrai. Techniquement, l'ancienne interface headless était une autre implémentation de navigateur qui avait été intégrée au même binaire Chrome. Il ne partage aucun du code du navigateur Chrome dans //chrome.

Comme vous pouvez l'imaginer, l'implémentation et la maintenance de ce navigateur headless séparé impliquaient de nombreuses tâches techniques. Mais ce n'était pas le seul problème. Comme Headless était une implémentation distincte, il possédait ses propres bugs et fonctionnalités qui n'étaient pas présents dans Headful Chrome. Cette situation déroutante : tout test automatisé de navigateur pouvait passer en mode headless, mais échouer en mode headless, ou inversement. C'était un problème majeur pour les ingénieurs en automatisation. Elle excluait également les tests automatisés qui dépendaient de l'installation d'une extension de navigateur, par exemple. Il en va de même pour toutes les autres fonctionnalités au niveau du navigateur: à moins que Headless n'ait sa propre implémentation distincte de celle-ci, elle n'était pas prise en charge.

En 2021, l'équipe Chrome a entrepris de résoudre ce problème et d'unifier les modes headless et headless.

La nouvelle version de Chrome sans interface graphique n'est plus une implémentation distincte du navigateur. Elle partage désormais du code avec Chrome.

Nous sommes heureux d'annoncer que le nouveau mode headless est désormais disponible dans Chrome 112. Dans ce mode, Chrome crée des fenêtres de plate-forme, mais ne les affiche pas. Toutes les autres fonctionnalités, existantes et futures, sont disponibles sans limite.

Essayer le nouveau headless

Pour essayer le nouveau mode headless, transmettez l'indicateur de ligne de commande --headless=new:

chrome --headless=new

Pour l'instant, l'ancien mode headless est toujours disponible via:

chrome --headless=old

Actuellement, la transmission de l'indicateur de ligne de commande --headless sans valeur explicite active toujours l'ancien mode headless. Toutefois, nous prévoyons de remplacer cette valeur par défaut par le nouveau mode headless au fil du temps.

Nous prévoyons de supprimer complètement l'ancien mode headless du binaire Chrome et de ne plus prendre en charge ce mode dans Puppeteer dans le courant de l'année. Dans le cadre de cette suppression, l'ancienne version sans interface graphique sera disponible en tant que binaire autonome pour les utilisateurs qui ne peuvent pas encore effectuer la mise à niveau.

Nouveau headless dans Puppeteer

Pour activer le nouveau mode headless dans 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();

Nouveau headless dans Selenium-WebDriver

Pour utiliser le nouveau mode headless dans Selenium-WebDriver:

const driver = await env
  .builder()
  .setChromeOptions(options.addArguments('--headless=new'))
  .build();

await driver.get('https://developer.chrome.com/');

// …

await driver.quit();

Consultez l'article de blog de l'équipe Selenium pour obtenir plus d'informations, y compris des exemples utilisant d'autres liaisons.

Options de ligne de commande spécifiques sans interface graphique

Les options de ligne de commande suivantes sont disponibles pour le nouveau mode headless.

--dump-dom

L'indicateur --dump-dom imprime le DOM sérialisé de la page cible sur stdout. Exemple :

chrome --headless=new --dump-dom https://developer.chrome.com/

Notez que cela diffère de l'impression du code source HTML (ce que vous pourriez faire avec curl). Pour obtenir la sortie de --dump-dom, Chrome analyse d'abord le code HTML dans un DOM, exécute toute <script> susceptible de modifier le DOM, puis reconvertit ce DOM en une chaîne HTML sérialisée.

--screenshot

L'indicateur --screenshot effectue une capture d'écran de la page cible et l'enregistre sous le nom screenshot.png dans le répertoire de travail actuel. Elle est particulièrement utile lorsqu'elle est combinée à l'indicateur --window-size. Exemple :

chrome --headless=new --screenshot --window-size=412,892 https://developer.chrome.com/

--print-to-pdf

L'indicateur --print-to-pdf enregistre la page cible au format PDF nommé output.pdf dans le répertoire de travail actuel. Exemple :

chrome --headless=new --print-to-pdf https://developer.chrome.com/

Vous pouvez éventuellement ajouter l'indicateur --no-pdf-header-footer pour omettre l'en-tête d'impression (avec la date et l'heure actuelles) et le pied de page (avec l'URL et le numéro de page).

chrome --headless=new --print-to-pdf --no-pdf-header-footer https://developer.chrome.com/

--timeout

L'indicateur --timeout définit le temps d'attente maximal (en millisecondes) au terme duquel le contenu de la page est capturé par --dump-dom, --screenshot et --print-to-pdf, même si la page est toujours en cours de chargement.

chrome --headless=new --print-to-pdf --timeout=5000 https://developer.chrome.com/

L'indicateur --timeout=5000 indique à Chrome d'attendre jusqu'à cinq secondes avant d'imprimer le PDF. L'exécution de ce processus ne prend donc pas plus de 5 secondes.

--virtual-time-budget

--virtual-time-budget permet de voyager dans le temps. Eh bien, dans une certaine mesure. Le temps virtuel permet d'avancer rapidement pour tout code dépendant du temps (par exemple, setTimeout/setInterval). Il oblige le navigateur à exécuter le code de la page le plus rapidement possible tout en faisant croire à la page que le temps passe réellement.

Pour bien comprendre son utilisation, prenons cette page de démonstration qui incrémente, consigne et affiche un compteur toutes les secondes à l'aide de setTimeout(fn, 1000). Voici le code correspondant:

<output>0</output>
<script>
  const element = document.querySelector('output');
  let counter = 0;
  setInterval(() => {
    counter++;
    console.log(counter);
    element.textContent = counter;
  }, 1_000);
</script>

Après une seconde, la page affiche "1", après deux secondes, "2", et ainsi de suite. Voici comment capturer l'état de la page au bout de 42 secondes et l'enregistrer au format PDF:

chrome --headless=new --print-to-pdf --virtual-time-budget=42000 https://mathiasbynens.be/demo/time

--allow-chrome-scheme-url

L'indicateur --allow-chrome-scheme-url est requis pour accéder aux URL chrome://. Il est disponible à partir de Chrome 123. Exemple :

chrome --headless=new --print-to-pdf --allow-chrome-scheme-url chrome://gpu

Débogage

Chrome étant effectivement invisible en mode headless, il peut sembler difficile de comprendre ce qui se passe en cas de problème. Heureusement, il est possible de déboguer Chrome headless. L'astuce consiste à lancer Chrome en mode headless avec l'indicateur de ligne de commande --remote-debugging-port.

chrome --headless=new --remote-debugging-port=0 https://developer.chrome.com/

Cela imprime une URL WebSocket unique sur stdout, par exemple:

DevTools listening on ws://127.0.0.1:60926/devtools/browser/b4bd6eaa-b7c8-4319-8212-225097472fd9

Dans une instance Chrome headless standard, nous pouvons ensuite utiliser le débogage à distance des outils pour les développeurs Chrome pour nous connecter à la cible sans interface graphique et l'inspecter. Pour ce faire, accédez à chrome://inspect, cliquez sur le bouton Configure... (Configurer), puis saisissez l'adresse IP et le numéro de port de l'URL WebSocket. Dans l'exemple ci-dessus, j'ai saisi 127.0.0.1:60926. Cliquez sur OK. Vous devriez voir une cible distante s'afficher avec tous ses onglets et autres cibles listés ci-dessous. Cliquez sur inspect. Vous avez désormais accès aux outils pour les développeurs Chrome qui inspectent la cible distante sans interface graphique, et inspect.

Les outils pour les développeurs Chrome peuvent inspecter une page cible distante sans interface graphique

Commentaires

Nous avons hâte de recevoir vos commentaires sur le nouveau mode headless. Si vous rencontrez des problèmes, veuillez les signaler.