Le mode par défaut de vue-router
est le mode hash. Il utilise la partie hash de l'URL pour simuler une URL complète et ainsi ne pas recharger la page quand l'URL change.
Pour se passer du hash, nous pouvons utiliser le mode historique qui utilisera l'API history.pushState
afin de permettre une navigation sans rechargement de page :
const router = new VueRouter({
mode: 'history',
routes: [...]
})
Quand vous utilisez le mode historique, l'URL ressemblera a n'importe quelle URL normale. Par ex. http://oursite.com/user/id
. Magnifique !
Cependant, un problème apparaît si votre application est une application monopage cliente. Sans une configuration serveur adaptée, les utilisateurs tomberons sur une page d'erreur 404 en tentant d'accéder à http://oursite.com/user/id
directement dans leur navigateur. Maintenant ça craint.
Ne vous inquiétez pas. Pour résoudre ce problème, il vous suffit d'ajouter une route à votre serveur prenant en compte toutes les adresses demandées. Si l'URL demandée ne concorde avec aucun fichier statique, alors il doit toujours renvoyer la page index.html
qui contient le code de votre application. De nouveau magnifique !
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.html$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.html [L]
</IfModule>
location / {
try_files $uri $uri/ /index.html;
}
const http = require("http")
const fs = require("fs")
const httpPort = 80
http.createServer(function (req, res) {
fs.readFile("index.htm", "utf-8", function (err, content) {
if (err) {
console.log('Impossible d\'ouvrir le fichier "index.htm"')
}
res.writeHead(200, {
"Content-Type": "text/html; charset=utf-8"
})
res.end(content)
})
}).listen(httpPort, function () {
console.log("Server listening on: http://localhost:%s", httpPort)
})
Pour Node.js avec Express, vous pouvez utiliser le middleware connect-history-api-fallback.
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="Handle History Mode and custom 404/500" 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>
<httpErrors>
<remove statusCode="404" subStatusCode="-1" />
<remove statusCode="500" subStatusCode="-1" />
<error statusCode="404" path="/survey/notfound" responseMode="ExecuteURL" />
<error statusCode="500" path="/survey/error" responseMode="ExecuteURL" />
</httpErrors>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
rewrite {
regexp .*
to {path} /
}
Il y a une limitation a tout ceci. Votre serveur ne renverra plus les erreurs 404 des chemins qui ne sont pas trouvés puisqu'il va servir à présent le fichier index.html
. Pour contourner ce problème, vous pouvez implémenter une route concordant avec toutes les adresses en 404 dans votre application Vue :
const router = new VueRouter({
mode: 'history',
routes: [
{ path: '*', component: NotFoundComponent }
]
})
Une alternative possible, si vous utilisez un serveur Node.js, est d'implémenter ce mécanisme de substitution en utilisant le routeur côté serveur pour vérifier la concordance des demande d'URL entrante. Si la route ne concorde avec rien, la page est inexistante. Consultez l'utilisation de Vue côté serveur pour plus d'informations.