peach
peach

Reputation: 757

Spring Boot Dev Tools / Live Reloading - refresh of static resources is not working

In order to improve developer experience I tried to include Spring Dev Tools.

My setup:

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:

enter image description here

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

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.

Upvotes: 4

Views: 2597

Answers (1)

Peter Süpfle
Peter Süpfle

Reputation: 1

Regarding

How can I get this to work with Live Reload?

I had the same kind of problem and a similar setup. With a React frontend which was build by webpack and copied the output into the /target/classes/static folder. I also used the live reload chrome plugin.

I noticed that sometimes the live reload works and sometimes not. The live reload server was always started and I could download the livereload.js from it. But the plugin was always complaining that it can't download the file.

In one of the sporadic cases where it was working I noticed in the chrome html inspector there was a tag injected with a reference to the livereload.js. When live reload wasn't working the injected script tag was missing.

As it turns out all that live reload chrome plugin does, is inject the reference to the .js file, but that almost never works.

So I went ahead and added this in my thyleaf template

<script th:if="${@environment.acceptsProfiles('dev')}" src="http://localhost:35729/livereload.js"></script>

With that it was working all the time. I deinstalled the chrome plugin afterwards.

TLDR

For live reload to work you need a live reload server running on your machine and a live reload client in your html (the livereload.js from the server)

<script src="http://localhost:35729/livereload.js"></script>

Livereload.js Github

Upvotes: 0

Related Questions