Gulp is a modern build system designed around the idea of streaming a set of input files down a pipeline of tasks for automated processing, e.g. concatenation, sourcemap generation, minification, revisioning and many more. LiveReload automatically reloads your application when detecting changes to the source and consists of two parts: a client, implemented as a browser extension (available for Chrome, Firefox, and more) and a server counterpart (we’ll use gulp-livereload, an elegant Gulp integration).
There are many tutorials on setting this up to work with Node.js projects (for starters see here, here and here), but nothing on getting it to work with compiled languages like Golang, so I thought I share my setup.
At the time of writing, there are two tools that try to solve the problem of rebuilding and restarting Go web applications upon changes: Gin and Fresh. Gin acts as a proxy to your application and monitors
*.go files for changes. Fresh monitors every file within your project. While the former misses changes in templates and configuration files, the latter may crash because of too many open file descriptors. Furthermore, none of them comes with LiveReload integration.
For the rest of this article we assume that you are familiar with the basic concepts of Gulp, so we can concentrate on smoothening the build process with Golang.
Gulp is a modern, stream-oriented build system. A set of input files is passed down a pipeline of tasks, e.g. stylesheets written in SASS are passed to the libsass compiler, an Autoprefixer, Media Query merger and Minifier, and finally written to disk. Gulp is very efficient and customizable at monitoring files for changes and will automatically start the associated task when it detects a change in a file.
LiveReload is a browser extensions for Chrome and Firefox that tells your browser to reload assets or whole pages upon notification of the server. Gulp is tightly integrated with LiveReload through gulp-livereload. Stylesheets are reloaded without a full page refresh, enabling instant preview.
We need to define three tasks: the first will rebuild the server, the second will terminate the currently running server process and respawn it, the third will watch for changes in source files to trigger a restart, or a rebuild and a restart. In Golang, the build step can easily be accomplished by invoking
1 2 3 4 5 6
build task is performed synchronously via
spawnSync (see documentation here), as we have to wait for the build to complete before restarting the application server. The
spawn task checks if the server is currently running, terminates it by sending
SIGTERM to the child process and restarts it. When the server sends the first log output (ideally something like
Listening on 127.0.0.1:3000), a reload is triggered and the browser will refresh instantly. Go compiles your application server down to a single binary, so put the name of your binary in line 9:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
watch task watches for changes in source files and performs either of two actions upon the detection of a change:
- It triggers
server:respawnif the changed files do not require a rebuild, but are loaded upon application start, e.g. changes in templates, configuration or locales.
- It triggers
server:rebuildand after completion
server:respawnif the source files demand a rebuild of the application. Obviously, this can not be parallelized.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
You can add files, directories or glob patterns to the watchdogs, tailoring the
watch task to fit your web application’s needs.
Gulp and LiveReload are great technologies that ease web application development by automating the rebuild-restart-reload cycle. While this article showed how to integrate those tools with Golang, it can easily be extended to other languages that require a build step.
For a complete Gulp setup including asset compilation, compression and revisioning, as well as view minification and the discussed automatic application server rebuild and restart, see this Gist.