Search code examples
node.jsgulpbrowser-syncgulp-sass

How to inject css into browserSync using gulp 4 with predefined tasks?


I am writing an automation tool for myself, which has similar concept to laravel mix. I have a tiny problem that I can't crack when injecting sass into browsersync using Gulp 4. The following exports brosersync task:

const argv = require('yargs').argv
const path = require('path')
const {watch, series} = require('gulp')
const webpack = require('webpack')
const bundler = webpack(webpackConfig)
const webpackDevMiddleware = require('webpack-dev-middleware')
const webpackHotMiddleware = require('webpack-hot-middleware')
const Sass = require('./sass')

class BS {
    constructor() {
        this.watchPaths = [`${process.cwd()}/tailwind.config.js`]
        this.setupWatchPaths()
    }

    config() {
        let middleware = [
            webpackDevMiddleware(bundler, {
                publicPath: webpackConfig.output.publicPath,
            }),
        ]

        if (argv.hot) {
            middleware.push(webpackHotMiddleware(bundler))
        }
        return {
            ...dev.bs,
            middleware,
        }
    }

    tasks(stream = false) {
        const tasks = []
        for (const conf of dev.sassConfigs) {
            const sassTask = new Sass(conf.src.segments.absolutePath, conf.dest.segments.absolutePath, conf.opts)
            tasks.push(() => stream
                ? sassTask.stream().setup()
                : sassTask.setup())
        }
        return tasks
    }

    setupWatchPaths() {
        for (const conf of dev.sassConfigs) {
            let watchPath = path.dirname(conf.src.segments.absolutePath)
            if (!this.watchPaths.includes(`${watchPath}/**/*.scss`)) {
                this.watchPaths.push(`${watchPath}/**/*.scss`)
            }
        }
    }

}

const bs = new BS()
const config = bs.config()

module.exports = cb => {
    browserSync.init(config)

    const task1 = () => bs.tasks(true)[0]()
    // task1 === () => (() => sassTask.stream().setup())()  --- returns gulp pipe
    const task2 = bs.tasks(true)[0]
    // task2 === () => sassTask.stream().setup() --- returns gulp pipe

    const conf = dev.sassConfigs[0]
    const task3 = () => (new Sass(conf.src.segments.absolutePath, conf.dest.segments.absolutePath, conf.opts)).stream().setup()

    // Returns true
    console.log(JSON.stringify(task1()) === JSON.stringify(task2()))

    // -------------------------------------
    // Works
    // -------------------------------------
    watch(bs.watchPaths, series(task1))
    watch(bs.watchPaths, series(()=>bs.tasks(true)[0]()))
    watch(bs.watchPaths, series(()=> task3()))
    watch(bs.watchPaths, series(task3))

    // -------------------------------------
    // Doesn't
    // -------------------------------------
    watch(bs.watchPaths, series(task2))
    watch(bs.watchPaths, series(...bs.tasks(true)))
    watch(bs.watchPaths, series(() => task2()))

    cb()
}

If you look at the exports section, task1 and task2 return gulp sass pipes, basically task1 === () => sassTask.stream().setup() and task1 === () => (() => sassTask.stream().setup())() , if I pass task1 info gulp watch it does stream css stylesheet into browsersync, but if I pass task2 it does not.

Why is it happening?

The reason why I need task2 because I want to destruct every task like so, watch(bs.watchPaths, series(...bs.tasks(true))


Solution

  • Don't understand why but this works like magic:

    const argv = require('yargs').argv
    const path = require('path')
    const {watch, series} = require('gulp')
    const webpack = require('webpack')
    const bundler = webpack(webpackConfig)
    const webpackDevMiddleware = require('webpack-dev-middleware')
    const webpackHotMiddleware = require('webpack-hot-middleware')
    const Sass = require('./sass')
    
    class BS {
        constructor() {
            this.watchPaths = [`${process.cwd()}/tailwind.config.js`]
            this.setupWatchPaths()
        }
    
        config() {
            let middleware = [
                webpackDevMiddleware(bundler, {
                    publicPath: webpackConfig.output.publicPath,
                }),
            ]
    
            if (argv.hot) {
                middleware.push(webpackHotMiddleware(bundler))
            }
            return {
                ...dev.bs,
                middleware,
            }
        }
    
        tasks(stream = false) {
            const tasks = []
            for (const conf of dev.sassConfigs) {
                tasks.push(() => {
                    const sassTask = new Sass(conf.src.segments.absolutePath, conf.dest.segments.absolutePath, conf.opts)
                    return stream
                        ? sassTask.stream().setup()
                        : sassTask.setup()
                })
            }
            return tasks
        }
    
        setupWatchPaths() {
            for (const conf of dev.sassConfigs) {
                let watchPath = path.dirname(conf.src.segments.absolutePath)
                if (!this.watchPaths.includes(`${watchPath}/**/*.scss`)) {
                    this.watchPaths.push(`${watchPath}/**/*.scss`)
                }
            }
        }
    
    }
    
    const bs = new BS()
    
    module.exports = () => {
        browserSync.init(bs.config())
        
        watch(bs.watchPaths, series(...bs.tasks(true)))
    }