Gulp - the best way of minifying multiple css files into one? - css

What is the best way of minify multiple css files into one?
The gulp task below causing two issues after the minification and concatenation:
bootstraps glyphicons that I use have disappeared.
some of my styles are broken. The task seems to have re-arranged the position of some styles, for instance .footer{...} was placed below html{...} but it is now above html{...}. How can i stop it from rearranging them?
gulpfile:
gulp.task('minify-css', function() {
return gulp.src([
'node_modules/bootstrap/dist/css/bootstrap.css',
'vendor/jquery-ui-1.12.1/jquery-ui.min.css',
'node_modules/bootstrap/dist/css/bootstrap-theme.css',
'node_modules/jasny-bootstrap/dist/css/jasny-bootstrap.css',
'css/style.css',
])
.pipe(sourcemaps.init())
.pipe(cleanCSS({debug: true}))
.pipe(sourcemaps.write())
.pipe(concat('bundle.min.css'))
.pipe(gulp.dest('dist'));
});
Any ideas?

I don't know if it help you but I think you could use SASS preprocessing by gulp-sass. There you could import all of your dependencies and let gulp-sass to minify the result. I have similar approach in my gulp devstack. SASS (libsass) can import *.css files, e.g. in your main.scss you can write
#import "path/to/file";
Note that without .css extension!
If you not familiar with SASS I recommend to give it a chance.

It's not a common solution but sometimes it helps. I make two min. bundles: 'head.bundle.min.css' and 'foot.bundle.min.css' just like you did. In head.bundle.min.css I collect styles which must be first. And finally I concatenated two min bundles in one.

Related

Laravel Mix import multiple globbed SCSS files into app.scss

I have a project structure where each component has its own SCSS file, and I would like to have all of these automatically imported into the project's main app.scss file, without having to list them all individually or update the list every time a new component is added. I know that merging a bunch of globbed CSS files could cause issues with selector order, but that is not a concern here.
I have tried this, with the components.scss file imported into app.scss:
mix.styles('resources/views/components/*.scss', 'resources/css/components.scss');
mix.sass('resources/css/app.scss', 'public/css');
And it basically works.
Except, mix.styles() runs after the Sass compilation, so you end up with the components.scss file from the previous execution being imported, rather than the current one.
Is there a way to solve this? Or is there another approach that would work?
As Sass #import does not support glob paths it's not possible to do something like this in app.scss as far as I am aware:
#import 'resources/views/components/*';
Discovered this can be done quite easily with node-sass-glob-importer, which is compatible with the Dart Sass implementation that Mix uses:
const sassGlobImporter = require('node-sass-glob-importer');
mix.sass('resources/css/app.scss', 'public/css', {
sassOptions: {
importer: sassGlobImporter(),
}
});
resources/css/app.scss
#import '../views/components/**/*.scss';

Why can't gulp compile a SASS file which imports a CSS file created by a previous gulp task?

I have a project which a dependency on Bootstrap. I'm customising the Boostrap variables so using gulp to do a custom compile of Bootstrap's LESS source. The rest of the CSS in my project is written with SASS. I have an imports.sass file which includes the following line:
#import '../bootstrap/compiled/custom-bootstrap';
What I'm trying to do is compile the Bootstrap LESS to CSS, then run a SASS task to create a CSS file which includes the compiled Bootstrap CSS. My 2 gulp tasks which achieve this are as follows:
gulp.task('bootstrap', function () {
return gulp
.src('assets/bootstrap/custom-bootstrap.less')
.pipe(less())
.pipe(gulp.dest('assets/bootstrap/compiled'));
});
gulp.task('sass', function () {
return gulp
.src('assets/scss/*.scss')
.pipe(sass({
includePaths: ['assets/bootstrap/compiled']
}).on('error', sass.logError))
.pipe(gulp.dest('assets/css'));
});
The first time I run this, the bootstrap task completes successfully, but the sass task throws this error:
Error in plugin 'sass' Message:
assets\scss\_imports.scss Error: File to import not found or unreadable: ../bootstrap/compiled/custom-bootstrap
Parent style sheet: [path/to]/assets/scss/_imports.scss
on line 5 of assets/scss/_imports.scss
>> #import '../bootstrap/compiled/custom-bootstrap';
^
When I run it a second time both complete successfully so clearly the problem is the fact that custom-bootstrap.css doesn't exist at the start of the initial run. However, you can see I've added the relevant includePaths option which seems to be the solution for other similar issues elsewhere on SO. Perhaps I'm not specifying this path correctly?
To complete the information you need, here is the structure of my solution detailing the relevant files. I'm confident the paths I've used are correct but just in case I've missed something...
assets
bootstrap
custom-bootstrap.less
custom-variables.less
scss
_imports.scss
main.scss
gulpfile.js
In case it's relevant, this is the front-end for an ASP.NET solution so I'm using Visual Studio's task runner to execute the gulp tasks, and this also explains why gulpfile.js is in the root of the project.

Less CSS - Add vendor prefixes with less.js in development environment

I'm using LESS with Gulp. I'm also using the Autoprefixer plugin which adds all needed vendor prefixes based on Browserlist. This works pretty nice when creating all minified files for the final export.
My problem is: When I test the CSS in the developement environment using less.js there are no vendor prefixes added. It seems that the auto prefixer is only available for the cli. Is there a way to add vendor prefixes on the fly with less.js or another plug in? I've already tried to run prefixfree after less.js but without luck.
Just pipe a stream from gulp-less to autoprefixer, e.g.
gulp.task('styles', [], function () {
return gulp.src('less/*.less')
.pipe(gulplLss())
.pipe(postcss([autoprefixer()]))
.pipe(gulp.dest('css/'));
}
gulp.task('watch', function () {
gulp.watch('less/*.less', 'styles');
}
(This is using autoprefixer via postcss tool which is now recommended way. Before deprecation it the autoprefixer line whould be: .pipe(autoprefixer()))
There is a pure frontend solution (if it is what you are looking for). Autoprefixer can run in browser environment. You don't have to run it as a Less plugin.
In estFiddle I run Autoprefixer after compiling Less into CSS and it works. (You can see source code here.)

How can I customise Bootstrap without losing the changes?

I'm using Bower to manage Bootstrap and would like to make some changes (colours, font size etc) to the default Bootstrap look and feel. Here's my workflow:
Edit bower_components/bootstrap/less/variables.less
Recompile bootstrap using grunt build
The problem is that I want to be able to upgrade bootstrap when a new version comes out and presumably I'll lose my changes to variables.less.
Is there a way I can keep my changes outside of bower_components and also avoid having bower_components in source control since it's 122MB?
you can create a variables-custom.less and import it into theme.less like this:
//
// Load core variables and mixins
// --------------------------------------------------
#import "variables.less";
//import custom-variables after variables so the values will override.
#import "custom-variables.less"; //only has variables that have changed.
#import "mixins.less";
IMO this is a little bit better than the first solution because you wont have to load two (almost) identical CSS files on the client.
I'm sorry I cant help you with what to to about Bower and your source control as I do not use Bower
Here's the solution which worked for me:
Use bower to install all UI packages e.g. bower install bootstrap chosen
Create a separate folder less which contains all the LESS modifications. This article was very helpful here.
Here's my less/styles.less file:
#import "../bower_components/bootstrap/less/bootstrap.less";
#import "../bower_components/bootstrap-chosen/bootstrap-chosen.less";
//My custom variables - overrides the bootstrap variables file
#import "variables-custom.less";
Use grunt to monitor changes within the less folder and compile them into .css
Here's my Gruntfile.js (thanks to this answer):
module.exports = function(grunt) {
grunt.initConfig({
less: {
development: {
options: {
paths: ["./less"],
yuicompress: true
},
files: {
"./static/css/styles.css": "./less/styles.less"
}
}
},
watch: {
files: "./less/*",
tasks: ["less"]
}
});
grunt.loadNpmTasks('grunt-contrib-less');
grunt.loadNpmTasks('grunt-contrib-watch');
};
This is indeed the best customization method. You create a theme.less and pull in original Bootstrap files (which can get upgraded in the future) and in the same file you call your own custom overrides. Either you #import them from a custom file which is not in the Bower directory or you just write your custom rules in your theme.less itself. You'll find this technique explained in this tutorial as well.
With Grunt, custom setups can get tricky. But with Brunch it's a piece of cake (yes!) and all pretty much goes automatically. Your grandma could do it.
As for avoiding the inclusion of bower_components in source control: with Git it's easy. You just check-in your bower.json but make sure to add /bower_components to your .gitignore file.
You should just create your own style sheet, use both with your custom one listed secondly. That way you can make changes but not change bootstrap at all.
Also, when you update, you keep your style sheet the same.
This allows you to change bits and pieces of Bootstrap but not actually changing the file, you're overriding it.
To be clear, your second CSS file would be SIGNIFICANTLY smaller... Only putting things your needed to change in it.

Using r.js to concatenate CSS

I'm working on a project using require.js and plan to optimize it using r.js. The optimization for javascript files is built in as part of the require configration automatically.
What I would like is to split the CSS into several different files, e.g. head.css, body.css, main.css, etc. When r.js runs, it should concatenate these into a single file. The HTML would have:
<link rel=stylesheet type=text/css href=css/main.css>
A problem is that during development, the files will still be split up. I'd like to keep them split and don't want to have to redo the optimization every time -- even if it can be done automatically.
I'd also like to be able to keep the HTML with just the one stylesheet reference even in development. What would be the optimal way to do this?
There are several possibilities that I can see, each with potential problems:
Have main.css use #import to include all other CSS files.
Not automatic -- have to edit main.css for each file. That's not a big deal since the number of files will be relatively small and probably all known very early on.
r.js does not optimize this
Use require-css
This seems to be geared more towards AMD loading of CSS -- I'd rather load all the CSS up front
Same issues with automatic loading of CSS files as the other option
Create my own script that calls r.js without CSS optimization, concatenate all of the CSS files and minify appropriately.
I'm sure there's someone out there who has done this better than I will
I use grunt-contrib-cssmin which works great. You can also pass arguments to grunt, so you can have grunt:dist combine all your css and plain grunt will leave them separate.
module.exports = function (grunt) {
grunt.initConfig({
cssmin: {
add_banner: {
options: {
banner: '/* My minified css file */'
},
files: {
'dist/css/dist.min.css': ["bower_components/bootstrap/dist/css/bootstrap.css", "tmp/css/dist.css"]
}
}
}
})
}
Grunt getting started.
There is also a requirejs script for grunt. The setup looks like this:
requirejs: {
compile: {
options: {
baseUrl: "path/to/base",
mainConfigFile: "path/to/config.js",
out: "path/to/optimized.js"
}
}
}

Resources