Le routage dans une application “SPA” fonctionne sous Node.js ou en “Server Side Rendering”. Comment faire quand on doit utiliser un serveur Web/J2EE?

Svelte, Apache TomEE et routage SPA

Introduction

Dans l’article Svelte, routage sans déroute, on avait vu comment mettre en place le routage au sein d’une application SPA. Sauf qu’il y a un petit souci: ce type de routage fonctionne sous Node.js ou en “Server Side Rendering”. Comment faire quand on doit utiliser un serveur Web/J2EE?

Svelte: mise en place du routage

On va utiliser ici la librairie “svelte routing” (documentation sur GitHub: https://github.com/EmilTholin/svelte-routing). L’installation se fait via NPM:

    
1npm install --save svelte-routing

Ensuite, dans la page principale Svelte, on ajoute ces éléments:

    
 1<style></style>
 2
 3<script>
 4    import { Router, Link, Route } from "svelte-routing";
 5    import CmpLfdUserLogin from "./cmpLfdUserLogin.svelte";
 6    import CmpLfdUserRegister from "./cmpLfdUserRegister.svelte";
 7
 8    export let urlSpa = '/app/spa/login';
 9</script>
10
11<main class="hero is-fullheight">
12    <div class="hero-body">
13        <div class="container">
14            <p class="title">
15                <Router url="{urlSpa}">
16                    <Route path="/app/spa/login"><CmpLfdUserLogin /></Route>
17                    <Route path="/app/spa/register"><CmpLfdUserRegister /></Route>
18                </Router>
19            </p>
20        </div>
21    </div>
22</main>

On peut bien sûr ajouter autant de tag <Route> que nécessaire: il suffit d’inclure le composant lié et de gérer l’url dédiée. Ensuite, pour changer de page (en fait le composant puisque le serveur TomEE n’est pas mis à contribution), il faut faire un navigate(url, { replace: true }); Le navigateur affiche alors l’url demandée (exemple: http://serveur/app/spa/login).

TomEE: redirection SPA

Une fois qu’on a navigué vers la page avec navigate, on croit que tout va bien. Mais si on recharge la page, le browser va effectuer une requête auprès du serveur (dans notre exemple, le serveur va devoir servir la page /app/spa/login). Sauf que cette url n’est pas connue de la WebApp et notre serveur TomEE retourne une erreur 404. On va donc rediriger les urls de type /app/spa vers la page d’accueil de l’application en lui indiquant quel est le composant demandé.

Pour rediriger les urls dans TomEE, il y a 3 petites étapes à effectuer: ajouter une dépendance au pom.xml, configurer le web.xml et ajouter la configuration des redirections dans le fichier WEB-INF/urlrewrite.xml.

pom.xml

On va ajouter le package org.tuckey.urlrewritefilter. La documentation se trouve sur http://www.tuckey.org/urlrewrite/.

    
1<dependency>
2   <groupId>org.tuckey</groupId>
3   <artifactId>urlrewritefilter</artifactId>
4   <version>4.0.4</version>
5</dependency>

web.xml

On ajoute un filtre qui se chargera de rediriger les urls configurées.

    
 1<filter>
 2    <filter-name>UrlRewriteFilter</filter-name>
 3    <filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>
 4</filter>
 5<filter-mapping>
 6    <filter-name>UrlRewriteFilter</filter-name>
 7    <url-pattern>/*</url-pattern>
 8    <dispatcher>REQUEST</dispatcher>
 9    <dispatcher>FORWARD</dispatcher>
10</filter-mapping>

WEB-INF/urlrewrite.xml

    
1<urlrewrite>
2    <rule>
3        <note>Transfer all urls starting with /spa/ to index page so client can route itselfs correctly</note>
4        <from>/spa/(.*)</from>
5        <to type="redirect">%{context-path}/index.html?page=/app/spa/$1</to>
6    </rule>
7</urlrewrite>

Ici, %{context-path} représente l’url de base de la WebApp (/app/ dans notre exemple).

Svelte: interception de la redirection

Dans notre composant principal, on va lire le paramètre “page” dans le QueryString de l’url (3 cas: paramètre manquant, sans valeur et avec valeur).

    
 1<style></style>
 2
 3<script>
 4    import { Router, Link, Route } from "svelte-routing";
 5    import CmpLfdUserLogin from "./cmpLfdUserLogin.svelte";
 6    import CmpLfdUserRegister from "./cmpLfdUserRegister.svelte";
 7
 8    let urlParams = new URLSearchParams(window.location.search);
 9    let page = urlParams.get('page');
10
11    export let urlSpa = ((null !== page) && (0 < page.trim().length)? page : '/app/spa/login'); // ici, si on a un paramètre "page" valide, on l'utilise sinon on va à la page de login. 
12</script>
13
14<main class="hero is-fullheight">
15    <div class="hero-body">
16        <div class="container">
17            <p class="title">
18                <Router url="{urlSpa}">
19                    <Route path="/app/spa/login"><CmpLfdUserLogin /></Route>
20                    <Route path="/app/spa/register"><CmpLfdUserRegister /></Route>
21                </Router>
22            </p>
23        </div>
24    </div>
25</main>

Conclusion

Moyennant peu de code, il est facile d’héberger une application “Single Page App” réalisée avec Svelte.