Génération PDF dynamique : ingénierie du papier numérique
Comment générer des PDF haute fidélité (factures, tickets) à l'aide de React et Node.js. Une comparaison de @react-pdf/renderer et Puppeteer dans des environnements sans serveur.
Le monde fonctionne en HTML, mais les entreprises fonctionnent en PDF. Une commande de commerce électronique n’est « réelle » que lorsqu’il y a une facture. Un billet de concert n’est “valable” que lorsqu’il y a un code QR sur un PDF. Pendant des années, générer des PDF a été la tâche la plus détestée dans le développement backend. Cela impliquait des outils archaïques comme « wkhtmltopdf », des modèles XML ou des scripts Python fragiles.
Chez Maison Code Paris, nous faisons entrer la génération PDF dans l’ère moderne. Nous utilisons la même architecture de composants (React) pour nos documents que pour nos interfaces utilisateur. Cela garantit que la cohérence de la marque est absolue. La police sur le site Web est la police sur la facture.
Pourquoi Maison Code en parle
Chez Maison Code Paris, nous agissons comme la conscience architecturale de nos clients. Nous héritons souvent de piles « modernes » qui ont été construites sans une compréhension fondamentale de l’échelle. Nous voyons des API simples qui mettent 4 secondes à répondre en raison de problèmes de requête N+1, et des « microservices » qui coûtent 5 000 €/mois en frais de cloud inactif.
Nous abordons ce sujet car il représente un point pivot critique dans la maturité de l’ingénierie. La mise en œuvre correcte de cela différencie un MVP fragile d’une plate-forme résiliente de niveau entreprise qui peut gérer le trafic du Black Friday sans transpirer.
Le paysage : Comment rendre un PDF
Il existe aujourd’hui trois manières principales de générer un PDF, chacune comportant d’énormes compromis.
| Approche | Outillage | Avantages | Inconvénients |
|---|---|---|---|
| Sans navigateur (Chrome sans tête) | Marionnettiste, dramaturge | Prise en charge CSS au pixel près. Si vous pouvez le créer en HTML, vous pouvez l’imprimer. | Lent. Utilisation importante de la mémoire. Nécessite le lancement d’une instance de navigateur (Chromium) ce qui est pénible en Serverless. |
| Primitives PDF | PDFKit, jsPDF | Extrêmement rapide. Zéro dépendance. | Développeur H*. Vous devez tracer des lignes manuellement (doc.moveTo(100, 100).lineTo(200, 200)). La maintenance des mises en page est un cauchemar. |
| React-PDF / @react-pdf/renderer | Réagir, Flexbox | Le Saint Graal. Écrivez des composants React, obtenez un PDF. Assez vite. | Sous-ensemble CSS uniquement (Flexbox principalement). Pas encore de support Grid. |
Chez Maison Code, nous standardisons strictement React-PDF.
L’architecture : pourquoi React-PDF gagne
Le changement de modèle mental est simple : Un PDF n’est qu’une autre cible de rendu. Tout comme « ReactDOM » est rendu dans le DOM et « ReactNative » dans les vues iOS/Android, « @react-pdf/renderer » est rendu dans la spécification PDF.
1. Partage de codes
Vous pouvez partager vos types de jetons Design System.
importer { StyleSheet } depuis '@react-pdf/renderer' ;
importer { thème } depuis '@/design-system/theme' ;
const styles = StyleSheet.create({
en-tête : {
fontFamily : theme.fonts.heading, // "Bodoni Moda"
couleur : theme.colors.void, // #000000
Taille de la police : 24,
}
});
Cela garantit que votre facture correspond à votre page de paiement pixel pour pixel.
2. Démarrages à froid sans serveur
Exécuter Puppeteer sur AWS Lambda est une bataille constante contre la limite de package de 50 Mo et les démarrages à froid de 10 secondes. React-PDF n’est qu’une bibliothèque Node.js. Il ajoute effectivement 0 ms à votre démarrage à froid. Il compile les chaînes dans des tampons binaires. Il est lié au processeur et non aux E/S.
Implémentation : Le volet « Papier Numérique »
Voici un exemple concret d’un composant Facture.
importer {Document, Page, Texte, Vue, Feuille de style, Police} depuis '@react-pdf/renderer' ;
// Enregistrer les polices personnalisées (critique pour l'image de marque)
Font.register({
famille : 'Bodoni Moda',
src : 'https://cdn.maisoncode.paris/fonts/BodoniModa-Regular.ttf'
});
const Facture = ({ commande }) => (
<Document>
<Page size="A4" style={styles.page}>
{/* En-tête */}
<Style d'affichage={styles.header}>
<Text style={styles.brand}>CODE MAISON.</Text>
<Text style={styles.invoiceId}>INV-{order.id}</Text>
</Vue>
{/* Éléments de campagne */}
<Style d'affichage={styles.table}>
{order.items.map(article => (
<Style d'affichage={styles.row}>
<Text style={styles.cellDesc}>{item.name}</Text>
<Text style={styles.cellQty}>x{item.quantity}</Text>
<Text style={styles.cellTotal}>€{item.price}</Text>
</Vue>
))}
</Vue>
{/* Pied de page */}
<Style d'affichage={styles.footer}>
<Texte>Merci pour votre confiance. Ce document est un original numérique.</Text>
</Vue>
</Page>
</Document>
);
Le point de terminaison de l’API
Vous n’enregistrez pas les fichiers sur le disque. Vous les diffusez directement sur le client ou S3.
// Route API Next.js / Node.js
importer { renderToStream } depuis '@react-pdf/renderer' ;
exporter la fonction asynchrone POST(req) {
const stream = wait renderToStream(<Invoice order={req.body} />);
renvoyer une nouvelle réponse (stream, {
en-têtes : {
'Type de contenu' : 'application/pdf',
'Content-Disposition' : 'pièce jointe ; nom de fichier="facture.pdf"'
}
});
}
Performances : la règle des 500 ms
En e-commerce, si le bouton « Télécharger la facture » tourne pendant 5 secondes, l’utilisateur suppose que le site est en panne. Puppeteer prend 3 à 8 secondes pour démarrer, naviguer et imprimer. React-PDF prend 200 à 600 ms pour afficher une facture complexe.
Cette différence de vitesse vous permet de générer des PDF de manière synchrone à la demande, plutôt que de les mettre en file d’attente dans un travail en arrière-plan (Céleri/SQS) et de les envoyer par courrier électronique plus tard. Une pièce mobile en moins. Une file d’attente en moins à surveiller.
Conclusion
Arrêtez de traiter les PDF comme des citoyens de seconde zone. En adoptant React-PDF, vous intégrez la couche de documents à votre flux de travail d’ingénierie standard.
- Contrôle de version : vos modèles de facture sont suivis par Git.
- Sécurité des types : Votre génération de PDF échoue au moment de la construction si vous manquez un champ « prix ».
- Consistance du design : votre marque reste premium, même sur papier.
Dans le secteur du luxe, l’expérience post-achat est aussi importante que la vente. Une belle facture instantanée est la touche finale d’une transaction premium.
Embauchez nos architectes pour auditer votre pipeline de génération de documents.