# Is it possible to use Revise.jl to reload webserver on file save?

**URL:** <https://discourse.julialang.org/t/is-it-possible-to-use-revise-jl-to-reload-webserver-on-file-save/94866>\
**Category:** General Usage\
**Created:** [February 19, 2023, 5:30am UTC](https://discourse.julialang.org/t/is-it-possible-to-use-revise-jl-to-reload-webserver-on-file-save/94866 "2023-02-19T05:30:18Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![zeroexcuses](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/zeroexcuses/32/46846_2.png) [@zeroexcuses](https://discourse.julialang.org/u/zeroexcuses)\
**Post date:** [February 19, 2023, 5:30am UTC](https://discourse.julialang.org/t/is-it-possible-to-use-revise-jl-to-reload-webserver-on-file-save/94866/1 "2023-02-19T05:30:18Z")

</div>

In [Compile time: we can't find any impls for this multi dispatch fn? - #7 by zeroexcuses](https://discourse.julialang.org/t/compile-time-we-cant-find-any-impls-for-this-multi-dispatch-fn/94736/7) , I described a shell script which uses inotify to restart a webserver every time www/server.jl is modified.

I was informed the “correct” way to do this is to use Revise.jl but not the details of _how_ to do it.

Question: using Revise.jl is there a way to restart/reload a webserver on file save to www/server.jl ?

---

<div class="post-metadata">

**Author:** ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)\
**Post date:** [February 19, 2023, 5:33am UTC](https://discourse.julialang.org/t/is-it-possible-to-use-revise-jl-to-reload-webserver-on-file-save/94866/2 "2023-02-19T05:33:58Z")

</div>

what are you using in `server.jl`, as far as I can tell, HTTP.jl works with Revise, and Genie.jl includes Revise.jl as part of it

---

<div class="post-metadata">

**Author:** ![zeroexcuses](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/zeroexcuses/32/46846_2.png) [@zeroexcuses](https://discourse.julialang.org/u/zeroexcuses)\
**Post date:** [February 19, 2023, 6:55am UTC](https://discourse.julialang.org/t/is-it-possible-to-use-revise-jl-to-reload-webserver-on-file-save/94866/3 "2023-02-19T06:55:22Z")

</div>

server.jl starts a HTTP server on 8080 for handling GET / POST requests.

I make some changes to server.jl (add/del a route) save the file, then the bash script restarts the HTTP server. How would you achieve this with Revise.jl ?

---

<div class="post-metadata">

**Author:** ![albheim](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/albheim/32/34660_2.png) [@albheim](https://discourse.julialang.org/u/albheim)\
**Post date:** [February 19, 2023, 7:42am UTC](https://discourse.julialang.org/t/is-it-possible-to-use-revise-jl-to-reload-webserver-on-file-save/94866/4 "2023-02-19T07:42:00Z")

</div>

There is an [example](https://timholy.github.io/Revise.jl/stable/#Other-Revise-workflows-1) in the Revise docs of the basic workflow for running some webserver with some assets with automatic reloading.

In my understanding (not tested this) the idea would be to have a main file that you don’t change, and this loads revise as well as the package/file that contains the code to start your server and runs the main entrypoint to the server in the way defined in the revise example workflow I linked. Now it should automatically update the julia runtime with any updated code/assets if they are monitored by revise, so you don’t need to restart the server on update.

---

<div class="post-metadata">

**Author:** ![zeroexcuses](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/zeroexcuses/32/46846_2.png) [@zeroexcuses](https://discourse.julialang.org/u/zeroexcuses)\
**Post date:** [February 19, 2023, 10:04am UTC](https://discourse.julialang.org/t/is-it-possible-to-use-revise-jl-to-reload-webserver-on-file-save/94866/5 "2023-02-19T10:04:14Z")

</div>

Are you referring to

```julia
entr(["file.js", "assets"], [MyWebCode]) do
    build_webpages(args...)
end

```

This is about as useful as `inotify / watch`.

What can we do with this? If we use `kill -9 + julia server.jl`, it’s not much of a improvement; we’ve merely moved “watching” to julia.

If there is some other way here of killing+ restarting the http server when src/server.jl is changed, (which I think many are hinting at), please let me know how.

---

<div class="post-metadata">

**Author:** ![albheim](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/albheim/32/34660_2.png) [@albheim](https://discourse.julialang.org/u/albheim)\
**Post date:** [February 19, 2023, 12:39pm UTC](https://discourse.julialang.org/t/is-it-possible-to-use-revise-jl-to-reload-webserver-on-file-save/94866/6 "2023-02-19T12:39:53Z")

</div>

I was just answering the question of how I think this would be done with revise which is what I though you were asking for. I think this is what other people hinted at as well but I might be wrong.

What do you mean by other way of killing + restarting the app, why do you want more ways? If you are happy with your way go with it, otherwise give revise a try. Or are you looking for some functionality that neither of them provide? In that case I might have misunderstood exactly what you want and need a clearer explanation.

To me it seems like a cleaner approach to use revise compared to the bash kill+restart, it is not “just” moved to julia IMO, though having it all in julia is nice by itself.  
It as well allows for not restarting the julia session since revise just injects any updates into the running session IIUC. This seems like it should be more efficient, though I have not tested any of this so I might be completely off.

---

<div class="post-metadata">

**Author:** ![tim.holy](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tim.holy/32/52_2.png) [@tim.holy](https://discourse.julialang.org/u/tim.holy)\
**Post date:** [February 19, 2023, 12:46pm UTC](https://discourse.julialang.org/t/is-it-possible-to-use-revise-jl-to-reload-webserver-on-file-save/94866/7 "2023-02-19T12:46:00Z")

</div>

> [@zeroexcuses](#):
>
> If there is some other way here of killing+ restarting the http server when src/server.jl is changed, (which I think many are hinting at), please let me know how.

As stated in [Compile time: we can't find any impls for this multi dispatch fn? - #23 by tim.holy](https://discourse.julialang.org/t/compile-time-we-cant-find-any-impls-for-this-multi-dispatch-fn/94736/23), I think you’re failing to understand that you don’t have to kill it just because `src/server.jl` changed. (IIUC, Scala can’t recompile code within the same session when the code changes. But Julia most definitely can.) If you’re using Revise, you can update the running session, and all you need to do is regenerate the web pages.

---

<div class="post-metadata">

**Author:** ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)\
**Post date:** [February 19, 2023, 3:02pm UTC](https://discourse.julialang.org/t/is-it-possible-to-use-revise-jl-to-reload-webserver-on-file-save/94866/8 "2023-02-19T15:02:12Z")

</div>

> [@zeroexcuses](#):
>
> then the bash script restarts the HTTP server.

With Revise.jl, you don’t need to kill the Julia process, just refresh the webpage in your browser and you should see change taking effect. Let us know if it doesn’t work

---

<div class="post-metadata">

**Author:** ![zeroexcuses](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/zeroexcuses/32/46846_2.png) [@zeroexcuses](https://discourse.julialang.org/u/zeroexcuses)\
**Post date:** [February 19, 2023, 7:37pm UTC](https://discourse.julialang.org/t/is-it-possible-to-use-revise-jl-to-reload-webserver-on-file-save/94866/9 "2023-02-19T19:37:16Z")

</div>

I understand that many of you are claiming that I am using HTTP.jl incorrectly and do not understand the full power of Revise.jl.

I am asking this: can any of you point me to sample code for how to correctly setup HTTP.jl with Revise.jl ?

---

<div class="post-metadata">

**Author:** ![mkitti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkitti/32/12459_2.png) [@mkitti](https://discourse.julialang.org/u/mkitti)\
**Post date:** [February 19, 2023, 7:50pm UTC](https://discourse.julialang.org/t/is-it-possible-to-use-revise-jl-to-reload-webserver-on-file-save/94866/10 "2023-02-19T19:50:19Z")

</div>

```julia
using Revise
using HTTP

using YourModule

```

Oh, you don’t have a module?

```julia
using Revise
using HTTP

includet("yourscript.jl")

```

---

<div class="post-metadata">

**Author:** ![zeroexcuses](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/zeroexcuses/32/46846_2.png) [@zeroexcuses](https://discourse.julialang.org/u/zeroexcuses)\
**Post date:** [February 19, 2023, 8:10pm UTC](https://discourse.julialang.org/t/is-it-possible-to-use-revise-jl-to-reload-webserver-on-file-save/94866/11 "2023-02-19T20:10:40Z")

</div>

Did you test your ‘solution’ before posting ?

Here are my expriments:

```julia
// inner.jl
using HTTP

const HOST = "127.0.0.1"
const PORT = 8080

println("Server Started")

router_8080 = HTTP.Router();

function do_8080(_::HTTP.Request)
    local r = HTTP.Response(200, "Hello World");
    return r;
end

HTTP.register!(router_8080, "GET", "/", do_8080)
HTTP.register!(router_8080, "GET", "**", do_8080)

HTTP.serve(router_8080, "127.0.0.1", 8080)
HTTP.serve(router_8001, "127.0.0.1", 8001)

```

```julia
// outer.jl
using Revise
using HTTP

include("inner.jl")

```

1. I run the code via “julia outer.jl” ; I load the page, “Hello World”

2. I modify inner.jl to say “Hello World 2”

3. I save.

4. I reload browser, still says “Hello World” (even with disable cache in dev console)

Back to the original question: What is the ‘correct’ way to setup HTTP.jl with Revise.jl for “auto reload after save” ?

---

<div class="post-metadata">

**Author:** ![stephenll](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stephenll/32/28751_2.png) [@stephenll](https://discourse.julialang.org/u/stephenll)\
**Post date:** [February 19, 2023, 8:15pm UTC](https://discourse.julialang.org/t/is-it-possible-to-use-revise-jl-to-reload-webserver-on-file-save/94866/12 "2023-02-19T20:15:49Z")

</div>

@mkitti used `includet` that is `include` with a `t` at the end of it. You are using `include` without the `t`. That may be the reason you are not seeing what is expected.

here is a link to the documentation on `includet`: [Revise usage: a cookbook · Revise.jl](https://timholy.github.io/Revise.jl/stable/cookbook/#includet-usage-1)

---

<div class="post-metadata">

**Author:** ![zeroexcuses](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/zeroexcuses/32/46846_2.png) [@zeroexcuses](https://discourse.julialang.org/u/zeroexcuses)\
**Post date:** [February 19, 2023, 8:21pm UTC](https://discourse.julialang.org/t/is-it-possible-to-use-revise-jl-to-reload-webserver-on-file-save/94866/13 "2023-02-19T20:21:43Z")

</div>

1. Good catch.

2. I tried it with:

```julia
// server.jl
using Revise
using HTTP

includet("inner.jl")

```

1. It still does not work.

2. Reading the docs you linked, I think the difference is this:

in the docs you linked, the included file returns (after defining the function)

in my case, the included file never returns – it starts a http server and waits

---

<div class="post-metadata">

**Author:** ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)\
**Post date:** [February 19, 2023, 8:33pm UTC](https://discourse.julialang.org/t/is-it-possible-to-use-revise-jl-to-reload-webserver-on-file-save/94866/14 "2023-02-19T20:33:27Z")

</div>

ok here’s work seems to work for me, remove this line from the file:

```julia
HTTP.serve(router_8080, "127.0.0.1", 8080)

```

in your REPL, do `using Revise, includet("./inner")`, and then manually run something like

```julia
a = @async HTTP.serve(router_8080, "127.0.0.1", 8080)

```

when you update the content of `inner.jl`, you want to run something in REPL, for example:

```julia
julia> a
Task (runnable) @0x00007fbad6977850

```

this will trigger Revise, and now refresh the website you should see the effect taking place

[https://global.discourse-cdn.com/julialang/original/3X/8/e/8ed859d64b020ecbd0bcc9b3528e8f1fd7bbee0d.mp4](https://global.discourse-cdn.com/julialang/original/3X/8/e/8ed859d64b020ecbd0bcc9b3528e8f1fd7bbee0d.mp4)

@quinnj really could use some documentation or quality of life for using HTTP.jl and Revise.jl together

---

<div class="post-metadata">

**Author:** ![zeroexcuses](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/zeroexcuses/32/46846_2.png) [@zeroexcuses](https://discourse.julialang.org/u/zeroexcuses)\
**Post date:** [February 19, 2023, 8:43pm UTC](https://discourse.julialang.org/t/is-it-possible-to-use-revise-jl-to-reload-webserver-on-file-save/94866/15 "2023-02-19T20:43:00Z")

</div>

1. Thanks, I can verify this works.

2. Can you explain why we have to retype ‘a’ in the REPL to trigger the revise/reload ?

I.e.

update inner.jl; reload Chrome; get old value  
update inner.jl; type “a” in REPL; reload Chrome; get new value

I’m wondering what magic is happening when we press “a”; because it’s clearly doing more than just looking up a value in a hashmap

---

<div class="post-metadata">

**Author:** ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)\
**Post date:** [February 19, 2023, 8:44pm UTC](https://discourse.julialang.org/t/is-it-possible-to-use-revise-jl-to-reload-webserver-on-file-save/94866/16 "2023-02-19T20:44:51Z")

</div>

> [@zeroexcuses](#):
>
> Can you explain why we have to retype ‘a’ in the REPL to trigger the revise/reload

Revise has 2 modes of operation, the default mode would identify changes and recompile stuff on demand when you actually run something, and the other mode ([polling](https://timholy.github.io/Revise.jl/stable/config/#Polling-and-NFS-mounted-code-directories:-JULIA_REVISE_POLL-1)) is usually not recommended unless you’re on a network mounted system where “file change” is not an observable of filesystem.

You could try polling but in that case you have a fixed latency so to speak, depends on how often Revise check for changes

---

<div class="post-metadata">

**Author:** ![stephenll](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stephenll/32/28751_2.png) [@stephenll](https://discourse.julialang.org/u/stephenll)\
**Post date:** [February 19, 2023, 8:48pm UTC](https://discourse.julialang.org/t/is-it-possible-to-use-revise-jl-to-reload-webserver-on-file-save/94866/17 "2023-02-19T20:48:33Z")

</div>

A different approach could be: set your response `Hello world` to a variable. Set up another route that loads the text from a file and assigns to that variable. This way, it isn’t always reading the text from a file, but there is a way to refresh the information.

---

<div class="post-metadata">

**Author:** ![ffevotte](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ffevotte/32/6587_2.png) [@ffevotte](https://discourse.julialang.org/u/ffevotte)\
**Post date:** [February 19, 2023, 9:21pm UTC](https://discourse.julialang.org/t/is-it-possible-to-use-revise-jl-to-reload-webserver-on-file-save/94866/18 "2023-02-19T21:21:44Z")

</div>

Here is a `Revise.entr`-based solution that should avoid the need to enter anything in the REPL to trigger `Revise` (it can actually run without a REPL at all)

```julia
using HTTP

const HOST = "127.0.0.1"
const PORT = 8080

function do_8080(_::HTTP.Request)
    local r = HTTP.Response(200, "Hello World 1");
    return r;
end

function start_server()
    server_task = @async try
        println("Server Started!")

        router_8080 = HTTP.Router();

        HTTP.register!(router_8080, "GET", "/", do_8080)
        HTTP.register!(router_8080, "GET", "**", do_8080)

        HTTP.serve(router_8080, "127.0.0.1", 8080)
    catch e
        e === :stop || rethrow()
    end
    errormonitor(server_task)
end

function stop_server(task)
    schedule(task, :stop, error=true)
    wait(task)
end

```

```julia
#outer.jl
using Revise
includet("inner.jl")

server_task = Ref(start_server())

entr(["inner.jl"], [], postpone=true) do
    stop_server(server_task[])
    server_task[] = start_server()
end

```

---

<div class="post-metadata">

**Author:** ![zeroexcuses](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/zeroexcuses/32/46846_2.png) [@zeroexcuses](https://discourse.julialang.org/u/zeroexcuses)\
**Post date:** [February 19, 2023, 10:04pm UTC](https://discourse.julialang.org/t/is-it-possible-to-use-revise-jl-to-reload-webserver-on-file-save/94866/19 "2023-02-19T22:04:53Z")

</div>

@ffevotte : Thanks. This is strictly superior to my old bash-script solution.

---

<div class="post-metadata">

**Author:** ![Marcell\_Havlik](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/marcell_havlik/32/37424_2.png) [@Marcell\_Havlik](https://discourse.julialang.org/u/Marcell_Havlik)\
**Post date:** [August 13, 2024, 9:36am UTC](https://discourse.julialang.org/t/is-it-possible-to-use-revise-jl-to-reload-webserver-on-file-save/94866/20 "2024-08-13T09:36:15Z")

</div>

Just noting for me this also worked and a little bit simpler:

```julia
using Revise

const ROUTER = HTTP.Router()

HTTP.serve!(ROUTER, "0.0.0.0", 8001)

entr(["APIEndpoints.jl"], [], postpone=true, pause=1.00) do
  include("APIEndpoints.jl")
end

```

But of course I get warnings like… but development gets like real time, so it worth the tradeoff:

```julia
┌ Warning: replacing existing registered route; GET => "/api/initialize" route with new path = "/api/initialize"
└ @ HTTP.Handlers ~/.julia/packages/HTTP/sJD5V/src/Handlers.jl:201

```

(I guess sooner or later there would be a flag to turn this off too in development)
