Traitement efficace en arrière-plan

Fonctionnalités Web : content-visibility

Mettez en pause les tâches d'arrière-plan lourdes lorsqu'un composant n'est pas affiché par le navigateur afin de préserver les ressources système et l'autonomie de la batterie.

Présentation

La propriété content-visibility: auto permet au navigateur d'ignorer les calculs de rendu pour les éléments qui se trouvent loin de la fenêtre d'affichage. Lorsque le navigateur décide d'ignorer ou de reprendre l'affichage d'un élément, il déclenche l'événement contentvisibilityautostatechange sur cet élément.

En écoutant cet événement, vous pouvez suspendre les opérations coûteuses telles que les animations <canvas>, l'affichage WebGL ou l'interrogation de données WebSocket à haute fréquence lorsqu'elles ne sont pas nécessaires, et les reprendre juste à temps lorsque le navigateur se prépare à afficher le contenu.

contentvisibilityautostatechange par rapport à IntersectionObserver

Il est important de comprendre quand utiliser chaque API :

  • Utilisez IntersectionObserver pour la logique d'application liée à la visibilité visuelle exacte d'un élément dans la fenêtre d'affichage (par exemple, le chargement différé des données, les déclencheurs de défilement infini).
  • Utilisez contentvisibilityautostatechange pour les tâches nécessitant un rendu important (comme les mises à jour de canevas complexes ou les mutations DOM lourdes). Cet événement est directement lié au cycle de vie de rendu interne du navigateur. Le navigateur commence souvent à afficher un élément avant qu'il n'apparaisse réellement à l'écran (marge de préaffichage). Cet événement vous indique quand cela se produit, ce qui vous permet de vous assurer que votre contenu est prêt à être vu.

Implémentation

1. Appliquer la visibilité du contenu CSS

Définissez content-visibility: auto sur le conteneur lourd et indiquez une taille d'espace réservé pour éviter que la barre de défilement ne saute.

.heavy-component {
  /* Defer rendering work when off-screen */
  content-visibility: auto;
  
  /* Mandatory: Provide a placeholder size to prevent layouts shifts.
    - 'auto' is optional and enables the browser to remember the actual size
      once rendered. It must be paired with a <length> value to be used for
      the first render.
    - 'none' tells the browser not to apply any intrinsic width to this element.
      It can be used for either the height or the width value.
    - '500px' is the estimated height of this element. This can be any valid
      CSS <length> value. Replace it with the expected height of your
      component.
   */
  contain-intrinsic-size: auto none auto 500px;
}

2. Écouter les changements d'état

Ajoutez un écouteur d'événements pour contentvisibilityautostatechange afin de mettre en pause ou de reprendre les tâches en arrière-plan.

const component = document.querySelector('.heavy-component');

// Option 1: Direct listener (recommended)
component.addEventListener('contentvisibilityautostatechange', (event) => {
  if (event.skipped) {
    // The browser skipped rendering this content.
    // DO NOT perform heavy mutations or animation loops here.
    stopSimulation();
    pauseWebSocketPolling();
  } else {
    // The browser is about to render the content.
    // Resume your work so it is ready when visible.
    startSimulation();
    resumeWebSocketPolling();
  }
});

// Option 2: Capturing listener for event delegation
document.addEventListener('contentvisibilityautostatechange', (event) => {
  if (event.target.matches('.heavy-component')) {
    if (event.skipped) {
      stopSimulation();
    } else {
      startSimulation();
    }
  }
}, { capture: true });

Stratégies de remplacement

La propriété content-visibility et l'événement contentvisibilityautostatechange associé sont des améliorations progressives. Dans les navigateurs qui ne sont pas compatibles :

  • La propriété CSS est ignorée et le contenu s'affiche normalement.
  • L'événement ne se déclenche jamais. Les tâches en arrière-plan continuent donc de s'exécuter comme elles le feraient normalement sans optimisation.

Si vous devez prendre en charge la mise en pause des tâches sur les anciens navigateurs, vous pouvez utiliser IntersectionObserver comme approximation. Cela permet également d'économiser la batterie et le processeur sur les appareils plus anciens.

// Fallback using IntersectionObserver for older browsers
const target = document.getElementById('target-container');

// Check if content-visibility is supported
const isSupported = 'contentVisibility' in document.documentElement.style;

if (!isSupported) {
  const observer = new IntersectionObserver((entries) => {
    entries.forEach(entry => {
      if (entry.isIntersecting) {
        // The element is close to the screen. Start work!
        startSimulation();
      } else {
        // The element is far away. Pause work!
        stopSimulation();
      }
    });
  }, {
    // Use rootMargin to start rendering before it hits the screen
    rootMargin: '200px'
  });

  observer.observe(target);
}