Lors du dévéloppement d’une application web (site web, application web, etc.) de nos jours, vous avez le backend (ou backoffice) qui représente le côté serveur et le coté frontend (ou frontoffice) qui représente le côté client. Le plus souvent, on a l’habitude lors du déploiement de l’application de déploier les deux parties séparément. Tout dernièrement, je me suis posé la question de savoir si on ne pouvait pas déploier spring boot (backend) et vue 3 (frontend) dans un même jar. Ce tutoriel vous présente ce que j’ai trouvé.

Plan de mise en oeuvre

Notre but ultime dans cet article et de finir par obtenir une application monolitique (c’est-à-dire en un seul morceau) sous forme de fichier jar à déployer. Pour cela, nous allons:

Installation de spring boot

L’installation de spring boot est décrite dans ce tutoriel sur spring boot initializr. Vous pouvez le consulter et initialiser le projet spring boot avec les caractéristiques suivantes:

ElémentValeur
Groupcom.ultron.systems
Artifactspringvue
Namespringvue
DescriptionRassembler spring boot vuejs sous forme
de projet monolitique
Package namecom.ultron.systems.springvue
Coordonnées du projet

Des que vous avez initialisé le projet spring boot, importez-le dans votre éditeur préféré et exécutez-le.

Installation de vuejs

Pour installer vuejs, il vous faut d’abord avoir node js installé sur votre ordinateur. Ensuite, vous exécutéz juste la commande qui suit.

npm install vue

Spring boot vuejs ensemble

A cette étape, vous avez déjà installé spring boot et vue js. Vous avez aussi compilé le projet spring boot et exécuté sans problèmes. Vous avez aussi vue-cli le programme ligne de commande qui vous permet d’initialiser un projet vuejs installé aussi. Maintenant, nous allons voir comment générer le projet vue js dans le projet spring boot et les lancer tous les deux.

Dans le dossier de projet, spring boot a généré une structure comportant un dossier nommé src. Avec la ligne de commande, allons dans ce dossier src et créons le projet vuejs frontend.

vue create frontend

Vue-cli va se lancer et vous poser quelques questions comme quelle version de vuejs vous voudriez utiliser. Vous pouvez choisir la version 3 ou 2 selon votre familiarité.

Ensuite naviguez vers le dossier frontend et exécutez aussi votre projet vuejs.

cd frontend
npm run serve

Le projet vuejs va donc se lancer et vous aurez aussi le projet spring boot qui est en exécution. Par défaut, spring boot utilise le port 8080 et vuejs le port 8000. Vous pouvez donc utiliser http://127.0.0.1:8080 pour tester votre application spring boot et https://127.0.0.1:8000 pour tester votre application vuejs.

Au cas oû les deux applications s’exécutent sur le même port, vous aurez un message d’erreur claire et vous devez changer le port d’écoute de l’un ou de l’autre.

Changement des ports d’écoute spring boot vuejs

Pour changer le port d’écoute de votre application spring boot, veuillez rechercher le fichier application.properties et le renommer en application.yml s’il est vide. Puis, ajouter les instructions qui suivent. Dans notre exemple nous allons le changer à 9000.

server:
  port: 9000

Si votre fichier application.properties contient déjà des instructions, vous pouvez changer le port juste en y ajoutant ou modifiant la ligne server.port.

server.port=9000

Au cas oû vous voulez plutôt changer le port d’écoute de votre application vuejs, vous devez accéder au dossier frontend contenant l’application vuejs et vous créer un fichier vue.config.js avec la configuration du port.

module.exports = {
    devServer: {
        port: 7000,
        }
    }
};

Quand vous allez recompiler les deux projets, vous allez constater que les ports d’écoutes ont changés. Dans notre exemple, l’application spring boot écoutera maintenant le port 9000 et l’application vuejs écoutera le 7000.

L’idée de la fusion

Maintenant que nos deux applications s’exécutent, nous voudrions les rassembler en un seul morceau. Du côté de spring boot, la condition favorable à toute fusion frontend, backend est que tout fichier html que vous déployez dans le répertoire /target/classes/static est sérvi comme une page web statique. Si vous mettez un contenu index.html dans ce dossier, il sera servi par défaut lors du chargement de l’application spring boot comme page d’index. Du côté de vuejs, un projet bien qu’étant construit en packages nodejs, fini par devenir un simple fichier html avec des scripts css et javascripts inclus. Cela arrange les choses, puisque si nous arrivons lors de la construction du jar spring boot à compiler le projet vuejs et le copier dans le repertoire /target/classes/static, le tour est joué. C’est donc ce que nous allons faire maintenant.

Compiler vuejs en utilisant les plugins maven

Pour compiler vuejs avec maven, nous devons installer le plugin  frontend-maven-plugin. Ensuite, nous allons faire deux opérations avec le plugin: installer npm et utiliser npm pour générer le build du projet vuejs. Pour ce faire, nous allons ajouter les instructions suivantes au fichier pom.xml du projet spring boot.

<properties>
    <java.version>11</java.version>
    <node.version>v10.15.0</node.version>
    <npm.version>6.14.3</npm.version>
</properties>
<plugin>
			<groupId>com.github.eirslett</groupId>
				<artifactId>frontend-maven-plugin</artifactId>
				<version>1.7.6</version>
				<executions>
					<execution>
						<id>Install node and npm</id>
						<goals>
							<goal>install-node-and-npm</goal>
						</goals>
						<phase>generate-resources</phase>
						<configuration>
							<nodeVersion>${node.version}</nodeVersion>
							<npmVersion>${npm.version}</npmVersion>
						</configuration>
					</execution>

					<execution>
						<id>npm install</id>
						<goals>
							<goal>npm</goal>
						</goals>
						<phase>generate-resources</phase>
						<configuration>
							<arguments>install</arguments>
						</configuration>
					</execution>

					<execution>
						<id>npm build</id>
						<goals>
							<goal>npm</goal>
						</goals>
						<phase>generate-resources</phase>
						<configuration>
							<arguments>run build</arguments>
						</configuration>
					</execution>
				</executions>
				<configuration>
					<nodeVersion>${node.version}</nodeVersion>
					<workingDirectory>src/frontend</workingDirectory>
				</configuration>
			</plugin>

Copier la sortie dans le dossier static de spring boot

Maintenant que nous avons compilé le projet frontend, nous devons le copier dans le dossier static de spring boot. Pour le faire nous allons utiliser le plugin  maven-resources-plugin.

<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-resources-plugin</artifactId>
				<executions>
					<execution>
						<id>Copier le projet vuejs dans le dossier static de  Spring Boot</id>
						<phase>process-resources</phase>
						<goals>
							<goal>copy-resources</goal>
						</goals>
						<configuration>
							<outputDirectory>target/classes/static</outputDirectory>
							<resources>
								<resource>
									<directory>src/frontend/dist</directory>
									<filtering>true</filtering>
								</resource>
							</resources>
						</configuration>
					</execution>
				</executions>
			</plugin>

Dans mon cas, voici le fichier pom.xml que j’obtiens:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.5.0</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.ultron.systems</groupId>
	<artifactId>springvue</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>springvue</name>
	<description>Spring boot et Vue Js dans un projet monolitique</description>
	<properties>
		<java.version>1.8</java.version>
		<node.version>v10.15.0</node.version>
		<npm.version>6.14.3</npm.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jpa</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-hateoas</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<dependency>
			<groupId>org.postgresql</groupId>
			<artifactId>postgresql</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
				<configuration>
					<excludes>
						<exclude>
							<groupId>org.projectlombok</groupId>
							<artifactId>lombok</artifactId>
						</exclude>
					</excludes>
				</configuration>
			</plugin>

			<plugin>
				<groupId>com.github.eirslett</groupId>
				<artifactId>frontend-maven-plugin</artifactId>
				<version>1.7.6</version>
				<executions>
					<execution>
						<id>Install node and npm</id>
						<goals>
							<goal>install-node-and-npm</goal>
						</goals>
						<phase>generate-resources</phase>
						<configuration>
							<nodeVersion>${node.version}</nodeVersion>
							<npmVersion>${npm.version}</npmVersion>
						</configuration>
					</execution>

					<execution>
						<id>npm install</id>
						<goals>
							<goal>npm</goal>
						</goals>
						<phase>generate-resources</phase>
						<configuration>
							<arguments>install</arguments>
						</configuration>
					</execution>

					<execution>
						<id>npm build</id>
						<goals>
							<goal>npm</goal>
						</goals>
						<phase>generate-resources</phase>
						<configuration>
							<arguments>run build</arguments>
						</configuration>
					</execution>
				</executions>
				<configuration>
					<nodeVersion>${node.version}</nodeVersion>
					<workingDirectory>src/frontend</workingDirectory>
				</configuration>
			</plugin>

			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-resources-plugin</artifactId>
				<executions>
					<execution>
						<id>Copy Vue frontend into Spring Boot target static folder</id>
						<phase>process-resources</phase>
						<goals>
							<goal>copy-resources</goal>
						</goals>
						<configuration>
							<outputDirectory>target/classes/static</outputDirectory>
							<resources>
								<resource>
									<directory>src/frontend/dist</directory>
									<filtering>true</filtering>
								</resource>
							</resources>
						</configuration>
					</execution>
				</executions>
			</plugin>
		</plugins>
	</build>
</project>

Pour le moment c’est la partie plugins qui devrait retenir le plus votre attention.

Production du jar final

Une fois que vous avez effectué toutes ces configurations, il ne restera qu’à construire l’exécutable final et à résoudre les éventuels problèmes.

mvn clean package 

Une fois le jar final généré, vous pouvez exécuter votre application monolitique.

java -jar target/springvue-0.0.1-SNAPSHOT.jar

Vous pouvez tester le regroupement monolitique en ajoutant saisissant le lien de votre application spring boot.

Conclusion

Dans cet article nous avons vu comment fusionner spring boot et vuejs dans un exécutable unique. J’espère que cette avanture vous a plu. Faites vos retours dans les commentaires et lisez d’autre tutoriels de développement web sur Ultron Systems.

Cordialement.