Spring-React frontend-maven-plugin not working - reactjs

I'm following the documentation is https://spring.io/guides/tutorials/react-and-spring-data-rest/ to build a React app that uses Spring. The spring part was fine until it gets to the part where recommends to install the node and npm modules with a plugin. I have the problem that this plugin does not do what it supposed to do. I've checked the documentation and it establish some executions (I don't really know how the plugins work). I introduce those executions, but I still can't see the React app render in the brower at localhost:8080.
This is the plugin that they use in the spring documentation. Just like that. I hope anybody who has followed this tutorial could help me.
<plugin>
<groupId>com.github.eirslett</groupId>
<artifactId>frontend-maven-plugin</artifactId>
</plugin>

You can run React Frontend and SpringBoot Backend on the same port and Package them as a single artifact !!
Here is the Github link of the demo project that I am going to
explain here
Spring Boot can serve static content from src/main/resources/static folder. We will exploit the above mentioned feature of Spring Boot to serve the single page of the react project. We will serve a html page from the static folder in the target directory, not in the source directory.
The Project structure-
First, create a spring boot project with https://start.spring.io. Add the Web dependency. Set the groupId and artifactId to whatever you want. Generate the project and unzip it into your project directory.
Or, if you are using Spring Tools Suite you can simply click
File->New->Spring Starter Project and mention the required details to create a spring boot project.
The frontend folder inside src/main should have your react application build using create-react-app.
So, there are two steps-
create a production build of the frontend.
copy the production build into ${target/classes/}.
We we will use two maven plugins and Thymleaf for that.
frontend-maven-plugin for step 1.
maven-resources-plugin for step 2.
For frontend-maven-plugin at Step 1-- If you closely look at the pom.xml there I have mentioned the src directroy from where frontend-maven-plugin will take the files, create the production build and place the contents inside the output directory mentioned(inside src/main/frontend/build).
<workingDirectory>${frontend-src-dir}</workingDirectory>
<installDirectory>${project.build.directory}</installDirectory>
For maven-resources-plugin at step 2-- It will take the production build that was just created by frontend-maven-plugin and place it inside your root directory then target/classes/static.
Then we will use Thymleaf to serve the static content from the target/classes/static using a rest endpoint in the controller. Or else you have to type in the name of the html file, like http://localhost:8080/index.html
Your pom.xml should look like this-
<?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.4.2</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>com.springreact</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<description>Run React Frontend and SpringBoot Backend on the same port.</description>
<properties>
<java.version>1.8</java.version>
<frontend-src-dir>${project.basedir}/src/main/frontend</frontend-src-dir>
<node.version>v14.15.4</node.version>
<yarn.version>v1.16.0</yarn.version>
<frontend-maven-plugin.version>1.7.6</frontend-maven-plugin.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</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>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</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>${frontend-maven-plugin.version}</version>
<configuration>
<nodeVersion>${node.version}</nodeVersion>
<yarnVersion>${yarn.version}</yarnVersion>
<workingDirectory>${frontend-src-dir}</workingDirectory>
<installDirectory>${project.build.directory}</installDirectory>
</configuration>
<executions>
<execution>
<id>install-frontend-tools</id>
<goals>
<goal>install-node-and-yarn</goal>
</goals>
</execution>
<execution>
<id>yarn-install</id>
<goals>
<goal>yarn</goal>
</goals>
<configuration>
<arguments>install</arguments>
</configuration>
</execution>
<execution>
<id>build-frontend</id>
<goals>
<goal>yarn</goal>
</goals>
<phase>prepare-package</phase>
<configuration>
<arguments>build</arguments>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<executions>
<execution>
<id>position-react-build</id>
<goals>
<goal>copy-resources</goal>
</goals>
<phase>prepare-package</phase>
<configuration>
<outputDirectory>${project.build.outputDirectory}/static</outputDirectory>
<resources>
<resource>
<directory>${frontend-src-dir}/build</directory>
<filtering>false</filtering>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Here is the Controller code.
package com.springreact.demo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.servlet.ModelAndView;
#Controller
public class IndexController {
#GetMapping("")
public ModelAndView home() {
ModelAndView mav=new ModelAndView("index");
return mav;
}
}
If you follow the above mentioned steps , you should see your React App being spun up on http://localhost:8080/.
If you still have some doubts then you can checkout the comprehensive blog that I have written on it. Here are the links of the blog on two different platforms, you can choose whichever you are comfortable with.
Dev Community- https://dev.to/arpan_banerjee7/run-react-frontend-and-springboot-backend-on-the-same-port-and-package-them-as-a-single-artifact-14pa
Medium- https://arpan-banerjee7.medium.com/run-react-frontend-and-springboot-backend-on-the-same-port-and-package-them-as-a-single-artifact-a790c9e10ac1

If your project structure looks like the following:
frontend/ -> React application
src/ -> Spring Boot application
You can bundle the React application with the frontend-maven-plugin with the following configuration:
<build>
<resources>
<resource>
<directory>${project.basedir}/frontend/build</directory>
<filtering>false</filtering>
<targetPath>public/</targetPath>
</resource>
<resource>
<directory>${project.basedir}/src/main/resources</directory>
<filtering>false</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>com.github.eirslett</groupId>
<artifactId>frontend-maven-plugin</artifactId>
<version>1.8.0</version>
<executions>
<execution>
<id>install node and npm</id>
<goals>
<goal>install-node-and-npm</goal>
</goals>
<phase>generate-resources</phase>
</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>
<environmentVariables>
<CI>true</CI>
</environmentVariables>
<arguments>run build</arguments>
</configuration>
</execution>
</executions>
<configuration>
<workingDirectory>frontend</workingDirectory>
<nodeVersion>v12.18.0</nodeVersion>
</configuration>
</plugin>
</plugins>
</build>
If your project structure differs, you have to adjust the workingDirectory and the first resources configuration and point it to your folder.
This plugin basically executes several npm commands to test and build your React application and with the resources configuration, you extend the standard directory to include inside your .jar. Your frontend application is then accessible at http://localhost:8080.
You can find a running example for this here.

I followed the same tutorial and stuck at the same point: the frontend-maven-plugin seems not working. In addition, the codebase that author provided looks not well organized to me, e.g. two pom.xml files, one in project root folder, the other in basic folder.
Here is what I figured out, and finally worked:
In pom.xml add the frontend-maven-plugin in plugins along with the scripts you want it to execute. Make sure you include the version tag and supply the latest version (you can find the version information in Maven Repository), otherwise the plugin won't be resolved.
<build>
<plugins>
<!-- For the sake of simplicity, -->
<!-- other plugins are omitted. -->
<plugin>
<groupId>com.github.eirslett</groupId>
<artifactId>frontend-maven-plugin</artifactId>
<version>1.12.0</version>
<configuration>
<installDirectory>target</installDirectory>
</configuration>
<executions>
<execution>
<id>install node and npm</id>
<goals>
<goal>install-node-and-npm</goal>
</goals>
<configuration>
<nodeVersion>v14.17.3</nodeVersion>
<npmVersion>7.18.1</npmVersion>
</configuration>
</execution>
<execution>
<id>npm install</id>
<goals>
<goal>npm</goal>
</goals>
<configuration>
<arguments>install</arguments>
</configuration>
</execution>
<execution>
<id>webpack build</id>
<goals>
<goal>webpack</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
Create package.json file in the project root folder, i.e. same location as pom.xml and paste following content:
{
"name": "spring-data-rest-and-reactjs",
"version": "0.1.0",
"description": "Demo of ReactJS + Spring Data REST",
"repository": {
"type": "git",
"url": "git#github.com:spring-guides/tut-react-and-spring-data-rest.git"
},
"keywords": [
"rest",
"hateoas",
"spring",
"data",
"react"
],
"author": "Greg L. Turnquist",
"license": "Apache-2.0",
"bugs": {
"url": "https://github.com/spring-guides/tut-react-and-spring-data-rest/issues"
},
"homepage": "https://github.com/spring-guides/tut-react-and-spring-data-rest",
"dependencies": {
"react": "^16.5.2",
"react-dom": "^16.5.2",
"rest": "^1.3.1"
},
"scripts": {
"watch": "webpack --watch -d --output ./target/classes/static/built/bundle.js"
},
"devDependencies": {
"#babel/core": "^7.1.0",
"#babel/preset-env": "^7.1.0",
"#babel/preset-react": "^7.0.0",
"babel-loader": "^8.0.2",
"webpack": "^4.19.1",
"webpack-cli": "^3.1.0"
}
}
Create webpack.config.js file in project root folder, i.e. the same location as pom.xml and paste following content:
var path = require('path');
module.exports = {
entry: './src/main/js/app.js',
devtool: 'sourcemaps',
cache: true,
mode: 'development',
output: {
path: __dirname,
filename: './src/main/resources/static/built/bundle.js'
},
module: {
rules: [
{
test: path.join(__dirname, '.'),
exclude: /(node_modules)/,
use: [{
loader: 'babel-loader',
options: {
presets: ["#babel/preset-env", "#babel/preset-react"]
}
}]
}
]
}
};
Copy client.js and the whole api folder in the same directory to your project. The app.js uses client.js which uses the two .js files in the api folder. You can find the source code of the three files in the tutorial repository.
Now you should have everything in order to make React work in this project. While depending on what IDE you're using, it may still "NOT WORK". Let me explain more about what I mean:
if you are using command line to run the project, then simply type ./mvnw spring-boot:run in the project root folder and it should work like a charm.
if you are using the little green triangle to run application in IntelliJ like me, you have to edit run/debug configuration in order to make it work; otherwise the application can run successfully but there is no bundle.js generated whatsoever:
First, open IntelliJ -> Run -> Edit Configurations
Secondly, click on the + button in Before Launch section and select Run Maven Goal
Thirdly, type generate-resources in command line and click OK. We choose this command as mentioned in frontend-maven-plugin git repo, if not sepecified, the goal is executed in generate-resources phase.
Finally, you can create a maven goal to clean everything before build. Here is what Before launch looks like:
Now click on the green triangle to run application and you will get the same result as mentioned in the tutorial (except there is no boarders in the employee list since we don't have the .css file).
Some final thoughts:
You add frontend-maven-plugin to use node and npm in your project.
You add package.json to install necessary JavaScript modules, e.g. React.js.
You add webpack.config.js to instruct webpack to transpile the javascript files into a single file named bundle.js and output it to the static folder of the project
You add many execution and goal tags in pom.xml to automate step 2 and 3.
You execute the maven goals to start the automation process.

Related

Gatling : Scala - Could not find or load main class Engine

I am getting error Could not find or load main class Engine while running the simulation through command line. I used below command to create the jar file.
mvn clean scala:compile assembly:single package
Folder Structure
src
test
resources
scala
testrunner
testsimuation1.scala
Engine
IDEPathHelper
Recorder
Maven - 3.6.3
Intellij - 2021.1
Scala - 2.13.10
Gatling - 3.9.0
JDK - 1.8
Below is the POM.xml
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>io.gatling.demo</groupId>
<artifactId>gatling-maven-plugin-demo-scala</artifactId>
<version>3.9.0</version>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<gatling.version>${project.version}</gatling.version>
<gatling-maven-plugin.version>4.2.9</gatling-maven-plugin.version>
<maven-jar-plugin.version>3.2.0</maven-jar-plugin.version>
<scala-maven-plugin.version>4.8.0</scala-maven-plugin.version>
</properties>
<dependencies>
<dependency>
<groupId>io.gatling.highcharts</groupId>
<artifactId>gatling-charts-highcharts</artifactId>
<version>${gatling.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/test/resources</directory>
</resource>
</resources>
<testSourceDirectory>src/test/scala</testSourceDirectory>
<pluginManagement>
<plugins>
<plugin>
<groupId>io.gatling</groupId>
<artifactId>gatling-maven-plugin</artifactId>
<version>${gatling-mvn-plugin.version}</version>
<configuration>
<configFolder>src/test/resources</configFolder>
<simulationsFolder>src/test/scala</simulationsFolder>
<resultsFolder>src/results</resultsFolder>
<simulationClass>testrunner.testsimuation1</simulationClass>
<jvmArgs>
<jvmArg>-Dsimulation=testsimuation1</jvmArg>
<jvmArg>-Xmx6g</jvmArg>
<jvmArg>-Xms2g</jvmArg>
</jvmArgs>
</configuration>
</plugin>
<plugin>
<groupId>net.alchim31.maven</groupId>
<artifactId>scala-maven-plugin</artifactId>
<version>4.4.1</version>
<executions>
<execution>
<id>scala-compile-first</id>
<phase>process-resources</phase>
<goals>
<goal>add-source</goal>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>io.gatling.app.Gatling</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<id>make-assembly</id> <!-- this is used for inheritance merges -->
<phase>package</phase> <!-- bind to the packaging phase -->
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
I tried moving src/test -> src/main but it threw the compilation error. Using this tool for the first time and struggling to resolve the issues.
I tried few solutions from other threads. It didn't help.
Thanks
The Engine class is only supposed to be used as a helper to launch with a "Right Click" when using your IDE.
Using this tool for the first time and struggling to resolve the issues.
You're using maven. The way you're supposed to be running Gatling with maven is to run mvn gatling:test, see gatling-maven-plugin's documentation.
Whatever else you're doing with maven-assembly-plugin is custom development, not really related to Gatling.
Note: if you're looking for handling Gatling deployments, Gatling Enterprise is an option.

How to make REST api call from React app bundled into Spring boot using frontend-maven-plugin?

I create a spring boot project and added a react app (created using create react-app) into it. I want to bundle the REST Api and the frontend in single build (fat jar).
Created spring boot web project, at the root added the frontend folder containing the react code. Here is the plugins inside pom.xml
<?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.2</version>
<relativePath/>
<!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>ppa-test</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>ppa-test</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>11</java.version>
<frontend-src-dir>${project.basedir}/src/main/frontend</frontend-src-dir>
<node.version>v15.7.0</node.version>
<npm.version>7.14.0</npm.version>
<frontend-maven-plugin.version>1.7.6</frontend-maven-plugin.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>com.github.eirslett</groupId>
<artifactId>frontend-maven-plugin</artifactId>
<version>${frontend-maven-plugin.version}</version>
<configuration>
<nodeVersion>${node.version}</nodeVersion>
<yarnVersion>${npm.version}</yarnVersion>
<workingDirectory>frontend</workingDirectory>
<installDirectory>${project.build.directory}</installDirectory>
</configuration>
<executions>
<execution>
<id>install-frontend-tools</id>
<goals>
<goal>install-node-and-npm</goal>
</goals>
</execution>
<execution>
<id>npm-install</id>
<goals>
<goal>npm</goal>
</goals>
<configuration>
<arguments>install</arguments>
</configuration>
</execution>
<execution>
<id>build-frontend</id>
<goals>
<goal>npm</goal>
</goals>
<phase>compile</phase>
<configuration>
<arguments>run-script build</arguments>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<executions>
<execution>
<id>copy-resources</id>
<phase>process-classes</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${basedir}/target/classes/static</outputDirectory>
<resources>
<resource>
<directory>frontend/build</directory>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Here is the github repo link
The project is running on 8087 and http://localhost:80807 does render the App.js. But inside that I made an api call to http://localhost:8087/api/audits which is returning 404 error. I though the Rest controller can be used like this.
What am I doing wrong here?
#EnableWebMvc does expose the Rest endpoint but then the App.js content is not served by the build.
You were right, im sorry. I just cloned your repo and tried. It does just work. Response Code 200 with empty array.
Btw: you do not need the cors configuration. It is only needed if the frontend would be served by another webserver. But when deploying it alongside your spring in a fat-jar - its not necessary since it is not doing cors calls since its the same host.
I just clicked in to the repo and saw your front-end code. The path u
are querying within axios is just
axios.get("/audits")
but has to be
axios.get("/api/audits")
since the controller is annotated with a corresponding
RequestMapping.
#RequestMapping("/api")

Can I create two react application in the one spring project?

I have two different part of the web application, that is a public site and admin site. And I want to create different independent react application for both of them. For the API I use Spring-Boot.
Can I do that in my case?
And what I need to add to the webpack.config.js file?
I tried to create one more HTML page and render to that application. But that does not work. Because one react application render only one time.
I expected to run two different react application using one API.
There are 2 main options:
Split up the 3 applications (spring-boot, react-public, react-admin) into separate repositories and deploy things separately as well.
Use 1 repo for all with a Maven multi-module build
I am going to assume from your question you want to do option 2.
In that case, create a structure like this:
+ project
| - backend-api
| - frontend-public
| - frontend-admin
The parent pom.xml should refer to the 3 modules:
<modules>
<module>backend-api</module>
<module>frontend-public</module>
<module>frontend-admin</module>
</modules>
Each of the modules should refer to the parent pom:
<parent>
<groupId>com.mycompany.myproject</groupId>
<artifactId>myproject</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
Your Spring Boot project will no longer be able to use the Spring Boot parent, so you need to import the BOM dependency:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring.boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
In the frontend-* modules, you should create a zip file, that you can then pull into your Spring Boot module using the maven-dependency-plugin:
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>unzip-webapp-public</id>
<phase>process-resources</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>com.mycompany.myproject</groupId>
<artifactId>frontend-public</artifactId>
<version>${project.parent.version}</version>
<classifier>distribution</classifier>
<type>zip</type>
</artifactItem>
</artifactItems>
<outputDirectory>${project.build.directory}/classes/static/public</outputDirectory>
</configuration>
</execution>
<execution>
<id>unzip-webapp-admin</id>
<phase>process-resources</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>com.mycompany.myproject</groupId>
<artifactId>frontend-admin</artifactId>
<version>${project.parent.version}</version>
<classifier>distribution</classifier>
<type>zip</type>
</artifactItem>
</artifactItems>
<outputDirectory>${project.build.directory}/classes/static/admin</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
This will unzip the react applications to /static/public and /static/admin. As a result, Spring Boot will serve them at /public and /admin in your application.

Spring boot & React production build

I created a spring boot project.After that,I created react project on spring boot project.Right now,both frontend and backend server are running.On frontend folder,I run that command npm run build.
It created a folder which is called build.What I want to do is to run all project with one server.(Example: localhost:8080).I know that I should move frontend files to under static folder.How do I do this?
I tried maven-antrun-plugin but it is not working.
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<phase>generate-resources</phase>
<configuration>
<target>
<copy todir="${project.build.directory}/classes/public">
<fileset dir="${project.basedir}/frontend/build"/>
</copy>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
Use the maven copy resources plugin

Upload React Application to Nexus

I built a React-Application using create-react-app.
The production build is done on Jenkins via:
npm install --prod
npm run build
Then I have the "ready to deploy" artifact.
But how can I get this artifact on my Nexus-Server?
Can i use the version from package.json?
Do I have to make a zip or something like that on my own before uploading?
This would be pretty nice to have a history and it would be easier/faster to build dockers from the artifact on nexus than building again.
How you guys solved that?
Thanks for answers.
I know this question is old, but it might help others.
I recently had to do something similar. My approach was:
Convert the project to a Maven one
Configure my private repository in pom.xml
<distributionManagement>
<snapshotRepository>
<id>RepoId</id>
<url>http://.../repositories/snapshots/</url>
</snapshotRepository>
<repository>
<id>RepoId</id>
<url>http://.../repositories/releases/</url>
</repository>
</distributionManagement>
Configure maven clean plugin to empty the build directory
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-clean-plugin</artifactId>
<configuration>
<filesets>
<fileset>
<directory>build</directory>
<includes>
<include>**/*</include>
</includes>
<followSymlinks>false</followSymlinks>
</fileset>
</filesets>
</configuration>
</plugin>
Configure maven jar plugin to skip the jar creation
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<id>default-jar</id>
<phase>none</phase>
</execution>
</executions>
</plugin>
Integrate frontend-maven-plugin - my project needed yarn, but it can also run with npm
<plugin>
<groupId>com.github.eirslett</groupId>
<artifactId>frontend-maven-plugin</artifactId>
<version>1.12.1</version>
<executions>
<!-- install node & yarn -->
<execution>
<id>install node and yarn</id>
<goals>
<goal>install-node-and-yarn</goal>
</goals>
<configuration>
<nodeVersion>v16.13.0</nodeVersion>
<yarnVersion>v1.22.17</yarnVersion>
</configuration>
</execution>
<!-- yarn install -->
<execution>
<id>yarn install</id>
<goals>
<goal>yarn</goal>
</goals>
</execution>
<!-- yarn run build -->
<execution>
<id>yarn run build</id>
<goals>
<goal>yarn</goal>
</goals>
<configuration>
<arguments>run build</arguments>
</configuration>
</execution>
</executions>
</plugin>
Integrate maven assembly plugin in order to pack everything under build directory into a zip file
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<!-- pack everything under /build into a zip -->
<execution>
<id>create-distribution</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptors>
<descriptor>assembly.xml</descriptor>
</descriptors>
</configuration>
</execution>
</executions>
</plugin>
where assembly.xml looks like:
<?xml version="1.0" encoding="UTF-8"?>
<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.1.0 http://maven.apache.org/xsd/assembly-2.1.0.xsd">
<includeBaseDirectory>false</includeBaseDirectory>
<formats>
<format>zip</format>
</formats>
<fileSets>
<fileSet>
<outputDirectory>/</outputDirectory>
<directory>build</directory>
</fileSet>
</fileSets>
</assembly>
Finally run mvn clean deploy in order to get the zip file uploaded to nexus.
Also, I found this solutions for synchronizing the package.json version with the pom.xml version, but I did not use it.

Resources