Cloudflare Pages et Cloudflare Workers représentent l'évolution la plus significative de Cloudflare vers une plateforme de développement complète. Là où le CDN et le WAF protègent et accélèrent vos sites existants, Pages et Workers vous permettent de construire et déployer directement sur le réseau Edge mondial de Cloudflare, dans plus de 310 datacenters simultanément. Cloudflare Pages est la réponse de Cloudflare à Netlify et Vercel : une plateforme de déploiement continu pour sites statiques et applications web modernes (Next.js, Nuxt, SvelteKit, Gatsby), avec intégration Git native, previews automatiques sur chaque pull request, et déploiements mondiaux en quelques secondes. Cloudflare Workers est un moteur d'exécution JavaScript/TypeScript (et Rust, Python via WASM) à la périphérie du réseau, permettant de créer des APIs, des middlewares, des transformations de réponses et des logiques métier complexes sans serveur à gérer. Ensemble, ils forment une stack fullstack serverless capable de supporter des milliers de requêtes par seconde avec une latence sub-milliseconde, des coûts bien inférieurs aux équivalents AWS Lambda/Vercel, et une sécurité renforcée grâce à l'isolation V8 Isolates et l'intégration native avec le WAF Cloudflare. Ce guide complet couvre l'ensemble du cycle de développement, du premier déploiement à la gestion des données avec KV et D1, en passant par la sécurisation des déploiements dans un contexte DevSecOps exigeant.

\n\n

Cloudflare Pages vs Workers : deux approches complémentaires

\n\n

La distinction entre Pages et Workers est fondamentale pour choisir le bon outil :

\n\n

Cloudflare Pages

\n

Pages est une plateforme de déploiement de sites statiques et d'applications Jamstack. Son workflow est centré sur Git : vous connectez votre dépôt GitHub ou GitLab, configurez la commande de build, et Cloudflare s'occupe du reste. Chaque push déclenche un build et un déploiement automatique.

\n\n

Caractéristiques principales :

\n
    \n
  • Déploiement global automatique sur l'Edge Cloudflare
  • \n
  • HTTPS automatique avec certificats gérés
  • \n
  • Previews de déploiement sur chaque branch/PR
  • \n
  • Pages Functions : logique serverless intégrée à vos pages statiques
  • \n
  • Intégration native avec les autres produits Cloudflare (KV, D1, R2)
  • \n
\n\n

Cloudflare Workers

\n

Workers est un moteur d'exécution de code JavaScript/TypeScript directement sur les serveurs Edge de Cloudflare. Contrairement aux fonctions serverless traditionnelles (Lambda, Cloud Functions) qui tournent dans des conteneurs avec des cold starts de 100-500ms, Workers utilise V8 Isolates : le code démarre en moins d'une milliseconde et s'exécute dans un environnement isolé par requête.

\n\n

Caractéristiques principales :

\n
    \n
  • Latence d'exécution inférieure à 1ms (pas de cold start)
  • \n
  • Accès à toutes les APIs Web modernes (fetch, crypto, streams)
  • \n
  • Intégration avec KV, D1, R2, Queues, Durable Objects
  • \n
  • Déploiement CLI via Wrangler
  • \n
  • Support TypeScript natif
  • \n
\n\n

Quand utiliser l'un ou l'autre ?

\n\n\n\n\n\n\n\n\n\n\n
Cas d'usagePagesWorkers
Site statique (blog, doc)OuiNon
Application Next.js/NuxtOui (avec Functions)Oui (manuel)
API REST/GraphQLVia FunctionsRecommandé
Middleware HTTP (auth, redirect)NonOui
Transformation de réponsesNonOui
Webhook handlerVia FunctionsRecommandé
\n\n

Cloudflare Pages — Déployer un site statique depuis GitHub/GitLab

\n\n

Le déploiement d'un premier site avec Cloudflare Pages prend moins de 5 minutes.

\n\n

Connexion du dépôt Git

\n\n
    \n
  1. Connectez-vous à dash.cloudflare.com
  2. \n
  3. Naviguez vers Workers & Pages > Pages > Create a project
  4. \n
  5. Sélectionnez "Connect to Git"
  6. \n
  7. Autorisez Cloudflare à accéder à votre compte GitHub ou GitLab
  8. \n
  9. Sélectionnez le dépôt à déployer
  10. \n
\n\n

Configuration du build

\n\n
# Exemple pour un site Next.js\nFramework preset: Next.js\nBuild command: npm run build\nBuild output directory: .next\nRoot directory: / (ou le sous-répertoire si monorepo)\n\n# Variables d'environnement de build\nNEXT_PUBLIC_API_URL = https://api.votre-site.com\nNODE_VERSION = 20
\n\n

Workflow de déploiement

\n\n
# Chaque push sur main déclenche un déploiement en production\ngit push origin main\n\n# Les branches/PR génèrent des previews automatiques\n# URL de preview : https://[branch-hash].votre-projet.pages.dev\n\n# Voir les déploiements en cours\nnpx wrangler pages deployment list --project-name=votre-projet
\n\n

Domaine personnalisé

\n\n

Depuis Pages > votre projet > Custom Domains :

\n
    \n
  1. Ajoutez votre domaine personnalisé
  2. \n
  3. Si le domaine est géré par Cloudflare DNS, la configuration est automatique
  4. \n
  5. Un certificat SSL est généré et renouvelé automatiquement
  6. \n
\n\n

Build presets et variables d'environnement

\n\n

Cloudflare Pages propose des presets de build pour les frameworks les plus populaires, ce qui simplifie considérablement la configuration initiale.

\n\n

Frameworks supportés nativement

\n\n
    \n
  • Next.js (App Router et Pages Router) : build command next build, output .next
  • \n
  • Nuxt 3 : build command nuxt build, output .output/public
  • \n
  • SvelteKit : avec l'adapter Cloudflare (@sveltejs/adapter-cloudflare)
  • \n
  • Remix : avec l'adapter Cloudflare Pages
  • \n
  • Astro : avec @astrojs/cloudflare
  • \n
  • Hugo : build command hugo, output public
  • \n
  • Jekyll : build command jekyll build, output _site
  • \n
  • Gatsby : build command gatsby build, output public
  • \n
\n\n

Variables d'environnement

\n\n
# wrangler.toml pour la gestion des variables\nname = "mon-projet"\ncompatibility_date = "2026-01-01"\n\n[vars]\nENVIRONMENT = "production"\nAPI_BASE_URL = "https://api.example.com"\n\n# Secrets (ne jamais mettre en clair dans wrangler.toml)\n# Configurer via le dashboard ou CLI :\nnpx wrangler pages secret put DATABASE_URL\nnpx wrangler pages secret put API_SECRET_KEY
\n\n

Environnements multiples

\n\n
# wrangler.toml avec environnements distincts\n[env.staging]\nvars = { ENVIRONMENT = "staging" }\n\n[env.production]\nvars = { ENVIRONMENT = "production" }
\n\n

La gestion des secrets dans les déploiements serverless est un point critique pour la sécurité. Consultez notre guide sur la conformité DORA pour les exigences de gestion des secrets dans les systèmes d'information critiques.

\n\n

Pages Functions — Logique serveur sur sites statiques

\n\n

Pages Functions permet d'ajouter des routes API et de la logique serveur directement dans votre projet Pages, sans déployer un Worker séparé. Les fonctions sont placées dans le répertoire /functions de votre projet.

\n\n

Structure des fichiers

\n\n
mon-projet/\n├── public/          # Fichiers statiques\n├── functions/       # Pages Functions\n│   ├── api/\n│   │   ├── hello.js          # /api/hello\n│   │   └── users/\n│   │       ├── index.js      # /api/users\n│   │       └── [id].js       # /api/users/:id\n│   └── _middleware.js        # Middleware global\n└── package.json
\n\n

Exemple de fonction API

\n\n
// functions/api/contact.js\nexport async function onRequestPost(context) {\n  const { request, env } = context;\n\n  const body = await request.json();\n  const { name, email, message } = body;\n\n  // Validation\n  if (!email || !message) {\n    return new Response(\n      JSON.stringify({ error: 'Email et message requis' }),\n      { status: 400, headers: { 'Content-Type': 'application/json' } }\n    );\n  }\n\n  // Stocker dans D1 (base SQLite serverless)\n  await env.DB.prepare(\n    'INSERT INTO contacts (name, email, message) VALUES (?, ?, ?)'\n  ).bind(name, email, message).run();\n\n  return new Response(\n    JSON.stringify({ success: true }),\n    { status: 200, headers: { 'Content-Type': 'application/json' } }\n  );\n}
\n\n

Middleware d'authentification

\n\n
// functions/_middleware.js\nexport async function onRequest(context) {\n  const { request, next, env } = context;\n\n  // Protéger les routes /admin/*\n  if (request.url.includes('/admin/')) {\n    const authHeader = request.headers.get('Authorization');\n    if (!authHeader || authHeader !== `Bearer ${env.ADMIN_SECRET}`) {\n      return new Response('Non autorisé', { status: 401 });\n    }\n  }\n\n  return next();\n}
\n\n

Cloudflare Workers — JavaScript à la périphérie du réseau

\n\n

Cloudflare Workers est la plateforme d'exécution de code la plus proche des utilisateurs finaux disponible à ce jour. Le code s'exécute dans des V8 Isolates — des environnements JavaScript légers et isolés qui démarrent en moins d'une milliseconde.

\n\n

Premier Worker avec Wrangler

\n\n
# Installer Wrangler\nnpm install -g wrangler\n\n# Authentification\nwrangler login\n\n# Créer un nouveau projet Worker\nnpm create cloudflare@latest mon-worker\n# Sélectionnez "Hello World" Worker\n\n# Structure créée :\n# src/index.ts  (ou .js)\n# wrangler.toml\n# package.json
\n\n

Worker de base (TypeScript)

\n\n
// src/index.ts\nexport default {\n  async fetch(\n    request: Request,\n    env: Env,\n    ctx: ExecutionContext\n  ): Promise<Response> {\n    const url = new URL(request.url);\n\n    // Router simple\n    if (url.pathname === '/api/health') {\n      return Response.json({ status: 'ok', timestamp: Date.now() });\n    }\n\n    if (url.pathname.startsWith('/api/')) {\n      return handleAPI(request, env);\n    }\n\n    // Fallback vers l'origine ou une réponse statique\n    return new Response('Not Found', { status: 404 });\n  },\n} satisfies ExportedHandler<Env>;\n\nasync function handleAPI(request: Request, env: Env): Promise<Response> {\n  // Logique API\n  const data = await env.KV_NAMESPACE.get('config', { type: 'json' });\n  return Response.json(data);\n}
\n\n

Déploiement

\n\n
# Déployer en production\nwrangler deploy\n\n# Déployer en staging\nwrangler deploy --env staging\n\n# Tester localement\nwrangler dev
\n\n

Pour les équipes qui pratiquent le pentest cloud, les Workers peuvent être utilisés comme proxies de sécurité pour intercepter et analyser le trafic, ou comme honeypots configurables pour détecter les scanners automatisés.

\n\n

KV Storage — Base de données clé-valeur distribuée

\n\n

Cloudflare KV (Key-Value) est une base de données distribuée globalement, idéale pour stocker des données de configuration, des sessions utilisateur, des résultats de cache applicatif, ou tout autre donnée à lecture fréquente.

\n\n

Caractéristiques de KV

\n
    \n
  • Lecture ultra-rapide : les données sont répliquées dans tous les datacenters Cloudflare
  • \n
  • Écriture éventuelle : la propagation d'une écriture peut prendre jusqu'à 60 secondes globalement
  • \n
  • TTL natif : chaque clé peut avoir une expiration automatique
  • \n
  • Taille max par valeur : 25 MB
  • \n
  • Plan gratuit : 100 000 lectures/jour, 1 000 écritures/jour
  • \n
\n\n

Création et configuration d'un namespace KV

\n\n
# Créer un namespace KV\nwrangler kv:namespace create "MON_CACHE"\n\n# Résultat :\n# { binding = "MON_CACHE", id = "abc123..." }\n\n# Ajouter dans wrangler.toml :\n[[kv_namespaces]]\nbinding = "MON_CACHE"\nid = "abc123..."
\n\n

Utilisation dans un Worker

\n\n
// Écrire une valeur\nawait env.MON_CACHE.put('user:123', JSON.stringify({\n  name: 'Alice',\n  email: 'alice@example.com'\n}), { expirationTtl: 3600 }); // Expire dans 1 heure\n\n// Lire une valeur\nconst user = await env.MON_CACHE.get('user:123', { type: 'json' });\n\n// Lister les clés avec un préfixe\nconst keys = await env.MON_CACHE.list({ prefix: 'user:' });\n\n// Supprimer\nawait env.MON_CACHE.delete('user:123');
\n\n

Opérations en masse via CLI

\n\n
# Écrire depuis un fichier JSON\nwrangler kv:bulk put --binding=MON_CACHE data.json\n\n# Exporter toutes les clés\nwrangler kv:key list --binding=MON_CACHE
\n\n

La documentation complète de KV est disponible sur developers.cloudflare.com/kv.

\n\n

D1 — Base de données SQLite serverless

\n\n

Cloudflare D1 est une base de données relationnelle SQLite serverless, disponible directement dans les Workers et Pages Functions. C'est la solution la plus récente et la plus polyvalente pour les applications nécessitant des requêtes SQL complexes.

\n\n

Pourquoi D1 plutôt que KV ?

\n\n\n\n\n\n\n\n\n\n\n
CritèreKVD1
Type de donnéesClé-valeurRelationnel (SQL)
Requêtes complexesNonOui (JOINs, agrégations)
TransactionsNonOui (ACID)
CohérenceÉventuelleForte (lecture locale)
Cas d'usageCache, sessionsDonnées applicatives
\n\n

Création d'une base D1

\n\n
# Créer la base de données\nwrangler d1 create ma-base-prod\n\n# Résultat :\n# { binding = "DB", database_id = "xyz789..." }\n\n# wrangler.toml\n[[d1_databases]]\nbinding = "DB"\ndatabase_name = "ma-base-prod"\ndatabase_id = "xyz789..."
\n\n

Migrations et schéma

\n\n
# Créer les tables\nwrangler d1 execute ma-base-prod --command "\nCREATE TABLE IF NOT EXISTS articles (\n  id INTEGER PRIMARY KEY AUTOINCREMENT,\n  slug TEXT UNIQUE NOT NULL,\n  title TEXT NOT NULL,\n  content TEXT,\n  published INTEGER DEFAULT 0,\n  created_at TEXT DEFAULT (datetime('now'))\n);\n\nCREATE INDEX idx_articles_slug ON articles(slug);\nCREATE INDEX idx_articles_published ON articles(published);\n"
\n\n

Utilisation dans un Worker

\n\n
// Requête simple\nconst article = await env.DB\n  .prepare('SELECT * FROM articles WHERE slug = ?')\n  .bind(slug)\n  .first();\n\n// Insertion avec paramètres liés (protection SQL injection)\nawait env.DB\n  .prepare('INSERT INTO articles (slug, title, content) VALUES (?, ?, ?)')\n  .bind(slug, title, content)\n  .run();\n\n// Requête multiple (batch)\nconst results = await env.DB.batch([\n  env.DB.prepare('SELECT COUNT(*) as total FROM articles WHERE published = 1'),\n  env.DB.prepare('SELECT * FROM articles ORDER BY created_at DESC LIMIT 10'),\n]);
\n\n

Sécurité des déploiements Cloudflare

\n\n

La sécurité des déploiements serverless présente des défis spécifiques qui nécessitent une approche rigoureuse, particulièrement dans un contexte DevSecOps.

\n\n

Gestion des secrets

\n\n
# Ne JAMAIS stocker des secrets dans wrangler.toml\n# Utiliser les secrets chiffrés Cloudflare\n\n# Ajouter un secret (chiffré, jamais visible en clair)\nwrangler secret put DATABASE_URL\nwrangler secret put API_KEY\nwrangler secret put JWT_SECRET\n\n# Lister les secrets (noms uniquement, pas les valeurs)\nwrangler secret list
\n\n

Isolation et permissions

\n\n

Chaque Worker s'exécute dans un V8 Isolate séparé par requête. L'isolation garantit qu'un Worker ne peut pas accéder aux données d'un autre Worker ni à la mémoire du processus hôte. Cependant, les bindings (KV, D1, R2) doivent être configurés avec le principe du moindre privilège :

\n\n
# wrangler.toml — permissions minimales\n[[kv_namespaces]]\nbinding = "SESSION_STORE"\nid = "abc123..."\n# Ne donner accès qu'aux namespaces strictement nécessaires
\n\n

Cloudflare Access pour restreindre l'accès aux Pages de preview

\n\n
# Configurer Access pour bloquer les previews publics\n# Dashboard : Zero Trust > Access > Applications > Add an application\n# Type: Cloudflare Pages\n# Subdomain: *.votre-projet.pages.dev\n# Policy: Allow uniquement les membres de l'équipe
\n\n

Cette pratique est essentielle pour éviter d'exposer des versions de développement contenant des données sensibles ou des fonctionnalités non finalisées. Elle s'inscrit dans les exigences de sécurisation des environnements de développement et de conformité NIS 2 pour la gestion des accès aux systèmes d'information.

\n\n

Variables d'environnement par environnement

\n\n
# Séparer strictement production et développement\n[env.production]\nvars = { LOG_LEVEL = "error", RATE_LIMIT = "100" }\n\n[env.development]\nvars = { LOG_LEVEL = "debug", RATE_LIMIT = "10000" }
\n\n

Audit des déploiements

\n\n
# Voir l'historique des déploiements\nwrangler deployments list\n\n# Rollback vers une version précédente\nwrangler rollback [deployment-id]
\n\n

Coûts et limites du plan gratuit vs payant

\n\n

Comprendre les limites des plans Cloudflare est essentiel pour dimensionner correctement votre architecture.

\n\n

Cloudflare Workers — Plan gratuit

\n
    \n
  • 100 000 requêtes/jour (puis $0.30 pour 1M de requêtes)
  • \n
  • Durée d'exécution : 10ms de CPU par requête (pas de temps mur)
  • \n
  • Mémoire : 128 MB par Isolate
  • \n
  • Scripts Workers : maximum 100
  • \n
  • Taille du script : 1 MB (compressé)
  • \n
\n\n

Cloudflare Workers — Plan payant ($5/mois)

\n
    \n
  • 10 millions de requêtes/mois incluses (puis $0.30/M)
  • \n
  • Durée d'exécution : 30 secondes de CPU par requête
  • \n
  • Mémoire : 128 MB
  • \n
  • Workers illimités
  • \n
  • Taille du script : 10 MB (compressé)
  • \n
\n\n

Cloudflare Pages — Plan gratuit

\n
    \n
  • 500 builds/mois
  • \n
  • Bande passante illimitée
  • \n
  • Sites illimités
  • \n
  • Domaines personnalisés illimités
  • \n
  • Pages Functions : 100 000 invocations/jour
  • \n
\n\n

KV — Plan gratuit

\n
    \n
  • 100 000 lectures/jour, 1 000 écritures/jour
  • \n
  • 1 GB de stockage
  • \n
  • Au-delà : $0.50/million de lectures, $5/million d'écritures
  • \n
\n\n

D1 — Plan gratuit

\n
    \n
  • 5 millions de lignes lues/jour
  • \n
  • 100 000 lignes écrites/jour
  • \n
  • 5 GB de stockage total
  • \n
\n\n

Pour les architectures critiques soumises à des exigences de résilience, les plans payants offrent également des SLA et un support prioritaire. Consultez nos recommandations sur la gestion des dépendances et des mises à jour pour maintenir vos Workers à jour.

\n\n

FAQ — Cloudflare Pages et Workers

\n\n

Cloudflare Workers peut-il remplacer un serveur Node.js Express ?

\n

Oui, dans de nombreux cas. Workers supporte les APIs Web standard (fetch, crypto, streams, URL), et des frameworks comme Hono, Itty Router ou même une version allégée d'Express sont disponibles pour Workers. Les limitations principales sont l'absence d'accès au système de fichiers (pas de fs.readFile), pas d'accès à des bibliothèques natives Node.js, et un modèle d'exécution sans état entre les requêtes. Pour des APIs REST stateless, des webhooks handlers, des proxies ou des transformations de données, Workers est une alternative excellente — plus rapide, moins chère et sans maintenance serveur.

\n\n

Les Workers Cloudflare sont-ils sécurisés pour des données sensibles ?

\n

Cloudflare Workers offre un modèle de sécurité robuste basé sur l'isolation V8 Isolates : chaque requête est traitée dans un contexte mémoire isolé, sans partage d'état entre les requêtes ou les clients. Cloudflare est certifié ISO 27001, SOC 2 Type II et PCI DSS. Pour des données très sensibles (santé, financier), vérifiez la localisation de traitement des données — les Workers s'exécutent dans le datacenter le plus proche du visiteur, ce qui peut poser des questions de conformité RGPD si des données personnelles transitent hors de l'UE. Utilisez les Smart Placement ou les Workers Unbound avec localisation forcée pour les données soumises à des exigences de résidence des données.

\n\n

Comment gérer les migrations de base de données D1 ?

\n

Cloudflare D1 intègre un système de migrations via Wrangler. Créez un répertoire migrations/ avec des fichiers SQL numérotés (0001_create_users.sql, 0002_add_index.sql). Appliquez les migrations avec wrangler d1 migrations apply ma-base. En production, intégrez les migrations dans votre pipeline CI/CD avant le déploiement du Worker. D1 maintient une table interne d1_migrations pour suivre les migrations appliquées, à la manière de Flyway ou Liquibase.

\n\n

Puis-je utiliser des packages npm dans un Worker ?

\n

Oui, avec des restrictions. Les packages npm qui utilisent uniquement des APIs Web standard (pas de modules Node.js core comme fs, http, net) fonctionnent généralement bien. Wrangler bundle automatiquement vos dépendances avec esbuild. Des packages comme zod (validation), jose (JWT), bcryptjs, date-fns, ou lodash fonctionnent. Des packages comme express, axios (remplacé par fetch natif), ou des drivers de bases de données SQL classiques (pg, mysql2) ne fonctionnent pas. La taille du bundle final doit rester sous 1 MB (plan gratuit) ou 10 MB (plan payant) compressé.

\n\n

Comment déboguer un Worker en production ?

\n

Cloudflare propose plusieurs outils de débogage : (1) wrangler tail permet de streamer les logs en temps réel depuis n'importe quel Worker en production, (2) les Workers Logs dans le dashboard offrent une interface visuelle avec filtrage, (3) console.log() dans le code Worker génère des entrées dans les logs (visibles via tail ou le dashboard), (4) Wrangler Dev simule l'environnement de production localement avec --remote pour utiliser les vraies ressources KV/D1. Pour les erreurs difficiles à reproduire, configurez Sentry ou un équivalent via fetch depuis le Worker pour centraliser les rapports d'erreur.

\n\n
\n

Points clés à retenir

\n
    \n
  • Pages = déploiement, Workers = exécution : Pages gère le CI/CD et l'hébergement des sites statiques/Jamstack ; Workers exécute du code JavaScript sur l'Edge — les deux sont complémentaires et s'intègrent nativement.
  • \n
  • V8 Isolates = pas de cold start : contrairement à AWS Lambda (100-500ms de cold start), les Workers démarrent en moins d'1ms grâce à V8 Isolates, rendant la latence prévisible et uniforme quel que soit le volume de requêtes.
  • \n
  • Secrets via wrangler secret : ne jamais stocker des clés API, mots de passe ou tokens dans wrangler.toml — utilisez exclusivement wrangler secret put pour chiffrer les secrets côté Cloudflare.
  • \n
  • D1 pour le relationnel, KV pour le cache : choisissez D1 pour des données structurées avec requêtes SQL complexes ; KV pour des données de session, de configuration ou de cache applicatif à lecture très fréquente.
  • \n
  • Plan gratuit généreux : 100 000 requêtes Workers/jour, 500 builds Pages/mois, 100 000 invocations Functions/jour — suffisant pour la majorité des projets en développement et des applications à trafic modéré.
  • \n
  • Cloudflare Access pour les previews : protégez systématiquement les URLs de preview Pages avec Cloudflare Access pour éviter d'exposer des versions de développement contenant des données sensibles ou des fonctionnalités non validées.
  • \n
\n
\n\n

Pour aller plus loin dans la sécurisation de vos déploiements serverless, consultez notre guide sur le pentest cloud qui couvre les vecteurs d'attaque spécifiques aux architectures Edge et serverless. La documentation officielle est disponible sur developers.cloudflare.com/pages et developers.cloudflare.com/workers.