Skip to content

Latest commit

 

History

History
148 lines (120 loc) · 5.33 KB

css-js-injection-bower-gulp.md

File metadata and controls

148 lines (120 loc) · 5.33 KB

CSS and JS injection Bower and Gulp

Today I learnt how to manage CSS and JavaScript dependencies via Bower and automatically inject them into appropriate HTML file. The setup can be seen below in a gulpfile.js file.

The task inject reads all Bower dependencies declared in options variable. The key here is ./bower.json file declaration that contains all our JavaScript and CSS dependencies. wiredep takes care of the rest.

To inject our own CSS and JavaScript files which are not downloaded via Bower, we use gulp-inject where we declare where our files are set up in injectSrc variable. That's it, pretty straightforward.

The serve task is not needed here but it runs our server and automatically re-injects any dependencies, or reloads the server in case anything changes in the watched files.

var gulp = require('gulp');
var nodemon = require('gulp-nodemon');

var jsFiles = ['*.js', 'src/**/*.js'];

gulp.task('inject', function () {
    var wiredep = require('wiredep').stream;
    var inject = require('gulp-inject');

    var injectSrc = gulp.src(['./public/css/*.css', './public/js/*.js'], {
        read: false
    });

    var injectOptions = {
        ignorePath: '/public'
    };

    var options = {
        bowerJson: require('./bower.json'),
        directory: './public/lib',
        ignorePath: '../../public'
    };

    return gulp.src('./src/views/*.html')
        .pipe(wiredep(options))
        .pipe(inject(injectSrc, injectOptions))
        .pipe(gulp.dest('./src/views'));
});

gulp.task('serve', ['inject'], function () {
    var options = {
        script: 'app.js',
        delayTime: 1,
        env: {
            'PORT': 3000
        },
        watch: jsFiles
    };

    return nodemon(options)
        .on('restart', function (ev) {
            console.log('Restarting...');
        });
});

An example of bower.json file can be seen below. It doesn't have to be like this, any bower.json file created with bower init will do. The only caveat here is that we need to override some default options because by default Bootstrap only provides less files, so we need to declare where the actual CSS file can be found as well using overrides attribute.

{
    "name": "express-sandbox",
    "description": "",
    "main": "app.js",
    "authors": [
    "Karolis Ramanauskas <[email protected]>"
  ],
    "license": "ISC",
    "homepage": "",
    "ignore": [
    "**/.*",
    "node_modules",
    "bower_components",
    "test",
    "tests"
  ],
    "dependencies": {
        "bootstrap": "^3.3.6",
        "font-awesome": "^4.6.1"
    },
    "overrides": {
        "bootstrap": {
            "main": [
                "dist/js/bootstrap.js",
                "dist/css/bootstrap.css",
                "less/bootstrap.less"
            ]
        },
        "font-awesome": {
            "main": [
                "less/font-awesome.less",
                "css/font-awesome.min.css",
                "scss/font-awesome.scss"
            ]
        }
    }
}

Finally, to inject the files during Gulp task, we declare the appropriate comments in our HTML files. The comments go as such <!-- bower:css --><!-- endbower --> for Bower files, and <!-- inject:css --><!-- endinject --> for files declared by us.

Below is an example of how a <head> would look of such HTML file. After running gulp inject, inside the comments we got our Bower dependencies and our own declared files as expected.

<head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
    <meta charset="utf-8">
    <title>Storystrap Template</title>
    <meta name="generator" content="Bootply" />
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    
    <!-- bower:css -->
    <link rel="stylesheet" href="/lib/bootstrap/dist/css/bootstrap.css" />
    <link rel="stylesheet" href="/lib/font-awesome/css/font-awesome.min.css" />
    <!-- endbower -->

    <!-- bower:js -->
    <script src="/lib/jquery/dist/jquery.js"></script>
    <script src="/lib/bootstrap/dist/js/bootstrap.js"></script>
    <!-- endbower -->

    <!-- inject:css -->
    <link rel="stylesheet" href="/css/styles.css">
    <!-- endinject -->

    <!-- inject:js -->
    <script src="/js/app.js"></script>
    <!-- endinject -->

    <!--[if lt IE 9]>
		<script src="//html5shim.googlecode.com/svn/trunk/html5.js"></script>
	<![endif]-->
</head>

Why?

One question, why do we need this at all? For really small projects there is no real need for such complex JavaScript and CSS dependency management. Where it really shines is when you have a large project with a number of files. Then each time you create a new file or edit existing one, it will become automatically available.

Also, in case you want to make the project more maintainable in the future, Bower is great because it makes updating packages a lot more convenient by removing the need for manual copy/pasting. It also manages the dependencies for whatever JavaScript and CSS files you require and thus, lessens the probability of new updates breaking your build.

Resources