Integrating A Maven-Backend- With A Nodjs/Grunt-Fronted-Project
Frontend-Development With Nodjs and Grunt
As I already wrote in a previous article, frontend-development is mostly done with Nodjs and Grunt nowadays. As I am planing to base the frontend of my next Spring-Application on Bootstrap, I was looking for a way to integrate my backend, which is build using Spring and Thymeleaf and managed with Maven, with a frontend, which is based on Bootstrap and, hence, build with Nodjs and Grunt.
Integrate The Frontend-Build Into The Maven-Build-Process
As I found out, one can integrate a npm-based build into a maven project with the help of the frontend-maven-plugin. This plugin automates the managment of Nodjs and its libraries and ensures that the version of Node and NPM being run is the same in every build environment. As a backend-developer, you do not have to install any of the frontend-tools manualy. Because of that, this plugin is ideal to integrate a separately developed frontend into a maven-build, without bothering the backend-developers with details of the frontend-build-process.
Seperate The Frontend-Project From The Maven-Based Backend-Project
The drawback with this approach is, that the backend- and the frontend-project are tightly coupled.
You can configure the frontend-maven-plugin to use a separate subdirectory as working-directory (for example src/main/frontend
) and utilize this to separate the frontend-project in its own repository (for example by using the submodule-functions of git).
But the grunt-tasks, that you call in the frontend-project through the frontend-maven-plugin, must be defined in that project.
Since I am planing to integrate a ‐ slightly modified ‐ version of Bootstrap as frontend into my project, that would mean that I have to mess around with the configuration of the Bootstrap-project a lot. But that is not a very good idea, because it hinders upgrades of the Bootstrap-base, because merge-conflicts became more and more likely.
So, I decided to program a special Gruntfile.js
, that resides in the base-folder of my Maven-project and lets me redefine and call tasks of a separated frontend-project in a subdirectory.
Redefine And Call Tasks Of An Included Gruntfile From A Sub-Project
As it turned out, there are several npm-plugins for managing and building sub-projects (like grunt-subgrunt or grunt-recurse) or including existing Gruntfiles from sub-projects (like grunt-load-gruntfile), but none of them lets you redefine tasks of the subproject before calling them.
I programmed a simple Gruntfile, that lets you do exactly this:
module.exports = function(grunt) {
grunt.loadNpmTasks('grunt-newer');
grunt.registerTask('frontend','Build HTML & CSS for Frontend', function() {
var
done = this.async(),
path = './src/main/frontend';
grunt.util.spawn({
cmd: 'npm',
args: ['install'],
opts: { cwd: path, stdio: 'inherit' }
}, function (err, result, code) {
if (err || code > 0) {
grunt.fail.warn('Failed installing node modules in "' + path + '".');
}
else {
grunt.log.ok('Installed node modules in "' + path + '".');
}
process.chdir(path);
require(path + '/Gruntfile.js')(grunt);
grunt.task.run('newer:copy');
grunt.task.run('newer:less');
grunt.task.run('newer:svgstore');
done();
});
});
grunt.registerTask('default', [ 'frontend' ]);
};
This Gruntfile loads the npm-taks grunt-newer.
Then, it registers a grunt-task called frontend
, that loads the dependencies of the specified sub-project, read in its Gruntfile and runs redefined versions of the tasks copy
, less
and svgstore
, which are defined in the sub-project.
The sub-project itself does not register grunt-newer itself.
This is done in this parent-project, to demonstrate how to register additional grunt-plugins and redefine tasks of the sub-project without touching it at all.
The separated frontend-project can be used by the frontend-team to develop the temlates, needed by the backend-developers, without any knowledge of the maven-project. The frontend-project is then included into the backend, which is managed by maven, and can be used by the backend-developers without the need to know anything about the techniques that were used to develop the templates.
The whole example can be browsed at juplo.de/gitweb or cloned with:
git clone http://juplo.de/git/examples/maven-grunt-integration
Be sure to checkout the tag 2.0.0
for the corresponding version after the cloning, in case i add more commits to demonstrate other stuff.
Also, you have to init and clone the submodule after checkout:
git submodule init
git submodule update
If you run mvn jetty:run
, you will notice, that the frontend-maven-plugin will automatically download Nodejs into a the folder node
of the parent-project.
Afterwards, the dependencies of the parent-project are downloaded in the folder node_modules
of the parent-project and the dpendencies of the sub-project are downloaded in the folder src/main/frontend/node_modules
and the sub-project is build automatically in the folder src/main/frontend/dist
, which is included into the directory-tree that is served by the jetty-maven-plugin.
The sub-project is fully usable standalone to drive the development of the frontend separately. You can read more about it in this previous article.
Conclusion
In this article, I showed how to integrate a separately developed frontend-project into a backend-project managed by Maven. This enables you to separate the development of the layout and the logic of a classic ROCA-project nearly totally.
Leave a Reply