Spring Boot and Thymeleaf: Reload templates and static resources without restarting the application
Thymeleaf was designed around the concept of Natural Templates that allows static prototyping: template logic doesn’t affect the template from being used as prototype. Although this is a great technique, you may also want to see the results in a running Spring Boot application and without restarting the server each time you change Thymeleaf view. In addition, you may expect that all other static resources like JavaScript and CSS files can be reloaded during development also. How to achieve it with Spring Boot?
Thymeleaf templates reloading
While working on a Spring Boot application that is utilizing Thymeleaf view engine two properties are needed in order to ensure reloading templates: spring.thymeleaf.cache
and spring.thymeleaf.prefix
. Setting spring.thymeleaf.cache
to false
disables template caching whereas spring.thymeleaf.prefix
allows specifying prefix that gets prepended to view names when building a view URL.
Example (Windows):
spring.thymeleaf.prefix=file:///C:/Projects/github/spring-boot-thymeleaf/src/main/resources/templates/
Assuming the all templates are in the path specified, changing them will require a page refresh but not application / server restart.
Both properties can be used in a development profile (e.g. create application-dev.properties
and run the application with dev
profile active).
Reload static resources (CSS, JavaScript)
With Spring Boot and Thymeleaf reloading templates during development is relatively easy. If you want to achieve reloading of static resources like CSS and JavaScript the approach is very similar: you need to use spring.resources.static-locations
.
Example (Windows):
spring.resources.static-locations=file:///C:/Projects/github/spring-boot-thymeleaf//src/main/resources/static/
In the above example there is a single location, but the property accepts multiple locations.
Furthermore, you can configure more settings related to static resources, like for example caching etc. Please refer to Spring Boot documentation and find out about spring.resources.*
properties (http://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html)
application-dev.properties
The final solution could look like below:
#
# Development profile with templates and static resources reloading
#
# Path to project
project.base-dir=file:///C:/Projects/github/spring-boot-thymeleaf
# Templates reloading during development
spring.thymeleaf.prefix=${project.base-dir}/src/main/resources/templates/
spring.thymeleaf.cache=false
# Static resources reloading during development
spring.resources.static-locations=${project.base-dir}/src/main/resources/static/
spring.resources.cache-period=0
Note: You will find it in the source code reference in this article: HOW-TO: Spring Boot and Thymeleaf with Maven
If you don’t want to create new profile, you can simply provide properties as JVM options (-D
) while running the application.
Alternative approach - Spring Boot DevTools
One of the modules of Spring Boot is the DevTools (as of version 1.3). Among many features it enables live reloading Thymeleaf templates and static resources without any further configuration. It has also support for LiveReload protocol.
Note: When you change the template / resource rebuild the project (CTRL+F9 on Windows) and then refresh. When you install LiveReload plugin (I tested with LiveReload plugin for Chrome: https://chrome.google.com/webstore/detail/livereload/jnihajbhpnppcggbcgedagnkighmdlei) after rebuild the page gets refreshed automatically.
Find out more here: https://spring.io/blog/2015/06/17/devtools-in-spring-boot-1-3 and here: https://t.co/td23nP73mt
Summary
You can make frontend development of the Spring Boot application much easier thanks to the techniques described in this article. But possibility of serving Thymeleaf templates and static resources of your Spring Boot application from outside the classpath in production could bring some advantages too. One of the example could be separating backend and frontend deployments.
project.base-dir=file:///C:/Projects/github/spring-boot-thymeleaf
ReplyDeletethis line is ridiculous, it means that your project will be able to build only from a single location)) so study how include thymeleaf instead of breaking spring boot with redefined vars
Thanks for very gentle comment ;)
DeletePushing this to repo indeed may sound ridiculous but this is just an example to give an idea. I provide this property via CLI while developing.
And please share your idea of doing this better.
An alternative is to use a relative path like this:
Deletespring.thymeleaf.prefix: file:./src/main/resources/templates/
Just make sure that your working directory is set correctly.
An alternative is to use a ralative URL like this:
Deletespring.thymeleaf.prefix: file:./src/main/resources/templates/
Just make sure your working directory is correct.
Hey,
ReplyDeleteThe cache false property work only if we are using an IDE like eclipse or intellij. IF we are running the application from terminal using maven e,g, mvn clean install tomcat7:run with tomcat server, it does not work. Please do let me know if this works without IDE.
Thanks,
Chirag
Hello,
DeleteThe described approach will work outside the IDE.
Run the Spring Boot application using Spring Boot plugin (either Maven or Gradle).
Thanks it's work perfectly
ReplyDeleteThanks Rafa, it worked like a charm :)
ReplyDeleteGreat tutorial...
ReplyDeletefor universal URL many OS
spring.thymeleaf.prefix: file:./src/main/resources/templates/
thank you woks great
ReplyDeleteThis is good!
ReplyDeleteWhy not use Gulp? I recommend using it to automate templates and resources reload. Following is a little Gulp task that does the magic for me:
ReplyDeletevar gulp = require('gulp'),
watch = require('gulp-watch');
gulp.task('watch', function () {
return watch('src/main/resources/**/*.*', () => {
gulp.src('src/main/resources/**')
//replace with build/resources/main/ for netBeans
.pipe(gulp.dest('out/production/resources/'));
});
});
gulp.task('default', ['watch']);
I also wrote a short blog post (https://attacomsian.com/blog/spring-boot-auto-reload-thymeleaf-templates/) on this topic which includes other methods as well.