Concatenate/relocate CSS files with Gulp

3.3k views Asked by At

I'm looking for a plugin chain to use with Gulp that provides:

  • source map support
  • less
  • minification
  • concatenation
  • URL replacement (rebase) to address relocation/concat

I currently have the first four, but I can't find a combination of existing plugins that will give me the last (URL rebasing) also. I've not found any URL rebasing plugins that emit sourcemaps.

Just to be clear, my issue is that when I compile multiple small CSS files from my project development folders, and output them into a common folder, the move resulting from concatenation breaks relative URLs, such as those for background images.

EDITS:

It sounds like the tool chain I currently use is already intended to solve this problem. So, that's ostensibly the answer. However, that raises another question, how the required syntax is supposed to work.

That question theoretically has lots of duplicates out there:

Unfortunately no answers actually explain the syntax, they just demonstrate voodoo; so I don't know why the following isn't working. If I can get it resolved I'll come back here and flag this accepted to indicate this tool chain does actually do what I need.

The source files:

/assets
    /site
        styleInput1.less "url(../site/logo.png)"
        logo.png
        background.png
    /application
        styleInput2.less "url(../site/background.png)"

The gulp task:

gulp.task(filename, function () {
    return gulp.src(files)
        .pipe(sourcemaps.init())
        .pipe(less())
        .pipe(minifyCss({ relativeTo: './compiled' }))
        .pipe(concat(filename))
        .pipe(sourcemaps.write('.'))
        .pipe(gulp.dest('./compiled'));
});

The output, with broken URLs. Note the multiple defects. Although the CSS is raised a directory level relative to the required assets, an additional parent directory has been added (!). Also, one of the URLs has had a hard asset folder name changed (!). Very strange:

/compiled
    styleOutput1.css "url(../../compiled/logo.png)"
    styleOutput2.css "url(../../site/background.png)"

My apologies for continuing the voodoo, but here is my working gulp pipe:

.pipe(minifyCss({ relativeTo: './compiled', target: './compiled' }))

And the correct output:

/compiled
    styleOutput1.css "url(../assets/site/logo.png)"
    styleOutput2.css "url(../assets/site/background.png)"
1

There are 1 answers

6
Romain Braun On BEST ANSWER

I personally use gulp-minify-css and specify the relativeTo attribute.

gulp.task('css', function() {
    gulp.src('./assets/css/main.css')
// Here I specify the relative path to my files
      .pipe(minifyCSS({keepSpecialComments: 0, relativeTo: './assets/css/', processImport: true}))
      .pipe(autoprefixer({
        browsers: ['last 2 versions'],
        cascade: false
      }))
      .pipe(gulp.dest('./assets/css/dist/'))
      .pipe(notify({
          "title": "Should I Go?",
          "subtitle": "Gulp Process",
          "message": '<%= file.relative %> was successfully minified!',
          "sound": "Pop",
          "onLast": true
      }));
  });

If that doesn't work for you, they have a lot of other parameters to rebase URLs : https://github.com/jakubpawlowicz/clean-css#how-to-use-clean-css-programmatically

Notably:

  • rebase - set to false to skip URL rebasing
  • relativeTo - path to resolve relative @import rules and URLs
  • restructuring - set to false to disable restructuring in advanced optimizations
  • root - path to resolve absolute @import rules and rebase relative URLs