Ionic-cli: feature: Imperative way to notify ionic serve livereload to reload

Created on 24 Apr 2015  路  8Comments  路  Source: ionic-team/ionic-cli

I would like to notify livereload to reload after my build is completely finished as opposed to when having a directory watch notify livereload. Today, I can do this by just bypassing ionic serve and making my own gulp (or whatever) serve command.

Does it make sense to have a feature with some sort of event or messaging system whatever that may be where a build system (again, or whatever) can notify the ionic livereload server that a reload should happen.

This is in reponse to the issues I'm seeing in #387 and #114. I'm not even sure that this functionality should be in ionic-cli.

ionic1

Most helpful comment

At our company, we also have a complex gulpfile for chaining our assets and uglifying them, so our gulp task could never finish before the reload. After reading most of the solutions, I came up with this:

1) Install ShellJS plugin. Usually it comes with Ionic and is already loaded on your gulpfile, otherwise just do npm install shelljs@latest and require it on your gulpfile with var sh = require('shelljs');

2) Identify the last gulp task in your chain, and add it as a dependency to this new task

gulp.task('signalChanges',['last_task_in_chain'], function(done){
    sh.touch('./www/.changesLock');
    done();    
});

3) Change your ionic.config.json file to only listen for changes on this file:

"watchPatterns": [
    "www/.changesLock"
  ]

4) If you depend on the _default_ task, just add it to the end of the task:

gulp.task('default', ['sass','templatecache','replace_and_ng_annotate','useref','signalChanges']);

This way, what happens is the livereload only listens for changes on the www/.changesLock file (which doesn't have to include anything o be any specific type), which you fake by doing a bash touch() command via ShellJS. By putting it in a task, you can run the regular _watch_ gulp task but make your other tasks call this one when they are done and only then will the browser be reloaded.
If you're on a *nix environment or Mac, you could just require Node's _spawn_ command and execute a touch on your file with regular Bash inside your task, but using ShellJS keeps it portable.

Hopefully this helps, cheers!

All 8 comments

:+1:

@mikehaas763 I like the suggestion.

I think we could fit this in.

A little knowledge might help too. When Vinyl sees a change on the watching directories, it sends a POST request to the live reload server at the path /changed with a body of the files changed.

However, before this feature gets finished, one thing that could work right now is manually fire off a POST request to the live reload server to have it refresh.

For example, say when your build process is done, send a POST request:

http://localhost:35729/changed with the body being:
files: ['www/index.html']

That might help in the interim.

Was thinking of making a similar suggestion.

Idea would be to cache the changed files into a list and when given a command would flush the list and trigger a changed event in the server.
Probably while having the server running with 'ionic run android -l' or 'ionic serve' etc, so add something similar to the following to the server command list:

cache or c - start collecting changes instead of passing them to the server on the fly.
push or p / flush or f - empty the cache list to the server and trigger changed
clear or cl - just empty the cache and start sending changes in real-time once again.

Helps with live developing / debugging - where you'd like to keep temporary input data, keep the interactive log in the browser, data passed to views from previous ones or don't want the app to start on navigated to views.

+1

This or #581 would be extremely helpful. Currently I have 3 watches set up: sass, html, and js. If I modify more than one (thus triggering more than one watch), ionic will livereload as many times as I change files, which can get a bit disorienting.

The solution that seems to be working for me:

www/js/app.js as a single entry point, has a bunch of requires, i.e. var services = require('./services');
www/scss/app.scss as a single entry point, has a bunch of imports from bower and custom scss components, i.e. @import "../bower_components/ionic/scss/ionic";

index.html references to the built files <script src="build/app.js"></script> and <link href="build/app.css" rel="stylesheet">

1) When running the application with ionic serve edit the ionic.project file gulpStartupTasks to include gulp tasks that set everything up, that usually means something like running sass and browserify. These should build build/app.js and a build/app.css as output.

2) Add a watch task to gulpStartupTasks. that watches for any .js and .scss file changes and run sass and browserify. (Obviously edit paths, etc)

gulp.task('watch', function() {
  gulp.watch(['./www/scss/**/*.scss'], ['sass']);
  gulp.watch(['./www/js/**/*.js'], ['browserify']);
});

3) At this point when you run ionic serve it should make the app.css and app.js files in build/ and if you edit a js or scss file in www/ it should re-build the files. This runs quite quickly for me, but your results may vary.

Your ionic.project file might have this in it:

"gulpStartupTasks": [
    "sass",
    "browserify",
    "watch"
  ]

4) By default ionic tries to watch everything in the www/ for livereload directory, which isn't ideal because you end up with multiple reloads when you start adding things like template caching and constants being generated. Specify in the ionic.project file that we only want to live reload when the build files change like this:

  "watchPatterns": [
    "www/build/app.js",
    "www/build/ionic.app.css"
  ]

This seems to be fast enough on a medium sized project (browserify task takes ~600ms), but obviously your results may vary.

At our company, we also have a complex gulpfile for chaining our assets and uglifying them, so our gulp task could never finish before the reload. After reading most of the solutions, I came up with this:

1) Install ShellJS plugin. Usually it comes with Ionic and is already loaded on your gulpfile, otherwise just do npm install shelljs@latest and require it on your gulpfile with var sh = require('shelljs');

2) Identify the last gulp task in your chain, and add it as a dependency to this new task

gulp.task('signalChanges',['last_task_in_chain'], function(done){
    sh.touch('./www/.changesLock');
    done();    
});

3) Change your ionic.config.json file to only listen for changes on this file:

"watchPatterns": [
    "www/.changesLock"
  ]

4) If you depend on the _default_ task, just add it to the end of the task:

gulp.task('default', ['sass','templatecache','replace_and_ng_annotate','useref','signalChanges']);

This way, what happens is the livereload only listens for changes on the www/.changesLock file (which doesn't have to include anything o be any specific type), which you fake by doing a bash touch() command via ShellJS. By putting it in a task, you can run the regular _watch_ gulp task but make your other tasks call this one when they are done and only then will the browser be reloaded.
If you're on a *nix environment or Mac, you could just require Node's _spawn_ command and execute a touch on your file with regular Bash inside your task, but using ShellJS keeps it portable.

Hopefully this helps, cheers!

Adding to @nameofperson 's solution (which works great!), you might want to modify watchPatterns in your ionic.config.json to this:

"watchPatterns": [ "www/**/*.html", "www/.changesLock" ]

Just so it listens to changes to the template .html files as well (I didn't have any gulp task watching for changes to .html files)

Was this page helpful?
0 / 5 - 0 ratings