Qu'est-ce que la pagination ?
La pagination est une technique qui divise un grand ensemble de résultats en pages de taille fixe pour améliorer les performances et l'expérience utilisateur. Au lieu de charger 10 000 résultats d'un coup, on charge 20 éléments par page. La pagination est presente partout : résultats de recherche Google, feeds de réseaux sociaux, listes de produits e-commerce, tables de données administratives.
Pagination par offset (traditionnelle)
La méthode classique utilise OFFSET et LIMIT en SQL : SELECT * FROM products ORDER BY id LIMIT 20 OFFSET 40 pour la page 3. Simple à implémenter et permet le saut direct à une page. Inconvénients : performance degradee sur les grandes tables (la base doit scanner toutes les lignes avant l'offset), résultats instables si des éléments sont ajoutes ou supprimes entre deux pages (éléments manques ou dupliques).
Pagination par curseur (keyset)
La pagination par curseur utilise la dernière valeur vue comme point de départ : SELECT * FROM products WHERE id > :last_id ORDER BY id LIMIT 20. Performante quel que soit la profondeur (utilise l'index directement), résultats stables. Le curseur est généralement encode en base64 et envoye au client. Inconvenient : pas de saut direct à une page, navigation uniquement sequentielle (précédent/suivant). Idéal pour les feeds infinis (scroll infini) et les API.
Pagination dans les API
Le pattern Relay (GraphQL) standardise la pagination par curseur avec edges (éléments), pageInfo (hasPreviousPage, hasNextPage, startCursor, endCursor), et les arguments first/after et last/before. En REST, les conventions varient : Link header avec rel=next/prev, enveloppe JSON avec meta (total, page, per_page, next_cursor). Toujours inclure le nombre total d'éléments (ou une indication s'il y a plus de résultats) pour l'affichage de la pagination.
Stratégies pour les grandes tables
Pour les tables avec des millions de lignes, des stratégies supplémentaires sont nécessaires. Estimated count : pg_class.reltuples dans PostgreSQL pour un comptage approximatif instantané plutôt que COUNT(*) (qui parcourt toute la table). Materialized views : pre-calculer les listes paginees pour les requêtes fréquentes. Search engine : Elasticsearch ou Typesense pour la pagination de résultats de recherche avec facettes.
Pagination cote client
En frontend, la pagination prend différentes formes : pagination classique (boutons de page, adapte aux tables de données), scroll infini (chargement automatique avec IntersectionObserver, adapte aux feeds), load more (bouton "charger plus", compromis entre les deux). Le scroll infini doit gérer la performance (virtualisation des éléments hors écran), l'accessibilité (navigation clavier), et le SEO (les pages suivantes doivent avoir des URL indexables).