DEV Community

Run React Frontend and SpringBoot Backend on the same port and Package them as a single artifact !!

Arpan Banerjee on April 10, 2021

Find out how to combine create-react-app with Spring Boot to give you a single artifact. Hey there! I am a full stack developer with 3+ ...
Collapse
 
jprakzaw profile image
Jim Prakash-Zawisza

Excellent resource! I wanted a single JAR file containing both my frontend and my backend that I could deploy to AWS Elastic Beanstalk, and this was invaluable in getting there.

The section on using Thymeleaf to avoid specifying index.html manually has a couple of issues, though. The spring.thymeleaf.prefix path provided is an absolute path, which won't work at all in the context of a deployment to a cloud resource. Another commenter suggested using file:./target/classes/static/ for the value of spring.thymeleaf.prefix, but this also won't work outside of your local system. When the Spring Boot JAR file gets built, the React frontend will be copied to the BOOT-INF/classes/static directory. Since BOOT-INF/classes is in your classpath, something like spring.thymeleaf.prefix=file:./static/ should work in the context of the JAR file.

But that masks a bigger issue: there's actually no need to use Thymeleaf at all. You can use Spring Boot redirects to achieve the same thing with much less work. Here's an example of a redirecting controller that takes a URL like example.com and does a forward to send the user to example.com/index.html:

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class IndexController {
    @GetMapping("/")
    public String forwardToIndex() {
        return "forward:/index.html";
    }
}
Enter fullscreen mode Exit fullscreen mode

In the browser, you'll still see example.com. If you replace forward with redirect in the string returned by forwardToIndex, you would see example.com/index.html in your browser instead.

When trying to deploy to Elastic Beanstalk, I had a lot of problems with Thymeleaf, even though the JAR file did the right thing on my local machine. Once I switched to redirects, I was able to deploy successfully.

Collapse
 
peterkronenberg profile image
Peter Kronenberg • Edited

Hope you don't mind some questions. If there is a better place to post them, let me know. I got your demo working. But when I try it with my React app, I can't get anything other than index.html to show. If I just enter localhost:8080, I get my default React page. If I enter localhost:8080/index.html, I get the generic index.html with no dynamic content. (tried to attached screenshot, but it doesn't work)
If I enter any of my other routes, such as localhost:8080/login, I get the Whitelabel error page. Any suggestions? Do you have a sample that has anything other than the default React app?

Note that if I browse directly to React at localhost:3000, the client responds properly

Collapse
 
shikharajpoot13 profile image
SHIKHA RAJPOOT

Hey Peter, did you find the anwser to your question? If yes please do share the solution.

Collapse
 
mostafamirzaee profile image
Mostafa S.Mirzaei

Bro, you guys are saints. you who spend a lot of time to share your knowledge freely by righting these articles. I will join you guys soon. thanks a lot for making other developers' lives much easier.

Collapse
 
peterkronenberg profile image
Peter Kronenberg

Thank you so much for this! Have been trying to figure this out for days. I'm an experienced Java developer, but new to Javascript frameworks. It was so hard to find a clear article on how to do this.

Collapse
 
ivanbo97 profile image
ivanbo97 • Edited

Hello and thank you for the in-depth tutorial !

In case someone is interested. There is also an alternative way of combining create-react-app with Spring Boot in a single artifact which does not require adding of maven-resources-plugin. In configuration part of frontend-maven-plugin you just need to set an environment variable with the name BUILD_PATH (ref : create-react-app.dev/docs/advanced...) and value ${basedir}/target/classes/static . In this way you are forcing frontend-maven-plugin to output the generated production build directly in target/classes/static. Therefore, we do not need maven-resources-plugin for making intermediate copies. I hope it makes sense.

Collapse
 
hendisantika profile image
Hendi Santika

Can you update it using the latest version?
It error on my side while running mvn clean package

Thanks

Collapse
 
azizbekavazov profile image
AzizbekAvazov • Edited

Thanks for this tutorial!
Here spring.thymeleaf.prefix path is hardcoded. How can we give it relative path?

Collapse
 
markhennings profile image
Mark Hennings

This path worked for me in my application.properties:
spring.thymeleaf.prefix=file:./target/classes/static/

Collapse
 
declantreanor profile image
declanTreanor

A more comprehensive guide than this probably couldn't be found. Armed with these two great tools in unison, I'm unstoppable, or at least, I should be.

Collapse
 
borche profile image
Andreas Börjesson

Good article. Thanks for sharing.