Avez-vous une question? (216) 97 656 803 hajjriadh@gmail.com
Angular

Déployer une application Angular sur un hébergement web ou un serveur dédié

Un cours complet pour maîtriser Déployer une application Angular sur un hébergement web ou un serveur dédié.

0 chapitres 0 QCM Accès gratuit
Dans cet article
  1. Objectifs

    • Déposer la version compilée sur un hébergement mutualisé (FTP, gestionnaire de fichiers) ou sur un serveur dédié (scp, rsync)
    • Comprendre pourquoi une page comme /cours/2 renvoie une erreur 404 quand on l'actualise
    • Configurer Apache avec un fichier .htaccess et Nginx avec try_files
    • Installer l'application dans un sous-dossier avec --base-href
    • Régler le cache: index.html toujours revérifié, fichiers avec empreinte gardés un an
    • Mettre à jour une application déjà en ligne
  1. Présentation

    • La leçon précédente a produit le dossier dist/premiers-pas-angular/browser/: quelques fichiers statiques. Les publier, c'est les copier dans le dossier qu'un serveur web expose sur Internet.
    • Deux situations courantes : un hébergement mutualisé (Apache le plus souvent, on dépose les fichiers dans public_html/ ou www/ et on ne règle le serveur qu'avec un fichier .htaccess) et un serveur dédié ou un VPS (on administre soi-même Apache ou Nginx).
    • Dans les deux cas, une seule vraie difficulté : le serveur doit renvoyer index.html pour les adresses gérées par le routeur Angular. Sans ce réglage, l'accueil fonctionne, mais toute autre page actualisée affiche une erreur 404.
  • Pour suivre ce chapitre, continuez dans le projet premiers-pas-angular, avec ses trois pages /, /cours et /cours/:id. Toutes les configurations ont été testées avec Angular 22.2, Apache 2.4 et Nginx, dans un vrai navigateur.

Du dossier dist/browser au serveur web, puis au navigateur

  1. Déposer les fichiers

    • Compilez d'abord en production :
ng build
  • Copiez ensuite le contenu du dossier browser/ (et non le dossier lui-même) à la racine du site. Sur la plupart des hébergements, index.html doit se trouver directement dans public_html/:
public_html/
├── .htaccess          ← à créer (voir plus bas)
├── index.html
├── main-7W7XMOG5.js
├── styles-5INURTSO.css
└── favicon.ico
  • Hébergement mutualisé: utilisez un client FTP (FileZilla), ou le gestionnaire de fichiers du panneau d'administration (cPanel, Plesk, aaPanel…) en déposant une archive .zip que vous décompressez sur place.
  • Serveur dédié: copiez en ligne de commande. rsync n'envoie que les fichiers modifiés, et --delete retire du serveur les anciens fichiers avec empreinte devenus inutiles. Notez la barre oblique finale après browser/: elle copie le contenu du dossier, pas le dossier.
# envoi du contenu de browser/ dans /var/www/premiers-pas-angular/
rsync -av --delete dist/premiers-pas-angular/browser/ utilisateur@mon-serveur:/var/www/premiers-pas-angular/

# sans rsync
scp -r dist/premiers-pas-angular/browser/* utilisateur@mon-serveur:/var/www/premiers-pas-angular/
  1. Le problème de l'actualisation : l'erreur 404

    • Déposez les fichiers sur un serveur Apache sans aucun réglage, puis testez :
Action Résultat
Ouvrir https://mon-site.tn/ 200 : l'accueil s'affiche
Cliquer sur « Cours », puis sur « Angular » Les pages s'affichent, l'adresse devient /cours/2
Actualiser (F5) sur /cours/2, ou ouvrir ce lien dans un nouvel onglet 404 Not Found

Erreur 404 Not Found d'Apache en actualisant /cours/2

  • Quand on clique sur un lien, c'est le routeur Angular, dans le navigateur, qui change l'adresse et la page : aucune requête n'est envoyée au serveur.
  • Quand on actualise, le navigateur demande au serveur le fichier /cours/2. Ce fichier n'existe pas sur le disque : le serveur répond 404, et Angular n'est jamais chargé.
  • La solution : configurer le serveur pour qu'il envoie le fichier demandé s'il existe (main-….js, une image…), et index.html dans tous les autres cas. Angular démarre alors, lit l'adresse /cours/2 et affiche la bonne page.

Lien cliqué : le routeur répond. Actualisation : le serveur cherche un fichier qui n'existe pas

  1. Apache : le fichier .htaccess

    • Créez un fichier nommé exactement .htaccess (avec le point) à côté de index.html:
RewriteEngine On
RewriteBase /

# 1. Un fichier ou un dossier qui existe : on le sert tel quel
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]

# 2. Toute autre adresse (/cours, /cours/2...) : index.html, le routeur Angular fait le reste
RewriteRule ^ index.html [L]

# 3. Cache : index.html toujours revérifié, fichiers avec empreinte gardés un an
<IfModule mod_headers.c>
  <FilesMatch "^index\.html$">
    Header set Cache-Control "no-cache"
  </FilesMatch>
  <FilesMatch "-[A-Z0-9]{8}\.(js|css)$">
    Header set Cache-Control "public, max-age=31536000, immutable"
  </FilesMatch>
</IfModule>
  • Résultat mesuré sur le serveur de test :
/                    -> 200  Cache-Control: no-cache
/cours/2             -> 200  Cache-Control: no-cache
/main-7W7XMOG5.js    -> 200  Cache-Control: public, max-age=31536000, immutable
/styles-5INURTSO.css -> 200  Cache-Control: public, max-age=31536000, immutable
  • Actualisez /cours/2: la page « Angular » s'affiche.
  • Le fichier ne fonctionne que si le module mod_rewrite est actif et si Apache autorise les .htaccess (AllowOverride All). C'est le cas chez presque tous les hébergeurs. Sur votre propre serveur Apache (Debian, Ubuntu), activez-les ainsi :
sudo a2enmod rewrite headers
sudo systemctl reload apache2
# /etc/apache2/sites-available/premiers-pas-angular.conf
<VirtualHost *:80>
    ServerName mon-site.tn
    DocumentRoot /var/www/premiers-pas-angular
    <Directory /var/www/premiers-pas-angular>
        AllowOverride All
        Require all granted
    </Directory>
</VirtualHost>
  • Deux pannes vérifiées sur le serveur de test : avec AllowOverride None, le fichier est ignoré et /cours/2 reste en 404 ; sans mod_rewrite, tout le site répond 500 Internal Server Error, et le journal d'erreurs indique Invalid command 'RewriteEngine', perhaps misspelled or defined by a module not included in the server configuration.
  • Le .htaccess se trouve à la racine du site, pas dans dist/: chaque ng build vide ce dossier. Pour qu'il soit recopié à chaque compilation, rangez-le dans le dossier public/ du projet.
  1. Installer l'application dans un sous-dossier

    • Pour publier l'application à l'adresse https://mon-site.tn/formation/, compilez avec la bonne adresse de base :
ng build --base-href /formation/
  • Déposez les fichiers dans public_html/formation/, avec ce .htaccess, où seul RewriteBase change :
RewriteEngine On
RewriteBase /formation/
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
RewriteRule ^ index.html [L]
  • Vérifié dans le navigateur : /formation/ affiche l'accueil, et /formation/cours/3 actualisé affiche le cours « Signals ».
  • Si l'on oublie --base-href, la page reste blanche: index.html demande /main-….js à la racine du site au lieu de /formation/main-….js, et la console affiche deux erreurs Failed to load resource: the server responded with a status of 404 (Not Found).

Page blanche : main.js cherché à la racine du site au lieu du sous-dossier

  1. Nginx sur un serveur dédié

    • Nginx ne lit pas les .htaccess: on règle tout dans la configuration du site. La directive try_files joue le rôle des règles de réécriture : elle essaie le fichier, puis le dossier, puis renvoie index.html.
# /etc/nginx/sites-available/premiers-pas-angular
server {
    listen 80;
    server_name mon-site.tn;
    root /var/www/premiers-pas-angular;
    index index.html;

    # Fichiers avec empreinte (main-XXXX.js) : mis en cache un an
    location ~* \.(?:js|css|ico|png|jpg|svg|woff2?)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
        try_files $uri =404;
    }

    # Toutes les autres adresses : le fichier s'il existe, sinon index.html
    location / {
        add_header Cache-Control "no-cache";
        try_files $uri $uri/ /index.html;
    }

    # Une seconde application dans un sous-dossier (compilée avec --base-href /formation/)
    location ^~ /formation/ {
        alias /var/www/formation/;
        try_files $uri $uri/ /formation/index.html;
    }
}
  • Activez le site, vérifiez la syntaxe, puis rechargez Nginx :
sudo ln -s /etc/nginx/sites-available/premiers-pas-angular /etc/nginx/sites-enabled/
sudo nginx -t
nginx: configuration file /etc/nginx/nginx.conf test is successful
sudo systemctl reload nginx
  • Résultats mesurés : /cours/2 répond 200 et affiche « Angular », /fichier-absent.js répond une vraie 404, et /formation/cours/1 affiche « TypeScript ».
  • Le ^~ devant /formation/ est indispensable. Sans lui, la règle des .js intercepte /formation/main-….js et cherche le fichier dans /var/www/premiers-pas-angular: la page du sous-dossier reste blanche. Avec ^~, Nginx s'arrête à ce bloc sans tester les expressions régulières.

Correspondance entre le .htaccess d'Apache et try_files de Nginx

  1. Passer en HTTPS

    • Sur un hébergement mutualisé, le certificat se demande dans le panneau d'administration (rubrique SSL, souvent Let's Encrypt gratuit), puis on force le HTTPS.
    • Sur un serveur dédié, l'outil certbot obtient un certificat Let's Encrypt et modifie la configuration du site :
sudo apt install certbot python3-certbot-nginx   # ou python3-certbot-apache
sudo certbot --nginx -d mon-site.tn              # ou --apache
  • Si l'application appelle une API, celle-ci doit aussi être en HTTPS : un site HTTPS ne peut pas appeler une adresse http:// (le navigateur bloque la requête, contenu mixte).
  1. Mettre à jour une application en ligne

    • À chaque nouvelle version : ng build, puis envoi des fichiers. Grâce aux empreintes, les nouveaux main-….js ne remplacent pas les anciens, ils s'ajoutent à côté ; seul index.html est écrasé et pointe vers les nouveaux.
    • Avec rsync --delete, les anciens fichiers sont supprimés. Par FTP, supprimez-les à la main de temps en temps (en gardant .htaccess).
    • Comme index.html est en no-cache, les visiteurs reçoivent la nouvelle version dès leur prochain chargement, sans vider leur cache.

Aide-mémoire : déployer une application Angular sur Apache ou Nginx

  1. Activité 1 : reproduire l'erreur 404

    • Compiler le projet et déposer le contenu de browser/ sur un serveur Apache (hébergement, XAMPP, WampServer…) sans .htaccess.
    • Naviguer jusqu'à /cours/2 en cliquant, puis actualiser la page.
  • Vérifier : la navigation par clics fonctionne, l'actualisation donne une erreur 404.
  • Expliquez en deux phrases pourquoi le clic fonctionne et l'actualisation non.
  1. Activité 2 : corriger avec un .htaccess

    • Ajouter le fichier .htaccess de la leçon, actualiser /cours/2, puis ouvrir directement /cours/3 dans un nouvel onglet.
    • Ranger ensuite le .htaccess dans le dossier public/ du projet, recompiler, et vérifier qu'il se trouve dans dist/premiers-pas-angular/browser/.
  • Vérifier : les deux pages s'affichent ; le fichier est recopié à chaque compilation.
  • Pourquoi les deux lignes RewriteCond sont-elles indispensables ? Que se passerait-il pour main-….js sans elles ?
  1. Activité 3 : une application dans un sous-dossier

    • Publier l'application à l'adresse /formation/ du serveur, d'abord sans --base-href, puis avec --base-href /formation/ et le .htaccess adapté.
    • Dans les deux cas, ouvrir les outils de développement (F12), onglet Réseau, et relever l'adresse demandée pour main-….js.
  • Vérifier : page blanche et erreurs 404 dans le premier cas ; application complète et /formation/cours/3 actualisable dans le second.
  • Quelles sont les deux modifications nécessaires pour passer de la racine à un sous-dossier ?
  1. Activité 4 : contrôler le cache

    • Dans l'onglet Réseau, cliquer sur index.html puis sur main-….js, et relever l'en-tête Cache-Control de chacun.
    • Modifier un texte de l'application, recompiler, redéployer, puis recharger la page normalement (sans vider le cache).
  • Vérifier : no-cache pour index.html, max-age=31536000 pour main-….js; la modification apparaît immédiatement.
  • Que verraient les visiteurs si index.html était lui aussi gardé un an en cache ?
  1. Activité 5 : configurer Nginx

    • Sur un serveur Linux (ou une machine virtuelle), installer Nginx, copier l'application dans /var/www/premiers-pas-angular et écrire la configuration du site avec try_files.
    • Ajouter une seconde application dans /formation/, d'abord avec location /formation/, puis avec location ^~ /formation/.
  • Vérifier : sudo nginx -t ne signale aucune erreur ; /cours/2 actualisé s'affiche ; le sous-dossier ne fonctionne qu'avec ^~.
  • Pourquoi un fichier .js absent doit-il recevoir une vraie 404 plutôt que index.html?
  1. Erreurs fréquentes

Message ou symptôme Cause Solution
404 Not Found en actualisant /cours/2 Le serveur cherche un fichier /cours/2 .htaccess (Apache) ou try_files … /index.html (Nginx)
Toujours 404 malgré le .htaccess AllowOverride None, ou fichier mal nommé (htaccess.txt) AllowOverride All; nommer le fichier .htaccess
500 Internal Server Error, Invalid command 'RewriteEngine' dans le journal mod_rewrite inactif sudo a2enmod rewrite puis recharger Apache
Page blanche, main-….js en 404 dans la console Sous-dossier sans --base-href ng build --base-href /dossier/ et RewriteBase /dossier/
Page blanche dans un sous-dossier sous Nginx La règle des .js passe avant location /formation/ location ^~ /formation/
Liste des fichiers, page 403, ou index.html introuvable Dossier browser/ copié au lieu de son contenu Placer index.html directement à la racine du site
Les visiteurs voient l'ancienne version index.html gardé en cache Cache-Control: no-cache sur index.html
Le .htaccess a disparu après une compilation Rangé dans dist/, vidé par ng build Le ranger dans public/
Requêtes vers l'API bloquées, Mixed Content dans la console Site en HTTPS, API en HTTP Passer l'API en HTTPS
  1. À retenir

    • On publie le contenu de dist/<projet>/browser/: index.html doit être à la racine du site (ou du sous-dossier).
    • Le routeur Angular fonctionne dans le navigateur : le serveur doit renvoyer index.html pour toute adresse qui n'est pas un fichier.
    • Apache : un .htaccess avec mod_rewrite et AllowOverride All; Nginx : try_files $uri $uri/ /index.html;.
    • Sous-dossier : ng build --base-href /dossier/, plus RewriteBase /dossier/ ou location ^~ /dossier/.
    • index.html en no-cache, fichiers avec empreinte en cache un an : les mises à jour arrivent tout de suite.
    • Rangez le .htaccess dans public/ pour qu'il soit recopié à chaque compilation.
Une application Angular n'est qu'un fichier index.html et ses scripts : le seul travail du serveur est de toujours répondre index.html, et de laisser le routeur faire le reste.