In order to improve developer experience I tried to include Spring Dev Tools.
My setup:
- Multiple modules
- Gradle 6.6
- Spring Boot 2.4.2
- Thymeleaf
- React with Webpack for subpages
I use a multi project gradle build with a settings.gradle
file and one submodule that also has the spring boot bootJar
. In that build.gradle
's file I added the developmentOnly("org.springframework.boot:spring-boot-devtools")
line.
IntelliJ Configuration
I start my Application via IntelliJ:
I also enabled the 'Build project automatically' in the 'Settings > Compiler' settings as well as the 'compiler.automake.allow.when.app.running'.
What works
When I start the application I see the log message
[2021-03-17 14:18:02.001] INFO [restartedMain] --- o.s.b.d.a.OptionalLiveReloadServer: LiveReload server is running on port 35729
stating that my LiveReloadServer started.
When I apply changes in my Java files files the build and restart are triggered so the restart on changes does work - it is pretty slow though - even if I just change a single line in a Java class the rebuild takes 15 seconds at least.
What does not work
When I apply changes to my HTML, CSS or JS files or to my react app, changes are only reflected once the project is rebuilt. All of my resources are in the default resources/static
folder so they should be handled by dev-tools reload.
FYI I package my react-app with webpack and when I start the webpack watch
task it correctly rebuilds my bundle.js whenever I apply changes.
I do have a custom ResourceRegistryHandler setup, mabye this is part of the problem even though I wouldn't understand why:
@Override
public void addResourceHandlers(final ResourceHandlerRegistry registry) {
boolean devMode = this.env.acceptsProfiles(Profiles.of("dev"));
boolean useResourceCache = !devMode;
final String[] pathPatterns = Arrays.stream(RESOURCE_FOLDERS).map(f -> f + FOLDER_SUFFIX)
.toArray(String[]::new);
final String[] resourceLocations = Arrays.stream(RESOURCE_FOLDERS).map(f -> CLASSPATH_PREFIX + f)
.toArray(String[]::new);
if (useResourceCache) {
resourceProperties.getCache().setPeriod(Duration.of(365, ChronoUnit.DAYS));
registry.addResourceHandler(pathPatterns)
.addResourceLocations(resourceLocations)
.setCachePeriod((int) Duration.of(365, ChronoUnit.DAYS).getSeconds())
.resourceChain(true)
.addResolver(new VersionResourceResolver().addContentVersionStrategy("/**"))
.addTransformer(new CssLinkResourceTransformer());
} else {
resourceProperties.getCache().setPeriod(Duration.of(0, ChronoUnit.DAYS));
registry.addResourceHandler(pathPatterns)
.addResourceLocations(resourceLocations)
.setCachePeriod(0)
.resourceChain(false);
}
}
Live Reload
Next to the fact, that static resources aren't refreshed at all yet, I also wondered how to use the live reload chrome plugin because I always get a popup stating Cannot download livereload.js
when I want to enable my live reload browser plugin.
My Quesions
- How can I get Spring to refresh static resources? They don't even refresh on a reload of the page for me, only once the restart has been triggered and finished
- How can I get this to work with Live Reload?
I would also appreciate any hints on why my build of the project could take that long even with that little changes, I'll probably check gradle build scans for that.