Martyn
Martyn

Reputation: 6383

Compile *.css files along with *.scss files

We have a combination of CSS and SCSS files. This is because we write our own styles in SCSS and some style libraries also provide a SCSS file, but we also have CSS only files where either no SCSS file is provided by the library vendor (e.g. they only provide a CSS file or a LESS file)

Below is our gulpfile.js task for SCSS files:

gulp.src([
        'bower_components/simple/simple.css',
        //... more CSS files

        'src/scss/app.scss'
        ],
        {base: '.'})
    .pipe(sourcemaps.init())
    .pipe(sass())
    .pipe(sourcemaps.write())
    .pipe(gulp.dest('dist/css'));

Anyway, this seems to be giving us strange behaviour such as creating a "bower_components" directory in the dist/ directory. How can we compile CSS files along with SCSS files?

Upvotes: 0

Views: 1284

Answers (2)

Daisi
Daisi

Reputation: 2418

Here are a couple of things you could try

1. Using gulp passthrough

This feature is probably the easiest but the caveat is that it requires gulp version 4

var gulp = require('gulp');
var sass = require('gulp-sass');
var concat = require('gulp-concat');
var bower_files = require('main-bower-files');
var sourcemaps = require('gulp-sourcemaps');
var filter = require('gulp-filter');
var merge = require('merge2');

gulp.task('styles', function () {
    var glob = bower_files('**/*.scss') // select the sass bower files
    glob.push('app/**/*.scss')          // select your projects sass files

    return gulp.src(glob)
      .pipe(sourcemaps.init())
      .pipe(sass().on('error', sass.logError))
      .pipe(gulp.src(bower_files('**/*.css'), {passthrough: true} )) // add bower css files to stream
      .pipe(concat('main.css'))
      .pipe(sourcemaps.write())
      .pipe(gulp.dest('dist'));
});

The workflow here is that you select all your initial sass files which will be from the bower components directory and also your projects directory. Then pass them to the sass compiler. Afterwards we can select all the bower downloaded css files using another gulp.src method and by passing the passthrough option to the method we add these files to our already sass compiled files and perform other necessary operations.

2. Using merge streams

This option doesn't require gulp version 4 and is probably a better option as it allows you to perform multiple operations on the different streams.

gulp.task('styles', function () {
    var scss_stream = bower_files('**/*.scss')
    scss_stream.push('app/**/*.scss')

    scss_stream = gulp.src(scss_stream)
      .pipe(sass().on('error', sass.logError));

    var css_stream = gulp.src(bower_files('**/*.css'))

    return merge(scss_stream, css_stream)
      .pipe(concat('main-one.css'))
      .pipe(gulp.dest('dist'));
})

By selecting different type of files separately and making them their own stream, we can perform several operations on the different streams. Here in the first stream, we selected the projects and bowers scss files and passed them to the gulp sass plugin. In the second stream we selected all the css files. We then merged both streams together and performed operations that aren't unique for the two (concatenation and writing to destination)

I strongly recommend using the main-bower-files plugin to select files from bower_components

Also be careful if the order of files being selected is important. You may have to resort to actually selecting the files in the right order. You could use the stream queue plugin along with the gulp-filter plugin.

I hope this helps

Upvotes: 0

fjoe
fjoe

Reputation: 1160

I ran into this same problem basically gulp doesn't like your diverse folder paths in src and you would have to use 2 different tasks to processes this as you wanted.

The only simple way I found to fix this is to use this utility: npm-gulp-rename

With a line like this:

var rename = require("gulp-rename");

.pipe(rename(function (path) { return path.dirname = "./"; }))

What this will do is remove the extra folder information in the stream after it has the data so that when it outputs the files the extra folder information is removed.

My code in your example:

gulp.src([
        'bower_components/simple/simple.css',
        //... more CSS files

        'src/scss/app.scss'
        ],
        {base: '.'})
    .pipe(sourcemaps.init())
    .pipe(sass())
    .pipe(sourcemaps.write())
    .pipe(rename(function (path) { return path.dirname = "./"; }))
    .pipe(gulp.dest('dist/css'));

UPDATE (Based on your comment):

Personally I would go about this in a different way:

  1. Copy the files you need out of bower_components.
  2. Place files in a new folder called vendor (ignore folder in GIT).
  3. Then I build the SCSS normally.

Off the top of my head it would work something like this:

gulp.task("copy", function () {
    return gulp.src([
        'bower_components/simple1/simple1.css'
        'bower_components/simple2/simple2.css'
    ], {base: '.'})
    .pipe(rename(function (path) { return path.dirname = './'; }))
    .pipe(gulp.dest('vendor')
)};

gulp.task("scss", ["copy"], function () {
    return gulp.src([ 'src/scss/app.scss' ], {base: '.'})
    .pipe(sourcemaps.init())
    .pipe(sass())
    .pipe(sourcemaps.write())
    .pipe(gulp.dest('dist/css')
)};

Now to the IMPORTANT part which you can do without my personal recommendations.

You will need to add to your app.scss the other CSS files using an @import which directly supports CSS files:

@import "../../vendor/simple1.css";

You could also use the @import directly from the bower_components folder thereby skipping my copy task:

@import "../../bower_components/simple1/simple1.css";

The second task will be the one you run which will create your CSS files all concatenated.

If you would like to not use @import in your app.scss then you can add another common gulp ad-in gulp-concat. If you would like me to expand upon how to use this just leave me a comment.

A few things to consider:

  1. Concatenation might make your source maps incorrect.
  2. Copying files from the bower_components folder to a vendor folder will make the files available on your web server so that your source maps are more meaningful.

Upvotes: 0

Related Questions