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

Add prepend option for autoInject #40

Closed pcfreak30 closed 8 years ago

pcfreak30 commented 8 years ago

There are cases where the css needs to be at the top not the bottom.

cheton commented 8 years ago

Hi @pcfreak30,

May I know for what purpose you may want to insert CSS to the head in reverse order?

If you require CSS files with the prepend option like this:

require('./app.css');
require('./app2.css');

then you will get the following result: image

pcfreak30 commented 8 years ago

@cheton im aware of that. Im my case I have css already on the page which isn't feasible to bundle and I don't need to be using !important

cheton commented 8 years ago

For your case, I'd recommend you use onFlush to output separate CSS files, then you can link CSS files at proper order on the page.

var browserify = require('browserify');
var fs = require('fs');

fs.unlinkSync('dist/assets/app.css');

browserify(options)
    .add('src/index.js')
    .transform(require('browserify-css'), {
        rootDir: 'src',
        onFlush: function(options, done) {
            fs.appendFileSync('dist/assets/app.css', options.data);

            // Do not embed CSS into a JavaScript bundle
            done(null);
        }
    })
    .bundle();
pcfreak30 commented 8 years ago

@cheton Not sure how that helps since I want to embed it and not use external. What I have submitted as a PR works well and I know the quirks regarding it.

cheton commented 8 years ago

From my point of view, the prepend option should embed CSS files in its loading order, not in reverse order.

How about updating the PR to insert styles in front of the first <link> tag? For example:

<style type="text/css" data-href="first.css"></style>
<style type="text/css" data-href="second.css"></style>
<link rel="stylesheet" href="css/vendor-specific.css" >
pcfreak30 commented 8 years ago

@cheton would not be accurate as a style could still come before them. You would have to use querySelectorAll to get the 1st style or link stylesheet and store the state somehow to order it right. I personally am not bothered by the reverse order as I know its there.

cheton commented 8 years ago

Hi @pcfreak30,

I'd like to use the algorithm implemented in the style-loader module for webpack. Please stay tuned for further updates.

https://github.com/webpack/style-loader/blob/master/addStyles.js#L102

var styleElementsInsertedAtTop = [];

function insertStyleElement(options, styleElement) {
    var head = getHeadElement();
    var lastStyleElementInsertedAtTop = styleElementsInsertedAtTop[styleElementsInsertedAtTop.length - 1];
    if (options.insertAt === "top") {
        if(!lastStyleElementInsertedAtTop) {
            head.insertBefore(styleElement, head.firstChild);
        } else if(lastStyleElementInsertedAtTop.nextSibling) {
            head.insertBefore(styleElement, lastStyleElementInsertedAtTop.nextSibling);
        } else {
            head.appendChild(styleElement);
        }
        styleElementsInsertedAtTop.push(styleElement);
    } else if (options.insertAt === "bottom") {
        head.appendChild(styleElement);
    } else {
        throw new Error("Invalid value for parameter 'insertAt'. Must be 'top' or 'bottom'.");
    }
}