Buy

Bower Components out of web

Great news! We've minified and combined all our CSS into just one file. Oh, except for the Bootstrap CSS! We have two good options. First, we could point the link to a public Bootstrap CDN. Or we could cram the bootstrap styling right into main.css. Let's do that - it's a lot more interesting.

Bower!

Bootstrap is installed thanks to Bowser. Um, I mean bower. Bower is the Composer for frontend assets, like Bootstrap or jQuery. It's an alternative to downloading the files and committing them to your repo.

Bower reads from, surprise!, a bower.json file:

20 lines bower.json
{
"name": "knpu-gulp",
... lines 3 - 15
"dependencies": {
"bootstrap": "~3.3.2"
}
}

And when I created the project, I also added a .bowerrc file. This told bower to download things into this web/vendor directory:

4 lines .bowerrc
{
"directory": "web/vendor"
}

That made them publicly accessible.

But now that we have the muscle of Gulp, I want to complicate things. Change this to be vendor/bower_components:

4 lines .bowerrc
{
"directory": "vendor/bower_components"
}

That'll put these files outside of the public directory, which at first, will cause some issues. Delete that old stuff:

rm -rf web/vendor

Head to the terminal and ctrl+c out of gulp. Now, run bower install:

bower install

If you don't have the bower command, just check out their docs. It's installed globally via npm, exactly like gulp.

Done! Now, in my vendor/ directory I have a beautiful bower_components folder.

Adding CSS Files to our Gulp Styles Stream

But even if I wanted to have 2 separate link tags in my layout, I can't: Bootstrap no longer calls the web/ directory home. So, get rid of its link tag.

In gulpfile.js, let's try to fix things! I'll start by adding a new configuration variable called bowerDir, because it's going to be really common to refer to things in that directory. Set it to vendor/bower_components:

41 lines gulpfile.js
... lines 1 - 3
var config = {
... lines 5 - 8
bowerDir: 'vendor/bower_components'
};
... lines 11 - 41

If you open that directory, you can see where the bootstrap.css file lives. Notice, it's not a Sass file - just regular old CSS. There actually is a Sass version of Bootstrap, and you can totally use this instead if you want to control your Bootstrap variables.

But the question is, can we push plain CSS files through our Sass-processing addStyle function? Sure! Let's add config.bowerDir then /bootstrap/dist/css/bootstrap.css:

41 lines gulpfile.js
... lines 1 - 23
gulp.task('sass', function() {
app.addStyle([
config.bowerDir+'/bootstrap/dist/css/bootstrap.css',
config.assetsDir+'/sass/layout.scss',
config.assetsDir+'/sass/styles.scss'
], 'main.css');
... lines 30 - 33
});
... lines 35 - 41

And we don't even need to worry about getting the min file, because we're already taking care of that. This file will go through the sass filter. But that's ok! It'll just look like the most boring Sass file ever.

Head back and run gulp:

gulp

And now, main.css starts out with glorious Bootstrap code. And it would be minified if I had passed the --production flag.

Our site should still look great. So refresh. Yep, it's just like before, but with one less pesky CSS file to download.

Renaming the Task to styles

And before we keep going, I think we can make another improvement. Our task is called sass. Let's change this to styles, because it's job is really to process styles, whether those are CSS or Sass files.

41 lines gulpfile.js
... lines 1 - 23
gulp.task('styles', function() {
... lines 25 - 33
});
... lines 35 - 41

We also need to change that name on the default task. Ooops, and before restarting Gulp, also change the name on the watch task to styles:

41 lines gulpfile.js
... lines 1 - 35
gulp.task('watch', function() {
gulp.watch(config.assetsDir+'/'+config.sassPattern, ['styles'])
});
... line 39
gulp.task('default', ['styles', 'watch']);

Ok, now we can try things. ctrl+c to stop Gulp, and re-start it:

gulp

Yes, no errors! And the site still looks Tri-tastic! See what I did there?

Leave a comment!

  • 2016-08-30 Stéphane

    Hi Paul-André,
    Thank you for your solution.

  • 2016-08-29 weaverryan

    Thanks for sharing Paul-André - and sorry about the issue! There is definitely some problem here - but I also haven't been able to nail it down yet.

  • 2016-08-29 Paul-André Duchesne

    Hello Stéphane,

    I've been having the same problem you've got. While looking at the error stack trace, it was mentioning it's coming from clean-css plugin.
    I guess that, like me, you followed the suggestion of not using gulp-minify-css plugin because of deprecation and to use gulp-clean-css instead...
    The only workaround I've currently found was to produce two different minified css: one for everything's coming from vendor/bower_components (bootstrap en fontawesome) that I named vendor.css and one for everything's coming from app/Resources/assets that I named main.css:
    gulp.task('styles', function() {
    var pipeline = new Pipeline();

    pipeline.add([
    config.bowerDir+'/bootstrap/dist/css/bootstrap.css',
    config.bowerDir+'/fontawesome/css/font-awesome.css'
    ], 'vendor.css');

    pipeline.add([
    config.assetsDir+'/sass/base.scss'
    ], 'main.css');

    return pipeline.run(app.addStyle);
    });

    It's not the ideal solution, but at least it's not failing anymore :)

    Kind regards,

    Paul-André

  • 2016-05-31 weaverryan

    Hey Stéphane!

    Hmm, I'm not sure about this - I can't repeat it locally. However, it's very likely that some change to some newer version of a library (probably sourcemaps related) is causing this issue. If you turn sourcemaps off, does the issue go away? Does everything work if you point to the bootstrap.css file that lives in the web directory (i.e. before the steps in this chapter)?

    Cheers!

  • 2016-05-26 Stéphane

    Hi,
    After add the instruction config.bowerDir+'/bootstrap/dist/css/bootstrap.css' I have an error when I start gulp. In the terminal, there is this error : Error: ENOENT: no such file or directory, open '/home/stephane/www/gulp/app/Resources/assets/sass/bootstrap.css.map'
    You know how I can correct this ? Thank.