Code reloading in `lib/<appname>` no longer works with 1.7.0-rc.0

Using 1.7.0-rc.0 for some experiments and it quickly became obvious that while code reloading is working as usual in lib/<appname>_web and elsewhere in the app, it is not working in lib/<appname>. This is a vanilla/out of the box application. I added phx.gen.auth to have some more code to edit that really should cause a reload.

I have tried this with a couple different versions of Elixir and Erlang. I tried going back to 1.6 and confirmed it’s working fine there. Finally, I used a different laptop (tested MacOS 12.4 and 12.6) and the same thing was observed.

Anyone else seen this? Third-party confirmation would be appreciated as well!

Try mix deps.compile file_system

It fixed the issue with live reload, for me, after I updated both Mac and Phoenix.

Unfortunately this had no effect. On the second machine I tried this on there was no elixir (or really any devtools at all) beforehand. Completely clean install of erlang/elixir/phoenix 1.7 rc0

Worth clarifying, also, that I’m not talking about ‘live reload’, but just basic code reloading like editing the generated user.ex from phx.gen.auth. Changing the code does not cause the server to reload this code so it just keeps running the old version (e.g. add require Logger and Logger.error("TEST") to user.ex while the server is running, and you will not see the log (or at least, I don’t).

You might check the live reload patterns in config/dev.exs ans adjust them…

This post might be helpful.

Thanks but again that is for live reload, when I’m talking about just basic code reloading. As in the Phoenix server knowing that you edited an elixir file and using the new version. Nothing at all to do with browser reloading :frowning:

If anyone would like to try to reproduce:

mix archive.install hex phx_new 1.7.0-rc.0
mix phx.new testapp && cd testapp
mix phx.gen.auth Accounts User users
mix deps.get && mix ecto.create && mix ecto.migrate
mix phx.server

Go to register a user and put in only 4 chars for password, say. You get a validation error as expected. Now go to lib/testapp/accounts/user.ex and add to validate_email function or similar, something like:

require Logger
Logger.error("\n\n\n*******************\nTESTING\n*************\n\n\n")

Hit submit button again in browser. I do not see my new log. Change text of log, hit button again – still no log. Restart the server and try again, log appears! Edit the log message again, hit button again, log text does not change.

I can say I have the same problem :smiley:

Well that’s… ‘good’? :sweat_smile:
Thanks for confirming!

Can you clarify whether or not you are using LiveView based authentication system? When you run mix phx.gen.auth Accounts User users, you are given the prompt:

An authentication system can be created in two different ways:
- Using Phoenix.LiveView (default)
- Using Phoenix.Controller only
Do you want to create a LiveVIew based authentication system? [Yn]

I can only assume that you are using LiveView and if that’s the case, I think I know why your changes to your user.ex file aren’t being reflected. If you check endpoint.ex, you can see that plug Phoenix.CodeReloader is specified. So every request to your dev server goes through this plug and runs Phoenix.CodeReloader.reload(ExampleWeb.Endpoint) for you. If you were to make your logger change and reload the page, this ought to work and your change honoured.

Now, this doesn’t work with LiveView since they are process based. Once your LiveView connection is mounted (as in your LV has successfully mounted in both calls), all changes will be pushed to the LV, and won’t go through the Phoenix.CodeReloader. You would need to update something your web directory, or run recompile in your iex session.

I am not absolutely sure that this is the case, but give it a go without LV and see if you can replicate the issue you have.

Did you lodge a git issue, as I think this would be good to have fixed before final release.

I couldn’t see it here, but maybe its already closed.

Yea, this is an interesting point. It is a liveview auth system. However having worked with liveview before I’ve never had a code reloading problem like this. I’m going to try it with a non-live auth right now – uno momento.

Sadly an out-of-the-box non-liveview auth system seems to fail on the register page with no "new" html template defined for TestappWeb.UserRegistrationHTML (similar for the login page).

Anyway, simply the fact that you see stuff like:

Rebuilding...
Done in 48ms.

when editing in <appname>_web and not in <appname> seems like a problem to me.

@Rugged yea I had considered doing that right off the bat, but also I tend to assume it’s me doing something wrong by default :laughing: were you able to confirm this behaviour yourself by any chance?

I did manage to confirm that you are correct – reloading the page does cause the new logger (or whatever changes) to be reflected. If you edit something in _web it triggers live reload, but also just refreshing the page (which as you mentioned would spawn a new liveview process for the page) also works.

Is this really the intended behaviour? I swear this has never been an issue before in other liveview apps. Maybe I’m mistaken.

So for the sake of my experiments I’m just heavy-handed adding:

~r"lib/<appname>/.*?/.*"

to my live_reload config, kinda like @kokolegorille suggested originally. I hope this isn’t really the intended way to solve this situation though :expressionless:

Is this really the intended behaviour?

Well, I would imagine so. Reloading the browser simply works since it’s going through the set of plugs that handle this problem. However, I would imagine that the alternative of having your LV processes run the code reloader per message is probably worse. It would be possible to add a Plug like setup to your LV, but the overhead would be far from ideal. I personally don’t really deal with this problem specifically since I write the core code, have tests that run against that and then wire it up with LV.

Using recompile in an iex shell does give you more control when to recompile, but I can imagine that runs against the dev userflow for some people.

1 Like

I guess I’m expecting a code change to nuke and restart any liveview processes that have outdated code. I’ll have a look and experiment with older liveview apps and see what happens there, but yea my dev workflow is definitely a “poke at it in the browser while making changes across the entire codebase”, usually. It’s just hobby stuff.

I guess I’m expecting a code change to nuke and restart any liveview processes that have outdated code

I suspect that you might have had a more aggressive configuration for LiveReloader in this instance. LiveReloader would have picked up your core changes and propagated them to cause the “nuke” on your LV process. LV definitely does take it to the next level, but it also adds a new set of problems to be solved.

I confirm this behavior, I am very new at phoenix and would likely report the flaw poorly as I do not know elixir specific terminology. If/when you make the github issue, please link it so that we can follow.

Thank you in advance.

Just for good measure, I can confirm this as well!

Was surprised to not see behavior changes when editing a function in the <appname> portion of my project and remembered seeing this post!

Alright so as @beepbeepbopbop was suggesting, this is apparently just normal behaviour. I used Phoenix 1.6.15 to make a new app and did:

mix phx.gen.live Things Thing things title:string count:integer

Added routes as instructions say, started server, made a ‘Thing’. Then I added a validation in thing.ex, e.g. add:

    |> validate_number(:count, less_than: 10)

Made a new Thing, and it let me make it with count: 500. Refresh the page and now the validation applies. Same with adding loggers. Nothing happens until you refresh the page (or recompile() when using iex). I definitely just want this to happen automatically, so I suppose I have to do the live_reload config ugliness I mentioned earlier.

I worked on an app early on with liveview (that unfortunately I can’t get to work at all anymore) and I really find it hard to believe I never noticed or encountered this. I did not make any changes to the live_reload config in that other app, totally vanilla as far as that’s concerned…

But, anyway, seems clear this is just expected and not a bug at all, folks. Thanks for all your input!

1 Like