Angular App released in a webjar: issue with baseHref

585 views Asked by At

I need to package my angular frontend in a webjar to be imported, through maven, in whatever java backend.

I did it, so now I have a spring boot backend with the following application.properties

server.servlet.context-path=/demo 

and the following pom.xml

<dependencies>
  <dependency>
    <groupId>com.foo.bar</groupId>
    <artifactId>angular-frontend-webjar</artifactId>
    <version>1.0.0</version>
 </dependency>
 ...     

And this config

@Configuration
public class WebjarConfig extends WebMvcConfigurationSupport {
  
  @Override
  protected void addResourceHandlers(ResourceHandlerRegistry registry) {
    registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
  }

So far so good, I'm able to reach the frontend at the url: http://localhost:8080/demo/index.html
But the angular frontend bootstrap fails because JS/CSS files are not correctly loaded.

The reason is: the contextPath of backend is /demo but the tag <base href="/"> specified into the index.html of the frontend is "/" (root).
So the browser tries to download JS from http://localhost:8080/main-es2015.js instead of http://localhost:8080/demo/main-es2015.js

I've read from the angular doc that is possible to override the base href at the frontend build time with the command ng build --base-href /actualContextPath/, but at that building time I don't know the contextPath of the spring boot app that will import the webjar with the frontend.

Any help?

2

There are 2 answers

1
seqqueman On

Did you try this?

On your pom.xml:

<build>
    <finalName>${project.parent.name}</finalName>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <version>${version.spring-boot}</version>
            <!-- Habilitamos la generacion de un properties con la info de maven 
                accesible desde spring-boot, como el nombre que le queramos dar a la apliacion, 
                para facilitar el desarrollo -->
            <executions>
                <execution>
                    <goals>
                        <goal>build-info</goal>
                    </goals>
                    <configuration>
                        <additionalProperties>
                            <applicationName>${project.parent.name}</applicationName>
                        </additionalProperties>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

Then in your configuration java file you have access to the property "applicationName"

@SpringBootApplication
public class DemoApplication extends SpringBootServletInitializer {
@Autowired
BuildProperties buildProperties;
...

And you can set de application context this way:

@Bean
public WebServerFactoryCustomizer<ConfigurableServletWebServerFactory>
    webServerFactoryCustomizer() {
    return factory -> factory.setContextPath("/"+buildProperties.get("applicationName"));
}

So, on pom.xml applicationName --> "demo" and in your java spring boot config you set the context path to "demo".

This way you use a more dynamic route to set the context path. If you don't want to play with pom.xml you only have to use this:

@Bean
public WebServerFactoryCustomizer<ConfigurableServletWebServerFactory>
    webServerFactoryCustomizer() {
    return factory -> factory.setContextPath("/demo");
}

Good luck and sorry for my English.

1
seqqueman On

OK OK, I got it now.

Set your base href to "./"

Load your webjar scripts like this src="webjars/..." without the "/" before webjars.

And the last point is let Angular manage the routes that are out of Spring. You can check this repo to have an idea, read the las part on the readme:

https://github.com/FraktonDevelopers/spring-boot-angular-maven-build