shama / webpack-stream

:tropical_drink: Run webpack through a stream interface
MIT License
1.4k stars 122 forks source link

BrowserSync not starting when watch: true #119

Open ivancuric opened 8 years ago

ivancuric commented 8 years ago

If I have watch: true enabled in the webpack config, BrowserSync won't start for some reason. Note, I don't have watching enabled in gulp.

JS task:

gulp.task('js', () => {
  return gulp.src('')
    .pipe(plumber())
    .pipe(webpack(webpackConfig))
    .on('error', notify.onError({
      message: (error) => {
        return error.message;
      }
    }))
    .pipe(sourcemaps.init({loadMaps: true}))
    .pipe(through.obj(function (file, enc, cb) {
      var isSourceMap = /\.map$/.test(file.path);
      if (!isSourceMap) this.push(file);
      cb();
    }))
    .pipe(gulp.dest('valamar/static/js/dist/'))
    .on('end', reload);
});

Default gulp task:

gulp.task('default', ['sass', 'js'], () => {
  browserSync.init({
    proxy: 'localhost:8000',
    ghostMode: false,
    notify: false,
    open: false,
    ui: false

Webpack config:

  watch: true,
  devtool: 'source-map',
  resolve: {
    modulesDirectories: ['node_modules', dir_js]
  },
  entry: {
    vendor: ['jquery'],
    app: path.resolve(dir_js, 'app/app.js'),
    admin: path.resolve(dir_js, 'admin/admin.js')
  },
  output: {
    path: dir_build,
    filename: '[name].js'
  },
  module: {
    loaders: [{
      test: /\.js$/,
      exclude: /(node_modules|vendor)/,
      loader: 'babel-loader'
    }]
  },
  plugins: [
    // new webpack.optimize.DedupePlugin(),
    new webpack.optimize.CommonsChunkPlugin('vendor', 'vendor.js')
  ]
ivancuric commented 8 years ago

Nevermind, it was a sync task. Removing js as a dependency task (which was always running) fixed it. Replaced it with gulp.start('js')

However, now .on('end', reload) serves no purpose, since it will never trigger. If I enable gulp.watch(src.js).on('change', browserSync.reload) it will run in async and reload the page before webpack is finished compiling.

Can webpack when using watch: true somehow signal to gulp that it's done and trigger a reload?

zaqqaz commented 8 years ago

Just, add handler, and trigger brwser sync from them. Something like that:

....

let webpackChangeHandler = function (err, stats) {
        $.util.log(stats.toString({
            colors: $.util.colors.supportsColor,
            chunks: false,
            hash: false,
            version: false
        }));

        browserSync.reload();

        firstBuildReady = true;
    };

....

    return  gulp.src('')
        .pipe(plumber({errorHandler: conf.errorHandler('webpack-stream')}))
        .pipe(webpackStream(webpackOptions, null, webpackChangeHandler))
        .pipe(gulp.dest('valamar/static/js/dist/'))
        .on('data', () => {
            if (firstBuildReady && callback) callback()
        });
ivancuric commented 8 years ago

Not sure if I follow to be honest. :\ I guess I'll just add a watch to the dist folder as well.

corinadev commented 8 years ago

@ivancuric

Can webpack when using watch: true somehow signal to gulp that it's done and trigger a reload?

When using webpack-stream that is possible by passing a callback as the 3rd parameter, as in @zaqqaz's example above:


.pipe(webpackStream(webpackOptions, null, webpackChangeHandler))

That function will be called when the compilation is done, so you can call BrowserSync.reload() there to get the updated code.

dsifford commented 8 years ago

@zaqqaz A complete example would be lovely.

simboonlong commented 4 years ago

When using watch:true in webpack, you probably want to run it as a parallel gulp task.

webpack.config.js:

module.exports = {
  ...
  watch: true,
  ...
}

gulpfile.js:

gulp.task('js', (done) => {
  return gulp.src([
    ...
  ])
    .pipe(webpackStream(webpackConfig, null, (err, stats) => {
      browserSync.reload()
      done()
    }))
    .pipe(gulp.dest(...))
})

gulp.task('default', gulp.parallel(['sass', 'js']))

Pass done callback from gulp task js, trigger browsersync reload, then call done in webpack stream handler to exit the gulp task properly.

Use gulp.parallel, so now webpack watch is a task on its own, independent from other gulp tasks you have in your pipeline.

Hope it helps.