Live-reload Dev Server for j2cl:watch #63
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Happy new year J2CL!
This PR enhances j2cl:watch's incremental recompilation with a live-reloading dev-server. The server serves resources from the configured
webappsDirectory
for an artifact. When an incremental recompilation is triggered, or a resource insrc/main/webapp
is changed, j2cl:watch triggers a reload in connected browser sessions.A video of the process in action is available here, and I've made a public example. I've also tested this feature on a multi-module, large SPA I've been working on.
Non Goals
It is not a goal of this PR to implement hot-swapping. Besides greater complexity, hot-swapping requires knowledge about the application to hot-swap (which is why it's typically a feature in frameworks, not build tools). Finally, hot-swapping allows applications to shirk the responsibility of handling location.reload() events in a graceful manner.
Because of these reasons, the vast majority of popular Javascript dev-servers implement live-reloading, and not hot-swapping. Examples include Facebook's react-scripts, es-dev-server and its successor @web/dev-server, webpack-dev-server, and even the (bare bones) j2cl Bazel plugin.
Configuration
The WatchMojo has four new configurable parameters:
Dependent Changes
The first commit improves the integration tests, which were configured without specifying the Java or maven-war-plugin versions.
The second commit harmonizes j2cl:build and j2cl:watch outputs by changing j2cl:build's
initialScriptFilename
to${artifactId}.js
.Now that :watch copies resources like index.html to
${webappsDirectory}/${artifactId}/
,it was not clear which
<script>
src to use for the output js(:watch needs
src="/${artifactId}.js"
to resolve, and :buildneeds
src="/${artifactId}/${artifactId}.js"
).By setting :build's
initialScriptFilename = ${artifactId}.js
by default,index.html can simply use
<script src="/${artifactId}.js"></script>
withoutconfusion.
WatchService Enhancements
One problem I know @mdproctor has experienced is that incremental reloads are very slow on MacOS. I have encountered this problem before, and it stems from the JDK using a polling implementation on that platform.
If you look here, you will see that I am registering Paths with the
SensitivityWatchEventModifier.HIGH
Modifier.I booted up my old macbook, and can confirm that after the first compilation, performance dramatically improves and is comparable to my Linux desktop.
j2cl:watch Timeout
Instead of timing out after 30 seconds, j2cl:watch now exits after some System.in input.
Version Bump
Note that the version has been bumped to
0.17-SNAPSHOT
when testing.Implementation Details
The core addition is
tools/DevServer.java
.I am quite happy with the features afforded in under 600 commented lines:
Future Changes
In a future Issue, I would like to rename parameter
webappDirectory
toj2clBuildDirectory
. This is much more clear, since the parameter isn't used to locatesrc/main/webapp
, but rather the build output folder.