cheton / browserify-css

A Browserify transform for bundling, rebasing, inlining, and minifying CSS files.
http://cheton.github.io/browserify-css/
MIT License
144 stars 22 forks source link

deterministic call order for onFlush #50

Closed csulok closed 7 years ago

csulok commented 7 years ago

Is it possible to tweak the way browserify-css (or browserify) works, so for the same JS code, the exact same CSS file is created? i.e. onFlush is called in the same order.

Currently when I do the following, bundle.css will be different after consecutive runs, making it hard to review changes and there's some desire to storing the bundled css in version control as well.

if (fs.existsSync("src/css/bundle.css")) {
    fs.unlinkSync("src/css/bundle.css");
}
const bundle = browserify({
    entries: "src/js/client.js"
});
bundle.transform(browserifyCSS, {
    onFlush: function(options, done) {
        fs.appendFileSync("src/css/bundle.css", options.data);
        done(null);
   }
});

return bundle.bundle()
    .pipe(source("bundle-client.js"))
    .pipe(ngAnnotate())
    .pipe(gulp.dest(config.client.jsDirectory));
cheton commented 7 years ago

You can try using lodash to produce deterministic call order:

var _ = require('lodash');
var browserify = require('browserify');
var browserifyCSS = require('browserify-css');
var source = require('vinyl-source-stream');
var tap = require('gulp-tap');

var classes = {};

bundle.transform(browserifyCSS, {
    onFlush: function(options, done) {
        classes[options.filename] = options.data;
        done(null);
    }
});

bundle.bundle()
    .pipe(source('bundle-client.js'))
    .pipe(tap(function() {
        classes = _(classes)
            .toPairs()
            .sortBy(pair => pair[0])
            .reduce((memo, pair) => {
                return memo + pair[1];
            }, ''));
    }));
csulok commented 7 years ago

Thanks, already fiddled around with something like that, collecting options.data into a Buffer and writing it on the end event. These are acceptable workarounds.

Going back the issue though, the bundled javascript file already is deterministic, so there is some capability there for sure. Would it be possible to change browserify-css?

cheton commented 7 years ago

The order is determined by browserify, I'm afraid that I'm not able to keep the order internally within the transform, you might need to control it yourself or try to find supported browserify options.

I'm not sure if browserify pipeline is able to work, but it's worth a try. https://github.com/substack/browserify-handbook#compiler-pipeline https://github.com/substack/browserify-handbook#sort