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

Manually triggering reload? #68

Closed
harshithkashyap opened this issue Jun 9, 2016 · 14 comments
Closed

Manually triggering reload? #68

harshithkashyap opened this issue Jun 9, 2016 · 14 comments
Assignees

Comments

@harshithkashyap
Copy link

harshithkashyap commented Jun 9, 2016

nodemon app takes a few seconds to restart the server but the live reload is triggered as soon as a file is changed. Is there a way to manually trigger the reload? I'm trying to use the nodemon restart event and manually trigger a reload(Not watching server files). Client files would be handled via args.

@napcs
Copy link
Owner

napcs commented Jun 17, 2016

I don't have any plans to implement something like this currently. Trying to wrap my mind around why you even need to do this. Can you give a lot more background info and be specific about what you'd like to have happen? What part of the API would need to change?

@harshithkashyap
Copy link
Author

harshithkashyap commented Jun 22, 2016

Sorry I wasn't clear before. Here's the folder structure i use for my node app.

config/routes
config/controllers
public/js
public/css
public/fonts
server.js
package.json
...

I'd go ahead and use this library as livereload public/ --port 35729. All HTML, CSS & client js files are reloaded without any problem.
If i try to watch over the server files aswell, livereload . --port 35729, before the server restarts, the livereload is triggered and the website crashes as the server is not running. So, if there is an api available from live-reload, i could explicitly trigger the reload after nodemon restarts the server. Say,

nodemon.on('restart', function() {
    setTimeout(function() {
            livereload.refresh();
    }, 3000);
});

I couldn't figure out how to modify the existing code but it seems the refresh method at https://github.com/napcs/node-livereload/blob/master/lib/livereload.js#L144 needs to be exposed.

@napcs
Copy link
Owner

napcs commented Jun 22, 2016

@harshithkashyap very helpful. Let me dig in.

@napcs napcs self-assigned this Jun 22, 2016
@napcs
Copy link
Owner

napcs commented Jul 17, 2016

@harshithkashyap Can you try v0.5.0 with the delay ( -w) option and see if it addresses your problem?

@harshithkashyap
Copy link
Author

@napcs Thank you for the new version. From the v0.5 i see two approaches to use the delay.

  1. Watch multiple directories and add delay for the same. This works but it waits for the delay even for client js, html & css files. Sometimes nodemon takes upto 15-20s for restart and hence this would be huge delay for client files.

  2. Run two livereload servers on two different ports. This approach seems to be the best one as i can immediately reload client files(no delay) and add delay to another script and watch over server files. The problem i'm facing here is that websocket connection in the browser is initiated only for the 1st script though GET requests to both livereload servers are fired.

    GET localhost:35729/livereload.js?snipver=1 & GET //localhost:35730/livereload.js?snipver=1

@napcs napcs closed this as completed Aug 3, 2016
@napcs
Copy link
Owner

napcs commented Aug 3, 2016

Reopen if this isn't a workable solution.

@raxod502
Copy link

I have the same problem. I have client-side files and server-side files. When I change client-side files, LiveReload can refresh my browser immediately. When I change server-side files, nodemon restarts my server, and only after the server has restarted can the browser be refreshed.

In my opinion, the right solution to this is for nodemon to start my server which starts a livereload server that only watches the client-side files. To get a refresh when server-side files are changed, it's a simple matter of telling livereload to trigger a refresh of the browser, after my server has started.

Unfortunately, there appears to be no way to do this. Using a hardcoded delay seems like a hacky workaround. It also won't work well because my server startup time might change due to network conditions.

I found #79 (comment), but it seems like what you said there would not be a problem for the setup I'm proposing. I'm not saying that livereload should reload on initial connection, but rather when I explicitly request it.

What am I missing here?

@raxod502
Copy link

As an addendum, I found that using touch public/some-file-that-livereload-watches.js as my code for "trigger a refresh of the browser" seems to make everything work perfectly. This contributes to my suspicion that LiveReload might be able to support this mode of operation without too much difficulty.

@napcs
Copy link
Owner

napcs commented Jun 25, 2017

The refresh method on the server is exposed. But you can't just call it because LiveReload needs to know what needs to be refreshed. And you probably don't know what it is either because any change to your code could bounce the server, and you might not know what path you're looking at in the browser. The protocol really is that if it's an html page, it reloads the whole page. If it's a css or js file, it reloads in the background. There's no message for "reload" without also specifying a path.

So you'll have to figure out the right solution for your app. I'd try to find something better than nodemon - it seems overkill to have to bounce the whole server every time you make a change to a file.

LiveReload literally just watches files that change. It'll watch any file extension you tell it to watch and it will send the appropriate refresh command. Just tell LiveReload.

I just ran a simple test of all this with a basic Express app:

$ npm install -g express-generator
$ express testapp --view=pug
$ cd testapp
$ npm install
$ npm start

Then in a new window, I started the LiveReload CLI to watch .pug files (the views) in addition to html, css, etc.

$ livereload . -e "pug" -d

The output shows it's watching:

LiveReload is waiting for browser to connect.

Protocol version: 7
Exclusions: /\.git\//,/\.svn\//,/\.hg\//
Extensions: pug,html,css,js,png,gif,jpg,php,php5,py,rb,erb,coffee
Polling: false


Starting LiveReload v0.6.2 for /Users/brianhogan/tmp/testapp on port 35729.
Watching /Users/brianhogan/tmp/testapp...

Browser connected.

Client message: {"command":"hello","protocols":["http://livereload.com/protocols/official-6","http://livereload.com/protocols/official-7"],"ver":"2.2.2","ext":"Chrome","extver":"2.1.0"}

Client requested handshake...

Handshaking with client using protocol 7...

Client message: {"command":"info","plugins":{"less":{"disable":false,"version":"1.0"}},"url":"http://localhost:3000/"}

So then I make an edit to views/index.pug and save the file.

And LiveReload sees it:

Reloading: /Users/brianhogan/tmp/testapp/views/index.pug

Client closed connection

Browser connected.

Client message: {"command":"hello","protocols":["http://livereload.com/protocols/official-6","http://livereload.com/protocols/official-7"],"ver":"2.2.2","ext":"Chrome","extver":"2.1.0"}

Client requested handshake...

Handshaking with client using protocol 7...

Client message: {"command":"info","plugins":{"less":{"disable":false,"version":"1.0"}},"url":"http://localhost:3000/"}

Of course, it reloaded the page, which disconnected the browser, which then reconnected. So this is working as expected. But the page in the browser immediately reflected the changes.

So the Express app lets me change the pug views without bouncing the server.

Next I went and changed something in the routes that affects the views. I changed:

router.get('/', function(req, res, next) {
  res.render('index', { title: 'Express' });
});

to

router.get('/', function(req, res, next) {
  res.render('index', { title: 'The Awesomeness' });
});

Saved, and of course, LiveReload noticed there was a file change, but didn't update the HTML, cos it's a server-side JS file. :) Also, of course the server needed a bounce to make the change take effect.

So I restarted the server. And, as expected, the change didn't take effect on the web page. But a manual refresh fixed everything right up. So did a change to a pug file.

I''m thinking you could probably do this as the safest workaround if you can't / won't move off of Nodemon:

// livereload setup

const liveReload = require('../lib/livereload');
const liveReloadServer = liveReload.createServer({
  port: 35729,
  debug: true,
  exts: ['pug']
});

liveReloadServer.watch(__dirname);

// some other setup

nodemon.on('restart', function() {
    setTimeout(function() {
      liveReloadServer.refresh('path/to/the/css/file/for/your/app');
    }, 3000);
});

and it would work ok.

@raxod502
Copy link

raxod502 commented Jun 26, 2017

Thanks, the suggestion about using LiveReload to update Pug files without restarting the server is really cool. However, I really do want restarting the server to cause a refresh in the browser. From my understanding, the problem appears to be that LiveReload can't directly tell the client to refresh, it can only tell the client which file was updated. This seems like a shortcoming in the protocol to me, but I guess it can't be fixed here.

That said, an Express server using Pug is not serving static assets. So there's really no way for the client to draw a link between the Pug file that was updated, and the current page that's being viewed. I can only assume that whenever the client gets a message about any Pug file being updated, it refreshes. So in essence, LiveReload does have a way of forcing the client to refresh.

Would it make sense for LiveReload to expose a method to explicitly perform this functionality? Are there complications that make it more difficult to implement than I am thinking? (After all, touching a JavaScript file that I know is used on all pages in my application does appear to work, but it's difficult to get a hack like that past code review :P)

@napcs
Copy link
Owner

napcs commented Jun 26, 2017

The reason Pug stuff works is the default behavior refreshes the existing page. But the method on the client that requires that requires a path and some options.

I have to maintain compatibility with the CLI, the official browser plugin, and the browser extension. And I can't change the code for the client-side pieces. You can certainly hack it, but there's no guarantee it won't change later.

Try

nodemon.on('restart', function() {
    setTimeout(function() {
      liveReloadServer.refresh('');
    }, 3000);
});

And see if that works. If it does, let me know.

@raxod502
Copy link

Firstly, I'm sorry for the delay in my response (this is a work project). Secondly, your suggestion works perfectly. In my case, I would actually not use a timeout, and instead call liveReloadServer.refresh in my server code, after everything was booted up. I guess this would require me to either roll my own Nodemon, or do some kind of inter-process communication.

I think it's a shortcoming in the LiveReload client protocol that there's no way to just tell the client to refresh the page, but it does indeed appear that sending an empty string for the path is a valid workaround, at least for some client implementations.

Thanks for your help. This is a really helpful tool.

@napcs
Copy link
Owner

napcs commented Jul 24, 2017

Great to hear it works. I might go implement a reload page method on the server myself to abstract the empty string away. Then if it changes, nobody's code breaks.

@ijpatricio
Copy link

hey all

liveReloadServer.refresh("/")

might work better!

found solution to my case here https://bytearcher.com/articles/refresh-changes-browser-express-livereload-nodemon/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants