2.6.0
Features
This is a feature-packed release! We've crammed into this 2.6.0 release the usual
bug fixes & tweaks along with some entirely new APIs & workflow possibilities. It's a good one!
http-protocol
We've seen interest in allowing communication to the BrowserSync server from
separate processes to enable things like reloading browsers following a build script
(using npm as opposed to grunt, gulp etc). To enable this we've introduced a new
http protocol. Basically you'll be able to start BrowserSync
in one terminal window and then communicate to the process from another.
# run a server from any folder
browser-sync start --server
# from another window, tell all browsers to reload their css files
browser-sync reload --files "*.css"
This is really cool (and a bit magic) - but it gets even more interesting when
you consider that anything can hit the correct HTTP endpoint of a browser-sync server
and have the page reload. Think about how cool it would be having a Wordpress plugin that listens to
some post saved
event and then reloads all browsers/devices? No problemo...
/* PHP pseudo codez */
add_action( 'save_post', function() {
http_get("http://localhost:3000/__browser_sync__?method=reload");
});
Docs coming soon...
- http-protocol:
- commands: Add reload command for http-protocol comms (c0fe70dc)
More flexible .reload()
Normally, should you want to reload core.css
& styles.css
in the same page, you would do...
browserSync.reload(['core.css', 'styles.css']);
... which is fine - but sometimes you either don't know the exact filename referenced
in the DOM, or you would prefer not to hard-code the paths in your build scripts; either
way, you can now simply provide a wild-card and ALL assets with the same extension will be
reloaded.
/** refresh every CSS on page **/
browserSync.reload('*.css');
We've also added a global debounce option for reloading, as well as making reloadDelay
&& reloadDebounce
available from the cli
File Watching
We've now switched to chokidar for file watching (previously Gaze). This directly
addresses, amongst other things, one of the most commonly reported issues related
to watching file and directories - the ability (or previously the lack of) to watch
and report on new & incoming files.
We've also taken this opportunity to add a couple of extra ways to work with files in BrowserSync
User-defined watchers and callbacks
Usually, BrowserSync will just do the correct thing, if you give it this...
browserSync({
server: "app",
files: ["app/css/*.css", "app/*.html"]
})
... and then change a css
file, it will inject it into all browsers - or perform a
full reload when you change a html
file. That's great, but now that we've added
the ability to provide custom callbacks, it opens up a whole new range of things we can do.
Here's one example, where we provide the glob app/*.html
(which BrowserSync will handle as normal)
& also an object with match
& fn
properties. Any object such as this will be ignore
by BrowserSync internally and by all plugins, so for simple projects it's entirely possible that you
could ditch your build tools and create a workflow entirely around BrowserSync
var bs = require("browser-sync").create();
bs.init({
server: "./app",
files: [
"app/*.html",
{
match: "app/scss/*.scss",
fn: function (event, file) {
if (event === "change") {
processSass(file); // pseudo code, you get the point
bs.reload("*.css");
}
}
}
]
});
To top this off, we've added a public .watch()
method. Please note however, whilst this is
literally just pointing to internal watch method, it has no features relating to BrowserSync.
Use it as a stand-alone watcher and even interact with your BrowserSync Server if you like.
var bs = require("browser-sync").create();
var inject = bs.reload.bind(null, "*.css");
bs.watch("app/*.html").on("change", bs.reload); // hard reload
bs.watch("app/css/*.css").on("change", inject); // inject
bs.init({server: "./app"});
- file-watcher: Add
.watch()
to public api (6a2609f0) - watchers:
.stream()
Previously, when you could pipe a stream into .reload({stream: true})
- the filenames are
recorded and each connected browser will be informed that those files changed. This was obviously
a tacked-on feature and I have no idea why I didn't just create a separate method in the first
place - but anyway here it is:
var bs = require("browser-sync").create();
gulp.task('sass', function () {
return gulp.src('scss/**/*.scss')
.pipe(sass({sourcemap: true}))
.pipe(gulp.dest('css'))
.pipe(bs.stream());
Or, if you need to filter out source maps
so that browsers are only informed about
the files you want reloading (the css
files), you can now provide a glob pattern:
var bs = require("browser-sync").create();
gulp.task('sass', function () {
return gulp.src('scss/**/*.scss')
.pipe(sass({sourcemap: true}))
.pipe(gulp.dest('css'))
.pipe(bs.stream({match: "**/*.css"}));
- stream: Implement dedicated
.stream()
method for better handling streams & to pave the (2581e7a1)
CLI
You can now give the browser
option on the command line.
browser-sync start --server app/dist --browser firefox --browser safari
You can now open the UI directly when in snippet mode
browser-sync start --open "ui"
Plugins
We'll be announcing some amazing plugins soon, so watch out for that, but this change was to make it easier to register plugins so you can do things like this:
var bs = require("browser-sync").create();
bs.init({
server: "./app",
plugins: [
{
module: "bs-html-injector",
options: {
files: "./app/*.html"
}
}
]
});
Allowing plugins to be registered directly inline like this is a very important feature - it enables
the use of plugins in places you otherwise couldn't (for example, in the gruntfile.js configuration).
It's more verbose however, so if you do have access to the api, the same thing can be done with:
var bs = require("browser-sync");
bs.use(require("bs-html-injector"), {files: "./app/*.html"});
bs.init({server: "./app});
- plugins: Accept object literal as plugin + options (757f492e)
Bug Fixes
- server: set index correctly if serveStaticOptions: {index: } given (34816a76)