Javascript Package Management – NPM – Bower – Grunt

posted by Roberto Cortez on

When I was writing my previous post about Java EE and Angular, I was overwhelmed with all the javascript files that I needed to include in my application to implement the behaviour that I was looking for. OK, not that many scripts actually, four in total: Angular JS (Angular also requires jQuery), ng-grid and UI Bootstrap. Unfortunately, it was not so simple. Each script, may also need a CSS file and some of the scripts depended on different versions from each others. Finally, I also needed to include all the files in my index.html. For that particular post, I ended up doing everything manually and it was a real pain. There must be a better way!

The Problem

In Java, whether you like it or not, Maven is the number one tool to perform this kind of management, but what about Javascript? I’m far from an expert, so after asking our friend Google about it, I was a bit surprised with the amount of existent tools to do the job and for a newcomer this seemed complicated and lacking a common solution generally accepted by the community. Here are a couple of interesting posts about the problem:

Which solution?

I was not exactly sure which tool should I use, so after a few talks with a couple of colleagues that were working in Javascript applications they recommended NPM-Bower-Grunt combo:

  • NPM
  • NPM stands for Node Package Manager. Sounds weird, since we are not developing a Node.js application here, but we need NPM to use Bower and Grunt.

  • Bower
  • Bower is a package manager for the web. It will manage all your web files: javascript, css and images.

  • Grunt
  • Grunt is a task-based command line build tool for JavaScript projects.

Both Bower and Grunt are Node.js packaged modules and we only need NPM to download them. Bower is going to be responsible to download and manage all the javascript dependencies for our web application. Finally, Grunt will automate the task for adding the correct tags to the html files. Actually, Grunt also have tasks to concatenate and minify multiple files in a single one. This is useful to improve the performance of your application in production environments, but it was not may main focus.

The Setup

Paulo Grácio, a very good friend of mine that I work with, was kind enough to pick up my Java EE Angular sample on Github and setup everything needed to provide the application with Javascript Package Management. Thank you so much Paulo!

Maybe it’s a stupid comparison, but I’ll try to establish parallels with Java Maven build, to help people like me that are used to Maven to better understand what’s going on.

Install NPM

The pre-built installer of Node.js is all you need to have NPM up and running on your machine, but I actually followed this post to install NPM using Homebrew on OS X.

Now we need a package.json file in the root project folder. We are using this one:

In this file, you can find the node settings for your project. The most interesting stuff here is the devDependencies definition. Here you can find the Grunt task to download the project dependencies (grunt-bower-install-simple) and the task to inject the scripts and css in the index.html (grunt-wiredep). This is similar to the plugins definitions in a Maven pom.xml file. Running npm install should download everything you need to start using Grunt and the project tasks.

Managing Web Packages with Bower

Now we need to tell Bower which packages we want to include in the project. Add a file named bower.json in the root project folder:

Remember the original problem? Manage Angular, jQuery, ng-grid and UI Bootstrap dependencies? Here we have the definitions. I can compare it again like being a bit similar to the dependencies section in a Maven pom file for a Java project. Just a small detail, Bower uses Convention-over-Configuration to define project paths. This is important because the default location to download the javascript packages does not follow the Maven folder layout, so we should change Bower path to match Maven web app layout. To fix this, we need to add a file named .bowerrc to the project root folder:

Defining Grunt Tasks

To glue everything together, we use Grunt to run the different tasks, but first we need to add another file to the project root folder, Gruntfile.js:

For this file, we are just adding configurations to each Grunt task. We can also assemble all the tasks together to run in our own defined task named build or default. This is like defining our own Maven build lifecycle (which is not possible in Maven) and configuring the plugins settings. So, we actually have plugins (tasks) definitions in one file (package.json) and plugins (tasks) settings in a separate file (Gruntfile.js).

There is one more thing to do: we need to add a few special placeholders into our HTML files so that the Grunt tasks can add Javascript and CSS files automatically, based on Bower dependencies. For this project we have an unique index.html file and the head section should look like this:

The <!-- bower:css --> marks the location in the html file where the css files dependencies must be inserted and <!-- build:css css/third-party.css --> is used to indicate the merged file with all the css code. For <!-- bower:js --> and <!-- build:js lib/third-party.js --> it works the some way. Note that we have separated the external files from the own application files.

Final Structure

The project structure result is the following:

NPM-Bower-Grunt Structure

Executing Grunt Tasks

After all this setup, we are finally ready to execute Grunt tasks and have our web files managed! So, going from the start, we execute from the command line in the project folder root:

npm install

followed by

npm install -g grunt-cli



You will notice the following:

  • A node_modules folder is created with all of the Bower and Grunt dependencies.
  • A src/main/webapp/lib/bower folder is created with all of the web application dependencies (Angular, jQuery, ng-grid and UI Bootstrap).
  • The src/main/webapp/index.html file is injected with the needed Javascript and CSS files.
  • A build folder is generated with an optimised version of the web application (files concatenated and minified).

The end result:

NMP-Bower-Grunt Result

You can also execute individual Grunt tasks:

grunt bower – Downloads the web application dependencies.
grunt bowerInstall – Modifies and inject the required files in your index.html.


You can find the updated Java EE 7 – Angular JS example with Javascript Package Management in Github, here. For the moment it’s in a branch but we intend to merge it with the original example.

In the meanwhile I have merged this code with the original example. Please, download the original source of this post from the release 2.0. You can also clone the repo, and checkout the tag from release 2.0 with the following command: git checkout 2.0.

Final Thoughts

Uff! It was not easy to do this. A lot of files to add and to configure and a lot of tools to study. Maybe there is an easier way to accomplish the same using other existent setups and tools in the Javascript landscape. I cannot tell you this is the best, since I would have to setup all the other solutions around the Javascript landscape, but this is a possible approach and it works. Just a couple of weeks after working on this, I found the following:

And just like that Grunt and RequireJS are out, it’s all about Gulp and Browserify now

Don’t get me wrong, but I feel that the Javascript landscape is popping build tools like mushrooms. In my opinion it would be better to have a single standardised tool that everyone could use. Let’s see what is going to happen in the future.

Probably it could also be easier to use Yeoman to generate the structure, but we also wanted to learn more about the individuals tools, and I think you learn a bit more by doing things manually the first couple of times.

A Special Thanks

To Paulo Grácio for updating the Java EE 7 – Angular JS sample with all this setup! Thank you Paulo!

Comments ( 17 )

  1. ReplyYeroc

    If you’re using Maven (or another Java-based build tool) already then the easiest thing is just to use WebJars ( Just add your Javascript libraries as dependencies on your project and you’re done! Slick and easy. It’s a bit more work if you want to minify etc. For that consider something like wro4j (which will also work with WebJars).

    Again, this only applies if you’re combining a Java-based project with some Javascript client-side code.

    • ReplyRoberto Cortez

      Hi Yerow,

      Thank you for the tip. Actually I was not aware of WebJars until after I wrote the article and for some reason I didn’t find it when I was looking for possible solutions, but probably I didn’t look for combining Java, Javascript and Maven.

      Anyway, thanks again for the tip 🙂

    • Replyg00glen00b

      WebJars may look like a good solution, but it usually isn’t. If you’re working at projects involving modern web development using JavaScript, frameworks like AngularJS/Backbone/Ember.js/.. and a CSS preprocessor like Sass or Less, then you need more than just some front-end dependency management. You need a real buildplatform capable of building, minifying, compiling, template processing, JSHint/Lint validation, unit testing (Karma?), … .

      When you need such an environment, Maven is no longer no longer the best option. Of course, it has some support through plugins like wro4j, but many of these things feel as if you’re doing exotic stuff (like processing AngularJS templates), but with Gulp or Grunt they’re common and you can do a lot more stuff with them (unit testing with karma is for example a lot better and more configurable than the Maven Jasmine plugins I’ve seen).

      It’s also an upcoming trend. If you look at platform like JHipster (, you can see that they provide a Yeoman generator for a Spring Boot (Java) + AngularJS (JavaScript) application. And what does this platform use? Gulp/Grunt and Bower for front-end building and Maven for building the Java code.

      • ReplyRoberto Cortez

        Hi g00glen00b,

        Thank you for your very informative comment. I had no idea that Webjars existed when I was working the sample, so probably I would have use them if I knew about them. I still have in my TODO list to write a version of the sample using Webjars.

        I had no idea of the benefits or limitations of Webjards, but I do believe you. Usually when you try to use a tool (Maven) with an idea in mind to do other things that it was not intended to do, it can be a pain.

  2. Replyadben

    Nice post thanks!
    This is an angularJS in a maven project? I think the best way is using yeoman[1] for the frontend to manage all your scaffolding configuration regarding node, grunt and bower (and more.. just take a look at the features in the website) and then glue everything with the backend with this yeoman-maven plugin (hooks the maven cycles with the node-grunt-bower, ideal for the javascript unit testing into your CI server with phamtomJS)


    • ReplyRoberto Cortez

      Hi adben,

      Yes, this is an AngularJs + Java EE + Maven project. I did look into Yeoman, and I actually reference it in the end. I did choose to not use Yeoman for this, because I wanted to understand a bit more about NPM, Bower and Grunt individually.

      Anyway, thanks a lot for the tip. I do intend to try Yeoman 🙂

  3. Replypjrgracio

    It’s always a pleasure to collaborate with you, great article! Thank you for getting me on board for this challenge 🙂

    • ReplyRoberto Cortez

      It was my pleasure. Let’s think on something else next 🙂

  4. ReplyAdrian Meredith


    Do you know how to setup wildfly so that grunt can autodeply web resources? We do this with glassfish pretty easily (you just copy the files) but wildfly doesn’t seem to auto expand the ear file on the deployment as far as I can see.

    • ReplyRoberto Cortez

      Hi Adrian,

      When building a ear or war project, Maven target folder will contain the file itself and also an exploded version. You should copy the exploded application folder to the Wildfly instance into standalone/deployments and add the proper extension (war or ear). To finish the deploy, you also need to create a file [foldername].[ear|war].dodeploy. You should be able to copy the files directly there. An alternative is to use JRebel which reload your resources from your source code.


  5. Replykenw

    I’ve had a lot of headaches with npm and grunt (mismatched version dependencies, missing files, etc). Just started using WebJars with Maven and it seems to be working very well. My advice for Java+AngularJS projects: use Maven and WebJars.

    • ReplyRoberto Cortez

      Hi kenw,

      Thank you for your comment. A few other people also mentioned me to use WebJars instead. I’ll put that on my TODO list and update the sample to use web jars.


  6. Replydude

    Your blog is not zoomable (on chrome 41.0) – usability flaw

  7. ReplyThuc

    I followed your steps but at the final i got an error when i ran command “grunt”, please help.


    Running “clean:build” (clean) task

    Running “bower-install-simple” task
    Install Bower Dependencies
    bower error Arguments to path.join must be strings

    Stack trace:
    TypeError: Arguments to path.join must be strings
    at Object.win32.join (path.js:233:13)
    at Project._readInstalled (d:\Temp\javaee7-angular\node_modules\grunt-bower-install-simple\node_modules\bower\lib\core\Project.js:589:26)
    at Project._analyse (d:\Temp\javaee7-angular\node_modules\grunt-bower-install-simple\node_modules\bower\lib\core\Project.js:461:14)
    at Project.install (d:\Temp\javaee7-angular\node_modules\grunt-bower-install-simple\node_modules\bower\lib\core\Project.js:48:17)
    at install (d:\Temp\javaee7-angular\node_modules\grunt-bower-install-simple\node_modules\bower\lib\commands\install.js:27:20)
    at d:\Temp\javaee7-angular\node_modules\grunt-bower-install-simple\node_modules\bower\lib\commands\index.js:21:32
    at Promise.apply (d:\Temp\javaee7-angular\node_modules\grunt-bower-install-simple\node_modules\bower\node_modules\q\q.js:1078:26)
    at Promise.promise.promiseDispatch (d:\Temp\javaee7-angular\node_modules\grunt-bower-install-simple\node_modules\bower\node_modules\q\q.js:741:41)
    at d:\Temp\javaee7-angular\node_modules\grunt-bower-install-simple\node_modules\bower\node_modules\q\q.js:1304:14
    at flush (d:\Temp\javaee7-angular\node_modules\grunt-bower-install-simple\node_modules\bower\node_modules\q\q.js:108:17)

    Console trace:
    at StandardRenderer.error (d:\Temp\javaee7-angular\node_modules\grunt-bower-install-simple\node_modules\bower\lib\renderers\StandardRenderer.js:82:17)
    at Logger. (d:\Temp\javaee7-angular\node_modules\grunt-bower-install-simple\tasks\grunt-bower-install-simple.js:81:22)
    at Logger.emit (events.js:107:17)
    at Logger.emit (d:\Temp\javaee7-angular\node_modules\grunt-bower-install-simple\node_modules\bower\node_modules\bower-logger\lib\Logger.js:29:39)
    at d:\Temp\javaee7-angular\node_modules\grunt-bower-install-simple\node_modules\bower\lib\commands\index.js:40:20
    at _rejected (d:\Temp\javaee7-angular\node_modules\grunt-bower-install-simple\node_modules\bower\node_modules\q\q.js:797:24)
    at d:\Temp\javaee7-angular\node_modules\grunt-bower-install-simple\node_modules\bower\node_modules\q\q.js:823:30
    at Promise.when (d:\Temp\javaee7-angular\node_modules\grunt-bower-install-simple\node_modules\bower\node_modules\q\q.js:1035:31)
    at Promise.promise.promiseDispatch (d:\Temp\javaee7-angular\node_modules\grunt-bower-install-simple\node_modules\bower\node_modules\q\q.js:741:41)
    at d:\Temp\javaee7-angular\node_modules\grunt-bower-install-simple\node_modules\bower\node_modules\q\q.js:509:49

    System info:
    Bower version: 1.3.12
    Node version: 0.12.4
    OS: Windows_NT 6.3.9600 x64
    Warning: Task “bower-install-simple” failed. Use –force to continue.

    Aborted due to warnings.

    Execution Time (2015-06-09 08:00:59 UTC)
    bower-install-simple 805ms ██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████ 98%
    Total 819ms

  8. ReplyeHowToNow


Leave a reply

Your email address will not be published.

You may use these HTML tags and attributes:

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>