Spring Boot Live Reload Templates without Restart
Can I just start by exclaiming? ZOMG why was this so difficult to figure out?!?!? I'm working on a new Spring Boot project using Thymeleaf templates. The Java code is actually pretty minimal but there is quite a bit of styling to be done and template work. I wanted to be able to change an HTML file and have LiveReload trigger the browser refresh but the default behavior is for the app to restart as well. After much trial and error I nailed down the right combination of configuration options to make this work.
First, you'll want to move your templates out of the resource directory all together. I just created a new templates directory under src. Reason is, DevTools watches that classpath location for changes, which will trigger an app restart. Plus, I've never been a big fan of templates being wrapped up in JAR/WAR files anyway. Then, update your application config (.properties or .yml) to specify the new location.
spring:
resources:
static-locations: file:./src/static/
thymeleaf:
cache: false
prefix: file:./src/templates/
devtools:
restart:
enabled: true
livereload:
enabled: true
(for the file:
paths to work, you'll need to setup your working directory in your IDE's run configuration. Otherwise, use the absolute path. And it's probably a good idea to have a dev profile different from what you want to do in production)
Now for the confusing part. You need to tell devtools.restart
about the additional paths to watch.
spring:
resources:
static-locations: file:./src/static/
thymeleaf:
cache: false
prefix: file:./src/templates/
devtools:
restart:
enabled: true
additional-paths: ./src/templates/
livereload:
enabled: true
But wait, this tells restart
to restart
when something changes in that path. I thought we wanted to disable restarts but only allow reload? Well, that's the confusing part. In order to trigger the reload to fire, it has to be in restart.additional-paths
but then we need to exclude it from the restart with restart.additional-exclude
.
spring:
resources:
static-locations: file:./src/static/
thymeleaf:
cache: false
prefix: file:./src/templates/
devtools:
restart:
enabled: true
additional-exclude: "**/*.js,**/*.css,**/*.html"
additional-paths: ./src/templates/
livereload:
enabled: true
So I don't know. It's weird. It's confusing. It's undocumented that it works this way. But hey, it works! I guess I should stop complaining and just go submit a PR to the Spring Documentation. After all, it is open source. I love you Spring!