cssgulplessgulp-lessgulp-clean-css

Gulp + Less + Minify CSS error: concat multiple Less files?


How do you concat multiple Less files?

For instance, I have functions.less with all the functions that I want to use them in the style.less:

functions.less:

.rotate (@deg) {
    -webkit-transform: rotate(@deg * 1deg);
    -moz-transform: rotate(@deg * 1deg);
    -ms-transform: rotate(@deg * 1deg);
    -o-transform: rotate(@deg * 1deg);
}

style.less:

.button {
    .rotate (@deg: 90);
}

gulpfile.js:

// Task to compile less.
gulp.task('compile-less', function () {
  return gulp.src([
    'stylesheets/*.less'
  ])
  .pipe(sourcemaps.init())
  .pipe(less())
  .pipe(concat('compiled.css'))
  .pipe(sourcemaps.write('./maps'))
  .pipe(gulp.dest('stylesheets'))
})

// Task to minify css.
gulp.task('minify-css', function () {
  return gulp.src([
    'stylesheets/compiled.css'
  ])
  .pipe(sourcemaps.init())
  .pipe(cleanCSS({debug: true}))
  .pipe(concat('bundle.min.css'))
  .pipe(sourcemaps.write('./maps'))
  .pipe(gulp.dest('dist'))
  .pipe(livereload())
})

I will get:

Potentially unhandled rejection [2] No matching definition was found for .rotate (@deg: 90) in file /var/www/.../style.less line no. 107

Any ideas?

EDIT:

I get this errors sometimes when I use @import:

undefined:1



SyntaxError: Unexpected end of JSON input
    at JSON.parse (<anonymous>)
    at loadInputSourceMapFromLocalUri (/var/www/.../node_modules/clean-css/lib/reader/apply-source-maps.js:177:15)
    at extractInputSourceMapFrom (/var/www/.../node_modules/clean-css/lib/reader/apply-source-maps.js:116:17)
    at fetchAndApplySourceMap (/var/www/.../node_modules/clean-css/lib/reader/apply-source-maps.js:79:10)
    at doApplySourceMaps (/var/www/.../node_modules/clean-css/lib/reader/apply-source-maps.js:57:14)
    at applySourceMaps (/var/www/.../node_modules/clean-css/lib/reader/apply-source-maps.js:33:5)
    at Object.callback (/var/www/.../node_modules/clean-css/lib/reader/read-sources.js:25:12)
    at doInlineImports (/var/www/.../node_modules/clean-css/lib/reader/read-sources.js:200:25)
    at Object.callback (/var/www/.../node_modules/clean-css/lib/reader/read-sources.js:324:14)
    at doInlineImports (/var/www/.../node_modules/clean-css/lib/reader/read-sources.js:200:25

EDIT 2:

Obviously it is gulp-clean-css that is causing the problem:

// CSS compilation.
var concat = require('gulp-concat')
var cleanCSS = require('gulp-clean-css')
var concatCss = require('gulp-concat-css') // optional

gulp.task('minify-css', function () {
  return gulp.src([
    'stylesheets/style.css'
  ])
  .pipe(sourcemaps.init())
  // .pipe(cleanCSS({debug: true}))
  .pipe(concat('bundle.min.css'))
  .pipe(sourcemaps.write('./maps'))
  .pipe(gulp.dest('dist'))
  .pipe(livereload())
})

No error if I remove that line but then I does not minify the css anymore if I do.

Any ideas?

EDIT 3:

Entire content in gulpfile:

var gulp = require('gulp')
var sourcemaps = require('gulp-sourcemaps')
var livereload = require('gulp-livereload')

// JavaScript development.
var browserify = require('browserify')
var babelify = require('babelify')
var source = require('vinyl-source-stream')
var buffer = require('vinyl-buffer')
var uglify = require('gulp-uglify')

// Less compilation.
var less = require('gulp-less')

// CSS compilation.
var concat = require('gulp-concat')
var cleanCSS = require('gulp-clean-css')
var concatCss = require('gulp-concat-css') // optional

// HTML compilation.
var htmlmin = require('gulp-htmlmin')
var path = require('path')
var foreach = require('gulp-foreach')

// Task to compile js.
gulp.task('compile-js', function () {
  return browserify({
    extensions: ['.js', '.jsx'],
    entries:  ['./javascripts/app.js'],
    debug: true
  })
  .transform('babelify', {
    presets: ['es2015', 'es2017', 'react'],
    plugins: [

      // Turn async functions into ES2015 generators
      // https://babeljs.io/docs/plugins/transform-async-to-generator/
      "transform-async-to-generator"
    ]
  })
  .bundle()
  .pipe(source('bundle.min.js'))
  .pipe(buffer())
  .pipe(sourcemaps.init())
  .pipe(uglify())
  .pipe(sourcemaps.write('./maps'))
  .pipe(gulp.dest('dist'))
  .pipe(livereload())
})

// Task to compile less.
gulp.task('compile-less', function () {
  return gulp.src([
    'stylesheets/*.less'
  ])
  .pipe(sourcemaps.init())
  .pipe(less())
  .pipe(sourcemaps.write('./maps'))
  .pipe(gulp.dest('stylesheets'))
})

// Task to minify css.
gulp.task('minify-css', function () {
  return gulp.src([
    'stylesheets/style.css'
  ])
  .pipe(sourcemaps.init())
  .pipe(cleanCSS({debug: true}))
  .pipe(concat('bundle.min.css'))
  .pipe(sourcemaps.write('./maps'))
  .pipe(gulp.dest('dist'))
  .pipe(livereload())
})

// Loop each html.
// https://www.npmjs.com/package/gulp-foreach
gulp.task('minify-html', function () {
  return gulp.src('*.html')
    .pipe(foreach(function(stream, file){
      // Get the filename.
      // https://github.com/mariusGundersen/gulp-flatMap/issues/4
      // https://nodejs.org/api/path.html#path_path_basename_p_ext
      var name = path.basename(file.path)
      return stream
        .pipe(htmlmin({
          collapseWhitespace: true,
          removeComments: true
        }))
        .pipe(concat('min.' + name))
    }))
    .pipe(gulp.dest(''))
})

// Task to copy fonts to dist.
gulp.task('compile-fonts', function() {
  return gulp.src([
    'fonts/*',
    'node_modules/material-design-icons/iconfont/MaterialIcons-Regular.*',
    'node_modules/foundation-icon-fonts/foundation-icons.*',
  ])
  .pipe(gulp.dest('dist/fonts/'))
})

// Task to copy images to dist.
gulp.task('compile-images', function() {
  return gulp.src([
    'images/*',
    'node_modules/jquery-ui-bundle/images/*',
  ])
  .pipe(gulp.dest('dist/images/'))
})

// Task to watch less & css changes.
gulp.task('watch', function () {
  gulp.watch('javascripts/*.js', ['compile-js'])  // Watch all the .js files, then run the js task
  gulp.watch('stylesheets/*.less', ['compile-less'])  // Watch all the .less files, then run the less task
  gulp.watch('stylesheets/*.css', ['minify-css'])  // Watch all the .css files, then run the css task
  gulp.watch('stylesheets/*.css', ['compile-fonts'])  // Watch all the .css files, then run the font task
  gulp.watch('stylesheets/*.css', ['compile-images'])  // Watch all the .css files, then run the image task
})

// Development:
// Task when running `gulp` from terminal.
gulp.task('default', ['watch'])

// Production:
// Task when running `gulp build` from terminal.
gulp.task('build', ['minify-css', 'compile-fonts', 'compile-js', 'minify-html'])

Solution

  • All you need to do is create a master less file and import all your less files.

    So create, for example a file called master.less. Then edit this file by adding the follow instruction:

     @import "functions.less";
     @import "styles.less";
    

    And thats it. Then the gulp-less does the rest!! :) It compiles al the code in one single css file.

    My suggestion for your task is (this is the code i have in my project startup):

        var gulp = require('gulp'),
            postcss = require('gulp-postcss'),
            less = require('gulp-less'),
            autoprefixer = require('autoprefixer');
            concat = require('gulp-concat'),
            cssnano = require('gulp-cssnano'),
            browserSync = require('browser-sync');
    
    
        gulp.task('less', function () {
            var processors = [
                autoprefixer,
                cssnano
            ];
            gulp.src(config.paths.less.src)
                .pipe(less())
                .pipe(postcss(processors))
                .pipe(concat('bundle.min.css'))
                .pipe(cssnano())
                .pipe(gulp.dest('dist'))
                .pipe(browserSync.reload({stream:true}))
        });