BrowserSync / gulp-browser-sync

How to use the Browsersync module with gulp.
http://browsersync.io
384 stars 30 forks source link

Gulp + proxy = no injection #26

Open jessewallace opened 9 years ago

jessewallace commented 9 years ago

Hey all,

I have my Gulp task properly preprocessing my files, but it's not injecting the CSS. It's actually firing a full page reload.

Some background:

I'm using gulp-sass 0.7.2 and browser-sync 1.3.5

var gulp        = require('gulp'),
    browserSync = require('browser-sync'),
    reload      = browserSync.reload,
    sass = require('gulp-sass'),
    path = require('path'),
    minifyCSS = require('gulp-minify-css'),
    autoprefixer = require('gulp-autoprefixer'),
    rename = require("gulp-rename");
    filter = require("gulp-filter");

var config = {
    files: "web-app/css/**/*.scss",
    proxy: "localhost:80"
}

// browser-sync task for starting the server.
gulp.task('browser-sync', function() {
    browserSync(config)
});

// Sass task, will run when any SCSS files change & BrowserSync
// will auto-update browsers

gulp.task('sass', function () {
    return gulp.src('web-app/css/**/*.scss')
    .pipe(sass())
    .pipe(autoprefixer('last 2 version'))
    .pipe(minifyCSS({keepSpecialComments:0}))
    .pipe(rename({suffix: '.min'}))
    .pipe(gulp.dest('web-app/css/'))
    .pipe(filter('web-app/css/**/*.css'))
    .pipe(reload({stream:true}));
});

// Default task to be run with `gulp`
gulp.task('default', ['sass','browser-sync'], function () {
    gulp.watch("web-app/css/**/*.scss", ['sass']);
});

Thanks for any help on this, guys. I'm a UI/UX guy by trade, and this is pretty outside of my realm of comfort :)

shakyShane commented 9 years ago

So it does a full page reload every time your sass task runs?

sogko commented 9 years ago

Hi @jessewallace

May I suggest a change in how the gulpfile.js is written?

var gulp        = require('gulp'),
    browserSync = require('browser-sync'),
    reload      = browserSync.reload,
    sass = require('gulp-sass'),
    path = require('path'),
    minifyCSS = require('gulp-minify-css'),
    autoprefixer = require('gulp-autoprefixer'),
    rename = require("gulp-rename");
    filter = require("gulp-filter");

var config = {
    // 1. inform browser-sync to watch compiled *.css files instead of *.scss sass files
    files: "web-app/css/**/*.css",
    proxy: "localhost:80"
}

// browser-sync task for starting the server.
gulp.task('browser-sync', function() {
    browserSync(config)
});

// Sass task, will run when any SCSS files change & BrowserSync
// will auto-update browsers

gulp.task('sass', function () {
    return gulp.src('web-app/css/**/*.scss')
    .pipe(sass())
    .pipe(autoprefixer('last 2 version'))
    .pipe(minifyCSS({keepSpecialComments:0}))
    .pipe(rename({suffix: '.min'}))
    .pipe(gulp.dest('web-app/css/'));

     // 2. you don't need these anymore, since browser-sync will be 
    // triggered once the sass compilation task writes to web-app/css/ folder
    // .pipe(filter('web-app/css/**/*.css'))
    // .pipe(reload({stream:true}));
});

// Default task to be run with `gulp`
gulp.task('default', ['sass','browser-sync'], function () {
    gulp.watch("web-app/css/**/*.scss", ['sass']);
});

Details: We inform browser-sync to watch for changes in *.css files, instead of *.scss files.

We then can remove the instruction to tell browser-sync to reload upon completion of the sass tasks. Your sass task will eventually write the compiled *.css files and browser sync can pick it off from there.

So the new build flow would go something like this:

  1. Edit one of the *.scss files
  2. sass task recompiles all *.scss in your folder (Note: this can be improved further by only compiling changed *.scss files)
  3. Upon completion, the sass task updates your *.css files
  4. browser-sync sees that *.css has changed, tries to inject it to connected browsers.

Drawback: depending on how your pipe was written, it might take a while for your sass task to complete, thus you'd only see the injected changes after it completes.

Give this a try and let us know if it still do a full page reload.

@shakyShane: What is the actual behaviour if the whole watched folder changed at the same time? Would it still inject or would it do a page reload? I'm expecting it to be able to do an injection, I'm not sure.

jessewallace commented 9 years ago

@shakyShane - yes, it WAS doing a full reload. @sogko - I reverted to your solution to try, and didn't get a reload of any sort, injection or full page.

However, this is my code now:

var gulp        = require('gulp'),
    browserSync = require('browser-sync'),
    reload      = browserSync.reload,
    sass = require('gulp-sass'),
    path = require('path'),
    minifyCSS = require('gulp-minify-css'),
    autoprefixer = require('gulp-autoprefixer'),
    rename = require("gulp-rename");

var config = {
    proxy: "ggdev.elasticbeanstalk.com"
}

// browser-sync task for starting the server.
gulp.task('browser-sync', function() {
    browserSync(config)
});

// Sass task, will run when any SCSS files change & BrowserSync
// will auto-update browsers

gulp.task('sass', function () {
    return gulp.src('web-app/css/**/*.scss')
    .pipe(sass())
    .pipe(autoprefixer('last 2 version'))
    .pipe(minifyCSS({keepSpecialComments:0}))
    .pipe(rename({suffix: '.min'}))
    .pipe(gulp.dest('web-app/css/'))
    .pipe(reload({stream:true}));
});

// Default task to be run with `gulp`
gulp.task('default', ['sass','browser-sync'], function () {
    gulp.watch("web-app/css/**/*.scss", ['sass']);
});

I got rid of the files option and the gulp-filter, and now it injects...but only after two saves. The first save doesnt pick it up...almost like its firing the injection before the css can compile.

Any thoughts? Thanks again for you guys help on this!

sogko commented 9 years ago

@jessewallace Hmm, there might be something else at play here, because I managed to get it working using the sample gulp recipe I gave you.

Here's a repo with something that I think is close to your project with a working gulp recipe: https://github.com/sogko/browser-sync-issue-26

Try to run the project + gulp and see if it works for you.

Try editing web-app/css/test.scss and see that the changes are injected to the page.

sogko commented 9 years ago

@jessewallace oh btw, is it possible to show the logs from the terminal when you run gulp and when you try to edit a scss file.

Something like this:

[09:26:09] Using gulpfile ~/dev/browser-sync-issue-26/gulpfile.js
[09:26:09] Starting 'sass'...
[09:26:09] Starting 'browser-sync'...
[09:26:09] Finished 'browser-sync' after 5.92 ms
[BS] Proxying: http://localhost:3000
[BS] Now you can access your site through the following addresses:
[BS] Local: >>> http://localhost:3001
[BS] External: >>> http://192.168.1.1:3001

[09:26:09] Finished 'sass' after 104 ms
[09:26:09] Starting 'default'...
[09:26:09] Finished 'default' after 9.67 ms
[09:26:21] Starting 'sass'...
[09:26:21] Finished 'sass' after 25 ms
[BS] File Changed: test.min.css
[BS] Injecting file into all connected browsers...
[09:26:31] Starting 'sass'...
[09:26:31] Finished 'sass' after 23 ms
[BS] File Changed: test.min.css
[BS] Injecting file into all connected browsers...
[09:26:33] Starting 'sass'...
[09:26:33] Finished 'sass' after 25 ms
[BS] File Changed: test.min.css
[BS] Injecting file into all connected browsers...
shakyShane commented 9 years ago

@jessewallace - is this still an issue for you?

shakyShane commented 9 years ago

@onaliugo - Try this

gulp.task('_serve', function(){
  return browserSync.init(null, {
    proxy: "http://app.xxx.dev/",
    startPath: "/index_dev.php",
    files: "sass/*.css"
  });
});

gulp.task('_sass', function() {
  return gulp.src('sass/main.scss')
    .pipe(sass())
    .pipe(gulp.dest('sass/'));
});

gulp.task('_watch', function(){
  gulp.watch('sass/**', ['_sass']);
});

gulp.task('_test', [
  '_sass',
  '_serve',
  '_watch'
]);
ugogo commented 9 years ago

@shakyShane Thanks for your answer, but it didn't reload the browser or inject CSS.

However, doing this worked !

gulp.task('_serve', function(){
  return browserSync.init("sass/**", {
    proxy: "http://app.wisembly.dev/",
    startPath: "/index_dev.php"
  });
});
akwangho commented 9 years ago

Thanks, @onaliugo It works for me.

maxmx commented 9 years ago

Not getting injection either, tried all options on this page.

proxying on localhost:8080

malfborger commented 9 years ago

@sogko i'm using your config bu im only recieving following in ther terminal ➜ wp git:(master) ✗ gulp default [11:11:28] Using gulpfile ~/Sites/garbergs.se/wp/gulpfile.js [11:11:28] Starting 'sass'... [11:11:28] Starting 'browser-sync'... [11:11:28] Finished 'browser-sync' after 22 ms [BS] Proxying: http://localhost:9001 [BS] Now you can access your site through the following addresses: [BS] Local URL: http://localhost:3000 [BS] External URL: http://10.15.2.155:3000 [BS] Watching files... [11:11:28] Finished 'sass' after 480 ms [11:11:28] Starting 'default'... [11:11:28] Finished 'default' after 17 ms [BS] File changed: wp-content/themes/garbergs-theme/styles/component.css

it doesn't say " [BS] Injecting file into all connected browsers... "

ocombe commented 9 years ago

So I had the same problem: browser sync was doing a full reload because the sourcemap files changed at the same time as the css files. I filtered the *.map files and it injects the css without full reload now.

makbeta commented 8 years ago

Having the same issue. Found out that the loaded page, browsersync automatically insert the following JS code

<script type='text/javascript' id="__bs_script__">//<![CDATA[ document.write("<script async src='/browser-sync/browser-sync-client.2.8.2.js'><\/script>".replace("HOST", location.hostname)); //]]></script>

For me this snippet fails because my html also has tag in it, so it attempts to load the js file from the external, rather than local server.

I believe the auto-generated snippet should be updated to the following for it to work correctly across all configurations.

<script type='text/javascript' id="__bs_script__">//<![CDATA[ document.write("<script async src='//HOST/browser-sync/browser-sync-client.2.8.2.js'><\/script>".replace("HOST", location.hostname)); //]]></script>

I believe this may be the same issue https://github.com/BrowserSync/browser-sync/issues/453

tatemz commented 8 years ago

Per @ocombe - My problem was also an issue with *.map files being included in the pipe.

hkirsman commented 8 years ago

Can't get this working. Tried all the different code examples. Best I get is page reload.

hkirsman commented 8 years ago

Oh well it seems that BrowserSync does not support @import and that's what Drupal is using if aggregation is not enabled. Here's the issue and fix: https://github.com/BrowserSync/browser-sync/issues/534

zirho commented 8 years ago

anyone who struggle with map file injection causing full reload try something like this

gulp
.src('./public/css/*.css')
.pipe(browserSync.stream({match: '**/*.css'}));

this injects only css file to it so no full refresh with this

martinesdevelop commented 7 years ago

zirho, thanks! It helps me!

mrsimonemms commented 7 years ago

I've had a similar problem, although the cause is (perhaps) different. I'm putting this here as this is the top link when I search for "browsersync not injecting css" in the hope it's helpful to others.

My gulpfile is using the connect-modrewrite to rewrite links - it ensures that all URLs are routed through the index.html file (important for Angular). It appears that, when injecting the compiled CSS in, it's routing the CSS through the index.html file. The browser doesn't do this, so it's not immediately apparent there's a problem. See task below:

var modRewrite = require("connect-modrewrite");
gulp.task("default", ["clean", "bundle", "templates:watch", "sass"], function () {

    browserSync.init({
        open: false,
        server: {
            baseDir: "./src",
            middleware: [
                modRewrite([
                    "^\/assets/(.*) /assets/$1 [L]",
                    "!\\.\\w+$ /index.html [L]"
                ])
            ]
        }
    });

    gulp.watch(src.sass, ["sass"]);
    gulp.watch(src.html, ["templates:watch"])
        .on("change", reload);

});

By adding "^\/assets/(.*) /assets/$1 [L]", to the modRewrite array, it ensures my compiled CSS is injected correctly.

jobayerarman commented 7 years ago

Adding

.on("change", reload) 

fixed my issus.

gulp.task( 'watch', ['browser-sync'], function() {
  gulp.watch( watch.styles, [ 'styles' ] );
  gulp.watch( watch.html, [ 'render-html' ] ).on("change", reload );
  gulp.watch( watch.scripts, [ 'scripts' ] ).on("change", reload );
});
alexcracea commented 7 years ago

I've done all things I could ever find and for me it still doesn't work:

I getting new tab opened with a pop-up saying "Connected to browsersync" but still on any style change I don't get any reload or anything.

Vagelis-Prokopiou commented 7 years ago

@Onotoley for a Drupal setup you can find a lot of info here Switch current omega sub-theme to LibSass. No need for any Drupal module. I have provided step to step instruction on comment 20. Plus a lot of info by other guys.

demisx commented 7 years ago

Same here. No longer works, though the browser shows "Injected" message. Have to hit reload each time to see the changes. Using the latest BS 2.18.8.

Had to update my gulp task to do the hard reload instead of bs.stream():

gulp.src('dotnet/core/website/Mvc/**/*.scss')
  .pipe(sourcemaps.init())
  .pipe(sass())
  .pipe(sourcemaps.write())
  .pipe(gulp.dest('build'))
  .on('end', () => {
      bs.reload();
   })