nREPL in action - n is for Network
The REPL (Read Eval Print Loop) is a pretty cool piece of technology.
I got my first taste of the REPL with python, which was really cool, having been trained in C++. All of the sudden I could query the state of my program, while it was still running. Debuggers in all their glory, but this was a new tool in the toolbox, that allowed for previous unparalled flexibility.
n is for Network
The real killer feature is when you add network into the mix. This allows for you to send commands to the REPL, that is running inside your active program, and update and modify your program, while it is still running, from inside your editor. This is a highly interactive type of programming, that allows insights into your program, that is difficult to achieve when your toolbox is limited to compiling your code, run the program, reason in your head how it works and use the debugger as a poor man’s REPL.
But wait… n is for network. Can I use this on other machines? Yes… yes you can.
shadow-cljs and webapps
The following script is called with remote-shadow-cljs.sh <ip-or-url>
. It’s setup to
allow multiple developers to develop against a frontend based on shadow-cljs, where the
frontend is not running on the local computer, but instead on a phone or a tablet.
dev-index-browser.html
is an HTML file which you use a template for injecting the
URL/IP that shadow-cljs is running from. The only thing you now need is ${url}
in the HTML file,
where it should point towards the URL/IP where shadow-cljs is running.
It’s also very possible and easy to add extra URLs/IPs if need be.
#!/bin/bash
APP_URL=$1
URL_RX='\${url}'
prep_index () {
echo "Preparing index.html for remote REPL"
rm www/index.html
cp dev-resources/dev-index-browser.html www/index.html
sed -i -e "s/$URL_RX/http:\/\/$APP_URL\//g" www/index.html
}
prep_index
echo "Running: shadow-cljs watch :web --config-merge '{:asset-path \"http://$APP_URL:8700/js/compiled\", :devtools {:devtools-url \"ws://$APP_URL:9630/wsapp\"}}'"
shadow-cljs watch :web --config-merge "{:asset-path \"http://$APP_URL:8700/js/compiled\", :devtools {:devtools-url \"ws://$APP_URL:9630/wsapp\"}}"
If you supplement it with SSH tunneling it’s also possible to develop against a public domain name. You would need to adapt the script with regards to ports and protocol (HTTP or HTTPS).
shadow-cljs and cordova
If you want to wrap your webapp in a container, Cordova is a good choice. You now definately have a need for nREPL to work with a remote connection to Cordova.
The script (shoutout to Daniel Wasa Delatre for the MacOS vs Linux check):
#!/bin/bash
RX='([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])'
case "$(uname -s)" in
Darwin)
DEV_IP=$(ip route get 1 | head -1 | cut -d' ' -f8)
;;
Linux)
DEV_IP=$(ip route get 1 | head -1 | cut -d' ' -f7)
;;
esac
echo "Running: shadow-cljs watch :cordova --config-merge '{:asset-path \"http://$DEV_IP:8700/js/compiled\", :devtools {:devtools-url \"ws://$DEV_IP:9630\"}}'"
shadow-cljs watch :cordova --config-merge "{:asset-path \"http://$DEV_IP:8700/js/compiled\", :devtools {:devtools-url \"ws://$DEV_IP:9630\"}}"
Note |
The start HTML file (typically index.html) is specified in the config.xml that Cordova uses.
|
Regular clojure and nREPL
Working with nREPL on a different machine is a fairly straightforward process. Start the nREPL on that machine and connect to it via the IP and port.
There are two things you can do to make your life a lot easier if you do this on a a regular basis.
The first thing you can do is to set the port in the configuration to always be
the same. In leiningen, which is what I’ve used the most, you would set the
port for the machine in ~/.lein/profiles.clj
with {:repl-options {:port <port-number}}
.
With this simple configuration you achieve ease of use (always same port) and
keeping the configuration out of the project.
The second thing you can do is to make the IP/URL to the machine always be the same.
Control over the local network can afford to give you name based addresses to the machine, so that you don’t need to know the IP address.
You can use a VPN to make sure you always have the same IP to the machine, regardless of what network the machine is on. I have used Wireguard to great effect here.
Or use Calva
PEZ (Peter Strömberg) seems to be in hyperdrive to make life easier for us poor programmers. I’m still an Emacs fanboy, but whenever I try out Calva I’m impressed by how easy the UI is to hook things up is. Instead of fighting with the tooling, you just get started with cracking away at the problem you want to solve.
That said, some of the things mentioned are probably still of use.
Happy coding :).