Angular2 and Spring Boot. How to serve front-end? Angular2 and Spring Boot. How to serve front-end? heroku heroku

Angular2 and Spring Boot. How to serve front-end?


In my organization, we have a lot of Spring Boot and Angular apps. When two servers are unnecessary, Spring Boot can serve up the static content from any supported URL (such as "http:" or "file:"). Simply pass this argument to your app on startup:

--spring.resources.static-locations=<url>

Spring Boot can also support Angular single-page app routing by including the following web MVC configuration. This ensures that even if the user refreshes the page in the browser, Spring Boot will still serve up the contents of index.html for other angular routes.

public class SinglePageAppWebMvcConfigurer extends WebMvcConfigurerAdapter{    @Autowired    private ResourceProperties resourceProperties;    private String apiPath = "/api";    public SinglePageAppWebMvcConfigurer()    {    }    public SinglePageAppWebMvcConfigurer(String apiPath)    {        this.apiPath = apiPath;    }    protected String getApiPath()    {        return apiPath;    }    @Override    public void addResourceHandlers(ResourceHandlerRegistry registry)    {        registry.addResourceHandler("/**")            .addResourceLocations(resourceProperties.getStaticLocations())            .setCachePeriod(resourceProperties.getCachePeriod()).resourceChain(true)            .addResolver(new SinglePageAppResourceResolver());    }    private class SinglePageAppResourceResolver extends PathResourceResolver    {        @Override        protected Resource getResource(String resourcePath, Resource location) throws IOException        {            Resource resource = location.createRelative(resourcePath);            if (resource.exists() && resource.isReadable()) {                return resource;            } else if (getApiPath() != null && ("/" + resourcePath).startsWith(getApiPath())) {                return null;            } else {                LoggerFactory.getLogger(getClass()).info("Routing /" + resourcePath + " to /index.html");                resource = location.createRelative("index.html");                if (resource.exists() && resource.isReadable()) {                    return resource;                } else {                    return null;                }            }        }    }}


Option 1One server process hosting REST APIs and another server process hosting Angular UI

This option is the recommended option in a MicroServices based architecture where the individual APIs (or small related group of APIs) are run and scaled separately by hosting them in separate server processes. In such scenarios, if the Angular UI is also bundled with the REST APIs, it would mean that every bug-fix or enhancement in the Angular UI would require rebuilding and redeployment of your services. And when we start doing that, it would defeat the purpose of Microservices based architecture.

Therefore, in such an architecture one or more server instances would host only the Angular UI. The Angular UI would in turn call the individual APIs through an API Gateway using some service discovery mechanism. However, Microservices based architecture is not trivial - it's complex with a lot of moving parts. Such level of complexity can be justified for large projects.

Option 2One server process hosting both REST APIs and Angular UI

This option is the recommended option for small to medium sized projects where the user base is a few hundred users.

In such projects, create a single repository where a Maven project would contain two sub-modules - one for the REST APIs and the other for the Angular UI.

Use the Maven plugin "frontend-maven-plugin" to build the UI part. This will automatically download the specified NodeJs version and invoke appropriate npm commands to build the Angular project. Finally, using the Maven element copy the Angular dist folder to the Spring Boot static folder under the resources folder. (In the .gitignore file exclude the static folder so that the Angular distribution files are not checked into the source control along with the REST APIs).

Now, as the Java build will start, it would automatically include the static folder in the fat jar which would now serve both the APIs and the Angular UI.


So far I created applications with angular and spring-boot, using one git repository, but two different maven projects, one for the backend, one for the frontend.

With Maven than I built one fat jar with an embedded Tomcat and deployed it to Amazon EC2.

I also experimented with Heroku and you could for sure deploy the same fat jar there.

For the next project I would take another approach and deploy all static resources like html, javascript etc. to Amazon S3 and only the spring-boot app to a provider like heroku.

Frontend deployment this way seems to be much easier, faster and cheaper.

There is also a blog post about Using AWS S3 to Store Static Assets and File Uploads