- 6 minutes read

Let's talk about non-standard Angular project layouts.

Not every Angular project has the priviledge to live in its own domain. Many - or most? - Angular projects are tenants in a shared building. If I've picked it up correctly on the recent JAX conference, there's a new standard architecture. Everybody and their grandma are using Angular as the front-end and Spring Boot as the backend.

I'm sure there are many other architectures out there, but the bottom line is still valid: Angular is only as good as its back-end, and more often than not, both coexist in the same deployment unit. Originally, Martin Fowler's definition of the word "microservice" optionally included the client. For some reason, this idea has gone out of fashion. However, it has resurrected as a "self-contained system", aka SCS, and it's an important part of my approach to micro-frontends.

But that's another day's story. Today, let's cover one simple point: How can Angular and - say - Spring Boot peacefully coexist in the same building? More generally speaking, how to integrate Angular in a Maven project?

Demo project

Before I forget to mention it: there's also a demo project on my GitHub repository.

What about JakartaEE?

Everything I'm writing in this article also applies to JakartaEE projects. I just mention it all the time because this article is part of my Spring Boot series (and because of the perceived dominance of Spring Boot in the Microservice realm).

Learning from JHipster

During the last couple of years, I've tried several approaches. I wasn't happy with any of them. These days I evaluated JHipster, and their approach made a lot of sense to me.

Basically, they bend the Angular project structure to match the project structure of Maven.

In other words, there's a folder called src/main/angular containing the lion's share of the Angular code. That's everything except the root folder. The root folder, in turn, is simply added to the root folder of the Spring Boot project. That's easy because there's only a single file name collision.

OK, it might be a good idea to stick to the truth in a blog. In reality, JHipster puts the Angular application into another standard folder, src/main/webapp. However, my idea is to put the Angular source code into src/main/angular and to convince Angular to compile the binaries to src/main/webapp. This way, we can simply use the standard Maven build to include the Angular app with the Spring Boot app. All we have to do is to make sure we compile Angular first.

Is this possible?

Abandoning the Angular CLI

Obviously it is. As I've mentioned, JHipster leads the way. But I don't like their approach. They've replaced the Angular CLI by the own webpack scripts.

That's a bold move giving programmers maximum flexibility. If you need that, and if you're not afraid of future updates, just use JHipster. It's an awesome tool.

For what it's worth, I prefer to stick to the standard. The idea of Angular is to provide you with opinionated defaults. That's bad because you give up a lot of flexibility, but at the same time it's great because it enables the Angular team to help you.

So let's re-phrase the question again: can we integrate Spring and Angular without loosing the benefits of the Angular CLI?

Actually, that's two questions:

  • Can we bend the configuration of Angular to resemble the Maven structure?
  • Can we convince Maven to compile and include the Angular application with our Spring Boot app?

Configuring Maven

Actually, the second question has been answered years ago. There's a Maven plugin self-consciously claiming to be the "Maven-node-grunt-gulp-npm-node-plugin to end all maven-node-grunt-gulp-npm-plugins". And it seems to be true: I've seen it in every project using both Maven and node.js.

So, just for the sake of completeness, here's a sample pom.xml configuration:

com.github.eirslett frontend-maven-plugin 1.7.6 install node and npm install-node-and-npm v10.15.3 6.9.0 npm install npm webpack build dev npm generate-resources run build false

Configuring Angular

Setting up Angular requires several manual steps. I've created an empty Angular project with the same name as the Spring Boot project. After that, I've copied the top-level files to the root folder of the Spring Boot project, and the content of the src folder went to src/main/angular.

Next thing is to scan for /src in the Json files and replace it with /src/main/angular. That roughly half a dozen changes, give or take a few. You'll also want to fine-tune the lines copying the assets folder and the fav-icon.ico. I've described this in my previous article.

Finally, inspect the tsconfig*.* files. There are a few file includes that must be changed from src to src/main/angular, and it's a good idea to use the Maven folder target instead of the standard output folder.

Both the Spring Boot project and the Angular project bring their .git-ignore files. Merge them, and add the node/ and the src/main/webapp folders. The first is the default working folder of the Eirslett plugin, the second contains generated code which doesn't need to be committed to Git.

That's all! It takes less than five minutes. Now we've got a combined Spring Boot and Angular project. You can start the backend from the root folder with a Maven command. The frontend is also started from the root folder with a standard ng server --open command. To make things even simpler, my demo project adds the CORS rules to the Spring backend, allowing for seamless development.

What about the CLI commands?

That's the one point I'm not happy about yet. The CLI commands work, but only after navigating to the src/main/angular folder. Apart from that, I haven't seen any problems yet.

If you're creating multiple projects or libraries in your Angular project, you might run into trouble with the standard CLI commands, too. I believe that should be covered by our modification of the angular.json, but I haven't tried that yet.

Wrapping it up

Many teams hide the entire frontend code in a non-standard folder, making it the odd man standing out. New team members have to learn where the Angular project is. Other teams segregate the Angular project from it's backend completely, pushing it out of the Spring Boot project. It doesn't have to be that way. After merely five minutes of configuration, Angular and Spring can peacefully coexist in the same Maven project.


Comments