Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement a live reload server #2

Open
nicoabie opened this issue Feb 18, 2019 · 22 comments
Open

Implement a live reload server #2

nicoabie opened this issue Feb 18, 2019 · 22 comments
Labels
enhancement New feature or request help wanted Extra attention is needed question Further information is requested

Comments

@nicoabie
Copy link

As I was playing with the code I found myself querying make. upon save and the going to the browser to press F5 to reload.

I think it would be very cool if we can automate this process. I've already started playing with inotify and reading about websockets in prolog.

The idea is fairly simple and can be split in tasks (each one with an approximate complexity given my beginner skills):

  1. Inject some JS to the page that will call the server to open a websocket. (medium)
  2. detect some file has changed (easy)
  3. find a way to query make. Needs investigation but I've read of hot reload from another thread. (hard)
  4. send a message to the page via websocket that calls document.location.reload(). (easy)

Thoughts?

@nicoabie nicoabie added enhancement New feature or request help wanted Extra attention is needed question Further information is requested labels Feb 18, 2019
@kinow
Copy link
Member

kinow commented Feb 18, 2019

I use that with Vue.js, npm run serve combined with the Vue browser extension uses a websocket to refresh the browser. I believe they also use something similar in node (maybe this inotify?) to refresh the app every time I change something in the vue code.

+1 super useful

@nicoabie
Copy link
Author

Yes @kinow, the vue cli is using some npm package like livereload to do that.

The thing is that that needs a nodejs server to work, my intent is to have a prolog version of that if possible without the need of nodejs.

@kinow
Copy link
Member

kinow commented Feb 18, 2019

Yup, that's what I understood too. Only used "this inotify" to show another module with same name, though in different language. Sorry the confusion!

@Anniepoo
Copy link
Contributor

be simpler to write a bit of js that makes a pengine that calls make, add a button to page to fire it and reload on success.

@Anniepoo
Copy link
Contributor

or just poll and watch on the server for change

@nicoabie
Copy link
Author

@Anniepoo I don't want to sound utopic but ideally the page will refresh automagically when saving a file.
If a button could be added to do so it is also possible to write a bit of js that makes a pengine throught a websocket, that pengine will start listening to the files with inotify then upon save will call make and send a reload event back to the browser through the socket.

I just need some help with the part that creates the pengine and calls make. Can you provide any example?

@ninjarobot
Copy link

It would be quite nice if we could move towards using webpack with it's dev server and Hot Module Reload, designed for just this use case. To really make this work, however, I believe we would need to write out the JavaScript and serve it, rather than generating it on demand within Pengines. Would be something like this:

  1. Edit .pl source that builds the JS module that the UI consumes
  2. On save of .pl, regenerate the JS module
  3. The webpack Hot Module Reload (HMR) triggers the browser to reload that module automatically.

However, the current flow is always generating the JS on demand, so we might need to come up with a way to build it at development time.

@nicoabie
Copy link
Author

I do not agree at all @ninjarobot
Using webpack just because of its hot module reload plugin is an overkill.
Furthermore we would have to add nodejs to the stack.

Also take into account that when a .pl is saved it doesn't necessarily implies that a js should be rebuilt.
For example when playing with the html DCG in todo_page.pl

@ninjarobot
Copy link

That's not really the only reason to use webpack, it brings a lot of other benefits. True, you're going to end up with nodejs and deeper integration into the JS ecosystem, babel, etc, I'm not so sure that's really a bad thing, though (I'm not the first person in this thread to mention npm). Right now, the ownership is entirely on the programmer to ensure they are including all the appropriate modules in the correct order (pretty easy since it's only vue and jquery), but the complexity grows quickly once past a couple script tags.

I understand every .pl doesn't result in a new .js, however some .pl change does, and with some opinionated project structure, HMR is a mature solution for this common problem. Did you have something else in mind? Manually building this same sort of thing?

@nicoabie
Copy link
Author

Yes and I have specified the steps needed in the description of the thread.
I have worked for many years as web developer and I know all the babel + webpack + js ecosystem. But I believe that for this project is an overkill. We don't have a single js file for now and it is on the roadmap the posibility of compiling prolog to js so I honestly don't think it is the way to go.

@ninjarobot you are free to explore the webpack option and come back to tell us how it went.

@Anniepoo
Copy link
Contributor

I'll provide an example for the pengine call. I agree, the file observation solution is better.
An alternative is to hook make (there's a hook) and when the dev runs make we reload the page.
There's already www_open_url/1, so we just need to add a way to pass additional arguments to the shell command. We could just shell out, but I think it's better to add that and make www_open_url/2.
This totally elminates doing anything on client side.
Forcing make on save might disrupt some folks' workflow.
I'm of two minds regarding webpack. I certainly wouldn't import it just to get the auto reload. One of
the delights of working in SWI-Prolog is that dependencies are kept to a minimum. This can seem counterproductive at that moment, but in the long run, it really, really cuts down on the amount of sysadmin-y setup one does.
On the other hand, I don't want SWI-Prolog to turn into common lisp, where it's only relevant to some neckbeards. We're a modern language, and do things in modern ways.

@Anniepoo
Copy link
Contributor

Right now, the ownership is entirely on the programmer to ensure they are including all the appropriate modules in the correct order (pretty easy since it's only vue and jquery), but the complexity grows quickly once past a couple script tags.

SWI-Prolog resource system takes care of this.
http://www.pathwayslms.com/swipltuts/html/index.html#_including_resources_with_code_html_resource_code

@Anniepoo
Copy link
Contributor

I've thought up a way to do this with no change to code, just by loading a lib. Involves a bit of deep chicken waving, but can be done. I'll try to find some cycles this evening to promulgate a pack for it.

@Anniepoo
Copy link
Contributor

I should also say, reading the original issue - C-c C-m in the editor makes, and will give save dialogs for each file. I personally do C-c C-s C-c C-m to make, which avoids the dialog.

@Anniepoo
Copy link
Contributor

One thing I should say here - Prolog lives in it's own ecosystem, and that's been amazingly effective at futureproofing it. I would guess some descendent of SWI-Prolog will be here long after nodejs is gone.
yeah, I think enrolling NodeJS into the required stack is a non-starter. It comes up occasionally.

@Anniepoo
Copy link
Contributor

www_open_uri/1 will open a web page in a new tab.
Extending it to allow arguments is fairly trivial. But I'm having the devil's time figuring out how to open a web page in an existing tab.

@ninjarobot
Copy link

That's fine, I understand the perspective. There are existing processes and tooling that will just have to be reinvented, in this case it's just reloading a page (or part of it) when code changes server side, and then the necessary work to pull that code out when publishing a production application. Not an insurmountable task, for sure.

@Anniepoo
Copy link
Contributor

After a bit more research, it looks like yes, inotifywait and either a websocket or a never-ending pengine call.
The bit of deep juju I was thinking was to grab the last uri requested and try to call the browser on the server side via shell - essentially what www_open_uri/1 does.
But it makes as much sense to just keep a websocket open.
@nicoabie if you're working on this I'll hold off - I have lots of irons in the fire.

@Anniepoo
Copy link
Contributor

A nice client side hook might be to not reload the page but just call a js function.
Another nice hook might be to try to grab some state before the reload (eg contents of all input tags)

@Anniepoo
Copy link
Contributor

@nicoabie - check out the websocket package.
Might be even simpler to just use hub.pl

https://github.com/anniepoo/whiteboard

hub.pl got integrated into SWI-Prolog after that was written.

@nicoabie
Copy link
Author

nicoabie commented Feb 19, 2019

@Anniepoo I think I got lost a little bit in your train of thought.

I'll take a look into the websocket package, sure.

Regarding not reloading and just calling a js function what will the use case? Or you just mean to have it decoupled to call any function, one being () => document.location.reload()

The hook about grabbing the state before reload to have it applied after reloading (which I believe is the use case) I think it is a great idea and we can create another story for it.

I will then check alternatives on how to do it :)

@Anniepoo
Copy link
Contributor

yes, I meant decouple it so you can put in some custom behavior instead of just reloading the document.

my train of thought is a Brio train.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request help wanted Extra attention is needed question Further information is requested
Projects
None yet
Development

No branches or pull requests

4 participants