How to manage bower dependencies with Grunt
In this article we will describe how to manage bower dependencies with Grunt in your html file.
By managing the bower dependencies I mean, insert automatically bower dependencies in the html file by executing a Grunt command line.
What I want to manage
This is a list of things i want to do :
- Automatically insert the and tags in my index.html file for each dependencies i have in my bower file
- Update (automatically) the file when i add a bower dependency
Installing tools
I assume you already have node.js installed on your system, if not, simply go to the node.js website and follow the instructions.
If you already have Grunt and bower installed no need to do the following steps.
In order to install the needed tools run the following command :
npm install -g bower grunt-cli
Creating the project
Now we will create the main application structure like that :
cd PATHTO/project
mkdir app
Then create the file index.html in the app directory :
- app/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>My Cool Title</title>
</head>
<body>
</body>
</html>
Then we will create the node.js package.json file :
- package.json
{
"name": "projectName",
"version": "0.0.1",
"author": "Remi goyard",
"license": "MIT",
"description": "The Cool Description",
"repository": {
"type": "git",
"url": "http://github.com/"
},
"engines": {
"node": ">= 0.10.0"
}
}
❗️ In order to create that package.json file you can use the command
npm init` at the root of your project directory.
Then create the bower.json file :
- bower.json
{
"name": "projectName",
"version": "0.0.1",
"author": "Remi goyard",
"license": "MIT",
"description": "The Cool Description",
"main": "",
"homepage": "",
"private": true,
"ignore": [
"**/.*",
"node_modules",
"bower_components"
]
}
❗️ In order to create that bower.json
file you can use the command `bower init at the root of your project directory.
Adding dependencies
Ok, now we will add the bower dependencies, imagine, for example, you want to add Bootstrap and the Js implementation.
bower install boostrap asciidoctor.js --save
This will create a bower_components directory in your project.
So now if you want to use the new installed components in your index.html
file you will have to manually add the links, something like that :
- app/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>My Cool Title</title>
<link rel="stylesheet" href="../bower_components/bootstrap/dist/css/bootstrap.min.css" />
<link rel="stylesheet" href="../bower_components/bootstrap/dist/css/bootstrap-theme.min.css" />
</head>
<body>
<!-- JavaScript Files -->
<script src="../bower_components/jquery/dist/jquery.js"></script> (1)
<script src="../bower_components/bootstrap/dist/js/bootstrap.js"></script>
<script src="../bower_components/opal/opal/current/opal.js"></script> (2)
<script src="../bower_components/asciidoctor.js/dist/asciidoctor-all.min.js"></script>
</body>
</html>
- jQuery dependency required by booststrap
- Opal is required by Asciidoctor.js
So now you can use your dependencies.
As you can imagine if you add a bower dependency you will have to manually add the files in your index.html file.
Automatic insertion
As I said at the top of the post, I would prefer to automatically update the index.html file when I add a dependency. We will use Grunt and the grunt-bower-install
plugin.
First we need to create the Gruntfile.js, here is a minimal one :
- Gruntfile.js
/*global module:false*/
module.exports = function(grunt) {
// Project configuration.
grunt.initConfig({
// Tasks
});
// Default task.
grunt.registerTask('default', []);
};
❗️ As usual you can also create the Gruntfile.js
file by using the grunt-init
command.
As this, the file is not very useable, we need to add the grunt-bower-install
plugin :
npm install grunt-bower-install --save-dev
This will add the grunt-bower-install
plugin in the package.json file. And now you can create the grunt task for the plugin :
- Gruntfile.js
/*global module:false*/
module.exports = function(grunt) {
// Project configuration.
grunt.initConfig({
bowerInstall: {
target: {
src: [
'app/index.html' // .html support...
],
// Optional:
// ---------
cwd: '',
dependencies: true,
devDependencies: false,
exclude: [],
fileTypes: {},
ignorePath: '',
overrides: {}
}
}
});
grunt.loadNpmTasks('grunt-bower-install');
// Default task.
grunt.registerTask('default', ['bowerInstall']);
};
Then edit the index.html
file to insert the tags used by the `grunt-bower-install plugin :
- index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>My Cool Title</title>
<!-- bower:css -->
<!-- endbower -->
</head>
<body>
<!-- bower:js -->
<!-- endbower -->
</body>
</html>
And now execute the Grunt command :
grunt bowerInstall
This will modify your index.html
file and generate this one :
- index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>My Cool Title</title>
<!-- bower:css -->
<link rel="stylesheet" href="../bower_components/asciidoctor.js/dist/css/asciidoctor.css" />
<!-- endbower -->
</head>
<body>
<!-- bower:js -->
<script src="../bower_components/jquery/dist/jquery.js"></script> (1)
<script src="../bower_components/bootstrap/dist/js/bootstrap.js"></script>
<script src="../bower_components/opal/opal/current/opal.js"></script> (1)
<script src="../bower_components/asciidoctor.js/dist/asciidoctor.js"></script>
<script src="../bower_components/asciidoctor.js/dist/asciidoctor-core.js"></script>
<script src="../bower_components/asciidoctor.js/dist/asciidoctor-extensions.js"></script>
<script src="../bower_components/asciidoctor.js/dist/asciidoctor-docbook.js"></script>
<script src="../bower_components/asciidoctor.js/dist/asciidoctor-all.js"></script>
<script src="../bower_components/asciidoctor.js/dist/asciidoctor.min.js"></script>
<script src="../bower_components/asciidoctor.js/dist/asciidoctor-core.min.js"></script>
<script src="../bower_components/asciidoctor.js/dist/asciidoctor-extensions.min.js"></script>
<script src="../bower_components/asciidoctor.js/dist/asciidoctor-docbook.min.js"></script>
<script src="../bower_components/asciidoctor.js/dist/asciidoctor-all.min.js"></script>
<script src="../bower_components/asciidoctor.js/dist/asciidoctor.min.gz.js"></script>
<script src="../bower_components/asciidoctor.js/dist/asciidoctor-core.min.gz.js"></script>
<script src="../bower_components/asciidoctor.js/dist/asciidoctor-extensions.min.gz.js"></script>
<script src="../bower_components/asciidoctor.js/dist/asciidoctor-docbook.min.gz.js"></script>
<script src="../bower_components/asciidoctor.js/dist/asciidoctor-all.gz.js"></script>
<!-- endbower -->
</body>
</html>
- As you can see, dependencies requirements are also automatically added. As you can see some JavaScript files seems to be added but not needed and I also guess that the CSS files for Bootstrap are missing …
WHY ???
Simply because the grunt-bower-install
plugin look in dependencies bower.json
‘s files for the main files, and it add them to your file… We will need to adjust that « main » section.
Overriding main section For « overriding » the main section you can add an « overrides » section in your bower.json file (in your project root directory) :
- bower.json
{
"name": "projectName",
"version": "0.0.1",
"author": "Remi goyard",
"license": "MIT",
"description": "The Cool Description",
"main": "",
"homepage": "",
"private": true,
"ignore": [
"**/.*",
"node_modules",
"bower_components"
],
"overrides": { (1)
"asciidoctor.js": {
"main": [
"dist/asciidoctor-all.min.js",
"dist/css/asciidoctor.css"
]
},
"bootstrap": {
"main": [
"dist/js/bootstrap.min.js",
"dist/css/bootstrap.min.css",
"dist/css/bootstrap-theme.min.css"
]
}
}
}
- Will override some dependencies properties.
And then execute again the grunt command :
grunt bowerInstall
Which will generate the following index.html file :
- index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>My Cool Title</title>
<!-- bower:css -->
<link rel="stylesheet" href="../bower_components/bootstrap/dist/css/bootstrap.min.css" />
<link rel="stylesheet" href="../bower_components/bootstrap/dist/css/bootstrap-theme.min.css" />
<link rel="stylesheet" href="../bower_components/asciidoctor.js/dist/css/asciidoctor.css" />
<!-- endbower -->
</head>
<body>
<!-- bower:js -->
<script src="../bower_components/jquery/dist/jquery.js"></script>
<script src="../bower_components/bootstrap/dist/js/bootstrap.js"></script>
<script src="../bower_components/opal/opal/current/opal.js"></script>
<script src="../bower_components/asciidoctor.js/dist/asciidoctor-all.min.js"></script>
<!-- endbower -->
</body>
</html>
YEAAHHH !!
Now we have what we expected !
Automatic update
The last thing is to automate the grunt task execution when we add some dependencies.
We will use the grunt-contrib-watch
plugin :
npm install grunt-contrib-watch --save-dev
Then you edit the Gruntfile.js :
- Gruntfile.js
/*global module:false*/
module.exports = function (grunt) {
// Project configuration.
grunt.initConfig({
bowerInstall: {
target: {
src: [
'app/index.html' // .html support...
],
// Optional:
// ---------
cwd: '',
dependencies: true,
devDependencies: false,
exclude: [],
fileTypes: {},
ignorePath: '',
overrides: {}
}
},
watch: { (1)
files: ['bower.json'],
tasks: ['default'],
},
});
grunt.loadNpmTasks('grunt-contrib-watch');(2)
grunt.loadNpmTasks('grunt-bower-install');
// Default task.
grunt.registerTask('default', ['bowerInstall', 'watch']); (3)
};
- You add the task configuration, each time the bower.json is modified, we tell the plugin to run the default task
- We load the grunt plugin
- Then we add the watch after the bowerInstall execution, this way, the script will watch again for modifications.
So now, if you run the command :
- terminal 1
grunt
- terminal 2
bower install angular --save
The bowerInstall
grunt task is ran and the angular.js
dependency is added to the index.html
file …
- index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>My Cool Title</title>
<!-- bower:css -->
<link rel="stylesheet" href="../bower_components/bootstrap/dist/css/bootstrap.min.css" />
<link rel="stylesheet" href="../bower_components/bootstrap/dist/css/bootstrap-theme.min.css" />
<link rel="stylesheet" href="../bower_components/asciidoctor.js/dist/css/asciidoctor.css" />
<!-- endbower -->
</head>
<body>
<!-- bower:js -->
<script src="../bower_components/jquery/dist/jquery.js"></script>
<script src="../bower_components/bootstrap/dist/js/bootstrap.js"></script>
<script src="../bower_components/opal/opal/current/opal.js"></script>
<script src="../bower_components/asciidoctor.js/dist/asciidoctor-all.min.js"></script>
<script src="../bower_components/angular/angular.js"></script> (1)
<!-- endbower -->
</body>
</html>
The angular dependency automatically added.
Conclusion
Quite easy to do and very convenient !