Can't get GulpFile to act the way I want, missing something?

316 views Asked by At

Trying to set up gulp and one of the steps is frustrating. I am following a tutorial and can't get it to work right.

https://css-tricks.com/gulp-for-beginners/

Basically, I want to create a build task that compiles sass, concats the css files, minimizes it, and output it to the public folder. Here is my code for my index.html. (Simplified).

<!DOCTYPE html>
<html lang="en">

<head>

    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!--build:css css/styles.min.css -->
    <link rel="stylesheet" href="scss/styles.scss">
    <!-- endbuild -->
</head>

<body>

</body>

</html>

Now here is my Gulpfile.js

var gulp = require('gulp'),
    sass = require('gulp-sass'),
    useref = require('gulp-useref'), // Use to concatenate files
    gulpIf = require('gulp-if'),
    cssnano = require('gulp-cssnano'),
    uglify = require('gulp-uglify'),
    imagemin = require('gulp-imagemin'),
    imagecache = require('gulp-cache'),
    del = require('del'),
    runsequence = require('run-sequence');


/* ********************************* */
// PRODUCTION TASKS ONLY \\


/*Used to start with a clean slate on the public folder */
gulp.task('clean:public', function () { 
    return del.sync('public');
})

gulp.task('watch:prod', function () {
    gulp.watch('src/scss/**/*.scss', ['sass']);
});

gulp.task('sass:prod', function () {
    return gulp.src('src/scss/**/*.scss')
        .pipe(sass())
        .pipe(gulp.dest('public/css'))
});

gulp.task('useref:prod', function () {
    return gulp.src('src/*.html')
        .pipe(useref())
        .pipe(gulpIf('*.js', uglify()))
        .pipe(gulpIf('*.css', cssnano()))
        .pipe(gulp.dest('public'));
});

gulp.task('images:prod', function () {
    return gulp.src('src/images/**/*.+(png|jpg|gif|svg)')
    .pipe(imagecache(imagemin([
    imagemin.gifsicle({interlaced: true}),
    imagemin.jpegtran({progressive: true}),
    imagemin.optipng({optimizationLevel: 5}),
    imagemin.svgo({plugins: [{removeViewBox: true}]})
])))
    .pipe(gulp.dest('public/images'));
});

gulp.task('cssimages:prod', function () {
    return gulp.src('src/css/cssimages/**/*.+(png|jpg|gif|svg)')
    .pipe(imagecache(imagemin([
    imagemin.gifsicle({interlaced: true}),
    imagemin.jpegtran({progressive: true}),
    imagemin.optipng({optimizationLevel: 5}),
    imagemin.svgo({plugins: [{removeViewBox: true}]})
])))
    .pipe(gulp.dest('public/css/cssimages'));
});

/* BRING EVERYTHING TOGETHER */

gulp.task('build:prod', function (callback){
    runsequence
        (
            'clean:public',
            ['sass:prod','useref:prod','images:prod', 'cssimages:prod'], 
            callback
        )
})

As per the tutorial, this should create a file in the public folder under css names styles.min.css

This file should also already be compiled down from sass. I did an example styles.scss and inside it I have.

$bgcolor : yellow;
body {
    background: $bgcolor;
}

div {
    width: 100px;
    height: 20px;
}

When I run gulp build:prod , this is what it outputs in styles.min.css

$bgcolor:#ff0;body{background:$bgcolor}div{width:100px;height:20px}

The files minimizing fine but i can't get the sass part run right and compile when use the build task.

Folder structure

^^^ As you see, instead of sassing the file and then concatenating the file, it create 2 files. I'm trying to have gulp sass the file first, and then have useref move the file to the public folder and rename it to styles.min.css

It seems I'm missing something somewhere or not sourcing/destinating to the right folders?

If I run gulp sass:prod, it works fine. But can't seem to get my build task to run right I'm stumped.

2

There are 2 answers

2
Ramu Achala On BEST ANSWER

From the article that you have mentioned,

Gulp-useref concatenates any number of CSS and JavaScript files into a single file by looking for a comment that starts with "". Its syntax is:

<!-- build:<type> <path> --> ... HTML Markup, list of script / link tags. <!-- endbuild -->

path here refers to the target path of the generated file.

According to the document you have specified the following.

<!--build:css css/styles.min.css -->
    <link rel="stylesheet" href="scss/styles.scss">
<!-- endbuild -->

So the useref will copy the styles from styles.scss and creates styles.min.css and pastes the scss styles. That is the reason you are getting scss styles in the minified styles.min.css

To achieve what you wanted you have to modify your sass:prod dest path like below.

gulp.task('sass:prod', function () {
    return gulp.src('src/scss/**/*.scss')
        .pipe(sass())
        .pipe(gulp.dest('src/css'))
});

and in the html, you have to reference the css file.

<!--build:css css/styles.min.css -->
   <link rel="stylesheet" href="css/styles.css">
<!-- endbuild -->

And also as specified by @Mark, it is better to modify the run-sequence to make sure that the sass:prod task completes before the useref:prod task.

gulp.task('build:prod', function (callback){
    runsequence
        (
            'clean:public','sass:prod',
            ['useref:prod','images:prod', 'cssimages:prod'], 
            callback
        )
})
0
Mark On

From the run-sequence documentatin :

You can still run some of the tasks in parallel, by providing an array of task names for one or more of the arguments.

So, in your tasks array :

['sass:prod','useref:prod','images:prod', 'cssimages:prod'], 

these tasks run in parallel. There is no guarantee that the 'sass:prod' task will complete before the 'useref:prod' task. If you want that to happen change to:

gulp.task('build:prod', function (callback){
runsequence
    (
        'clean:public',
        'sass:prod',
        ['useref:prod','images:prod', 'cssimages:prod'], 
        callback
    )
})