Une SPA Angular, une fois « buildée », n'est qu'un ensemble de fichiers statiques (HTML, CSS, JS, assets). Contrairement à une application Node.js, aucun process ne doit tourner en continu sur le serveur : IIS sert directement ces fichiers, comme n'importe quel site statique. Node.js et Angular CLI ne sont nécessaires que pour la phase de build (sur un poste de développement ou un pipeline CI), pas sur le serveur de production — sauf si vous choisissez de builder directement dessus.
Ce document décrit comment déployer une application Angular (SPA) sur un Windows Server existant, servie par IIS. L'architecture est nettement plus simple que pour une application Node.js server-side : IIS sert des fichiers statiques, avec une seule règle spécifique à gérer — rediriger toutes les routes internes de l'application vers index.html pour que le routing Angular (côté client) fonctionne correctement, y compris lors d'un rafraîchissement de page (F5) sur une route profonde.
Schéma : Internet → IIS (port 443, certificat SSL) → fichiers statiques du dossier dist/ (+ règle de réécriture vers index.html pour les routes Angular).
angular.json et package.json valides.Si IIS n'est pas encore installé sur le serveur :
# PowerShell, en tant qu'administrateur Install-WindowsFeature -Name Web-Server -IncludeManagementTools
Ou via l'interface graphique : Gestionnaire de serveur → Ajouter des rôles et fonctionnalités → Serveur Web (IIS) → cocher au minimum : Contenu statique, Document par défaut, Compression du contenu statique, Journalisation HTTP, Filtrage des requêtes, Console de gestion IIS.
Indispensable pour que le routing interne d'Angular fonctionne (sans lui, un F5 sur une route comme /questionnaire/3 renvoie une erreur 404, car ce chemin n'existe pas physiquement sur le serveur). Télécharger et installer « URL Rewrite Module 2.1 » depuis le site officiel IIS (iis.net/downloads/microsoft/url-rewrite).
Un redémarrage d'IIS est recommandé après installation : iisreset en ligne de commande administrateur.
Sur le poste de build (pas nécessairement le serveur) :
# Installer les dépendances npm ci # Générer le build de production ng build --configuration production
Le résultat se trouve dans dist/<nom-du-projet>/ (ou dist/<nom-du-projet>/browser/ selon la version d'Angular). Ce dossier contient uniquement des fichiers statiques (index.html, fichiers .js/.css avec hash dans leur nom, assets) : c'est tout ce dont IIS a besoin.
Vérifier la configuration de build : si l'application n'est pas servie à la racine du domaine (ex.https://serveur/questionnaire/), penser à définir lebase hrefcorrespondant, soit dansindex.html, soit viang build –base-href /questionnaire/.
Copier l'intégralité du contenu de dist/<nom-du-projet>/ vers un dossier dédié sur le serveur, par exemple D:\Sites\questionnaire\.
# Exemple avec robocopy, en local sur le serveur ou via un partage réseau robocopy dist\questionnaire-app D:\Sites\questionnaire /MIR
L'option /MIR miroir le contenu (supprime côté serveur les anciens fichiers qui n'existent plus dans le nouveau build) — utile pour éviter d'accumuler d'anciennes versions des fichiers JS/CSS hashés.
Créer (ou compléter) un fichier web.config à la racine de D:\Sites\questionnaire\ :
<?xml version="1.0" encoding="utf-8"?> <configuration> <system.webServer> <!-- Redirige toutes les routes internes Angular vers index.html --> <rewrite> <rules> <rule name="Angular Routes" stopProcessing="true"> <match url=".*" /> <conditions logicalGrouping="MatchAll"> <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" /> <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" /> </conditions> <action type="Rewrite" url="/index.html" /> </rule> </rules> </rewrite> <!-- Types MIME parfois manquants par défaut sur IIS --> <staticContent> <remove fileExtension=".json" /> <mimeMap fileExtension=".json" mimeType="application/json" /> <remove fileExtension=".woff" /> <mimeMap fileExtension=".woff" mimeType="font/woff" /> <remove fileExtension=".woff2" /> <mimeMap fileExtension=".woff2" mimeType="font/woff2" /> <clientCache cacheControlMode="UseMaxAge" cacheControlMaxAge="7.00:00:00" /> </staticContent> <!-- Compression pour réduire le poids des fichiers JS/CSS --> <httpCompression> <dynamicTypes> <add mimeType="*/*" enabled="false" /> </dynamicTypes> <staticTypes> <add mimeType="application/javascript" enabled="true" /> <add mimeType="text/css" enabled="true" /> <add mimeType="text/html" enabled="true" /> </staticTypes> </httpCompression> </system.webServer> </configuration>
Cache des fichiers hashés : Angular ajoute un hash au nom des fichiers JS/CSS à chaque build (ex.main.a1b2c3.js), donc un cache long (7 jours ci-dessus) sur ces fichiers ne pose pas de problème — un nouveau build génère de nouveaux noms de fichiers. En revanche,index.htmlne doit jamais être mis en cache longtemps côté client, sous peine de servir une ancienne version de l'app après une mise à jour ; ajouter si besoin une règle de cache spécifique et courte pour ce fichier.
Fortement recommandé dès que le questionnaire transmet des données, même peu sensibles.
<rule name="ForceHTTPS" stopProcessing="true"> <match url="(.*)" /> <conditions> <add input="{HTTPS}" pattern="off" /> </conditions> <action type="Redirect" url="https://{HTTP_HOST}/{R:1}" redirectType="Permanent" /> </rule>
Autoriser uniquement les ports nécessaires en entrée : 80 et 443. Il n'y a ici aucun port applicatif interne à ouvrir (pas de Node.js en écoute), puisque IIS sert directement les fichiers statiques.
New-NetFirewallRule -DisplayName "IIS HTTP" -Direction Inbound -Protocol TCP -LocalPort 80 -Action Allow New-NetFirewallRule -DisplayName "IIS HTTPS" -Direction Inbound -Protocol TCP -LocalPort 443 -Action Allow
http://nom-du-site puis https://nom-du-site dans un navigateur : la page d'accueil de l'application doit s'afficher./questionnaire/3), puis rafraîchir la page (F5) : elle doit continuer à s'afficher correctement (et non renvoyer une erreur 404) — c'est le test clé qui valide la règle de réécriture.Content-Encoding: gzip ou br).X-Content-Type-Options: nosniff, X-Frame-Options: SAMEORIGIN, et une politique Content-Security-Policy adaptée à l'application.D:\Sites\questionnaire\ pour que seuls les comptes de déploiement/administration puissent y écrire.npm ci et ng build –configuration production.dist/<nom-du-projet>/ vers D:\Sites\questionnaire\ (avec robocopy /MIR pour nettoyer les anciens fichiers hashés).Bonnes pratiques : conserver une copie de la version précédente du dossierdist/quelque part (ex. archivée par date) pour pouvoir revenir en arrière rapidement en cas de problème après une mise à jour.
| Élément | Statut |
|---|---|
| Rôle IIS installé (avec compression du contenu statique) | ☐ |
| Module URL Rewrite installé | ☐ |
| Build de production généré (ng build –configuration production) | ☐ |
| Fichiers copiés sur le serveur (dossier dist/) | ☐ |
| web.config en place (règle SPA, MIME types, compression) | ☐ |
| Site créé dans IIS, binding http configuré | ☐ |
| Certificat SSL installé, binding https configuré | ☐ |
| Redirection HTTP → HTTPS active | ☐ |
| Pare-feu : ports 80/443 ouverts | ☐ |
| Test de rafraîchissement (F5) sur une route interne réussi | ☐ |
| Aucune erreur 404 sur les fichiers statiques (JS/CSS/fonts) | ☐ |
| Test de bout en bout du questionnaire réussi | ☐ |
| En-têtes de sécurité HTTP en place | ☐ |
| Symptôme | Piste de résolution |
|---|---|
| Erreur 404 en rafraîchissant une route interne (ex. /questionnaire/3) | Règle « Angular Routes » absente ou mal placée dans le web.config, ou module URL Rewrite non installé. |
| Page blanche à l'ouverture du site | Vérifier le base href dans index.html (doit correspondre au chemin réel du site) et la console navigateur pour une erreur JS/404 sur un asset. |
| Fichiers .woff/.json en erreur 404 ou mal interprétés | Vérifier la section staticContent du web.config (types MIME manquants par défaut sur certaines configurations IIS). |
| L'app affiche encore l'ancienne version après une mise à jour | Cache navigateur ou cache trop long sur index.html — vérifier la politique de cache et forcer un rafraîchissement (Ctrl+F5) pour confirmer. |
| Erreur 500.19 sur le site IIS | web.config invalide (erreur de syntaxe XML) ou module URL Rewrite non installé. |
| Le site répond en HTTP mais pas en HTTPS | Vérifier le binding 443 et que le certificat sélectionné est valide et non expiré. |
Document préparé le 18 août 2026.