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.

Serving Static HTML With Nodjs And Grunt For Template-Development

A Simple Nodejs/Grunt-Development-Environment for static HTML-Templates

Nowadays, frontend-development is mostly done with Nodjs and Grunt.
On npm, there are plenty of useful plugin’s, that ease the development of HTML and CSS.
For example grunt-contrib-less to automate the compilation of LESS-sourcecode to CSS, or grunt-svgstore to pack several SVG-graphics in a single SVG-sprite.

Because of that, I decided to switch to Nodejs and Grunt to develop the HTML- and CSS-Markup for the templates, that I need for my Spring/Thymeleaf-Applications.
But as with everything new, I had some hard work, to plug together what I needed.
In this article I want to share, how I have set up a really minimalistic, but powerful development-environment for static HTML-templates, that suites all of my initial needs.

This might not be the best solutions, but it is a good starting point for beginners like me and it is here to be improved through your feedback!

You can browse the example-development-environment on juplo.de/gitweb, or clone it with:


git clone http://juplo.de/git/examples/template-development

After installing npm you have to fetch the dependencies with:


npm install

Than you can fire up a build with:


grunt

…or start a webserver for development with:


git run-server

Serving The HTML and CSS For Local Development

The hardest part while putting together the development-environment was my need to automatically build the static HTML and CSS after file-changes and serve them via a local webserver.
As I wrote in an earlier article, I often stumble over problems, that arise from the Same-origin policy when accessing the files locally through file:///-URI’s).

I was a bit surprised, that I could not find a simple explanation, how to set up a grunt-task to build the project automatically on file-changes and serve the generated HTML and CSS locally.
That is the main reason, why I am writing this explanation now, in order to fill that gap ;)

I realised that goal by implemnting a grunt-task, that spawn’s a process that uses the http-server to serve up the files and combine that task with a common watch-task:


grunt.registerTask('http-server', function() {

  grunt.util.spawn({
    cmd: 'node_modules/http-server/bin/http-server',
    args: [ 'dist' ],
    opts: { stdio: 'inherit' }
  });

});

grunt.registerTask('run-server', [ 'default', 'http-server', 'watch' ]);

The rest of the configuration is really pretty self-explaining.
I just put together the pieces I needed for my template development (copy some static HTML and generate CSS from the LESS-sources) and configured grunt-contrib-watch to rebuild the project automatically, if anything changes.

The result is put under dist/ and is ready to be included in my Spring/Thymeleaf-Application as it is.

Bypassing the Same-Origin-Policy For Local Files During Development

downloadable font: download failed …: status=2147500037

Are you ever stumbled accross weired errors with font-files, that could not be loaded, or SVG-graphics, that are not shown during local development on your machine using file:///-URI’s, though everything works as expected, if you push the content to a webserver and access it via HTTP?
Furthermore, the browsers behave very differently here.
Firefox, for example, just states, that the download of the font failed:


downloadable font: download failed (font-family: "XYZ" style:normal weight:normal stretch:normal src index:0): status=2147500037 source: file:///home/you/path/to/font/xyz.woff

Meanwhile, Chrome just happily uses the same font.
Considering the SVG-graphics, that are not shown, Firefox just does not show them, like it would not be able to at all.
Chrome logs an error:


Unsafe attempt to load URL file:///home/you/path/to/project/img/sprite.svg#logo from frame with URL file:///home/you/path/to/project/templates/layout.html. Domains, protocols and ports must match

…though, no protocol, domain or port is involved.

The Same-Origin Policy

The reason for this strange behavior is the Same-origin policy.
Chrome gives you a hint in this direction with the remark that something does not match.
I found the trail, that lead me to this explanation, while googling for the strange error message, that Firefox gives for the fonts, that can not be loaded.


The Same-origin policy forbids, that locally stored files can access any data, that is stored in a parent-directory.
They only have access to files, that reside in the same directory or in a directory beneath it.

You can read more about that rule on MDN.

I often violate that rule, when developing templates for dynamically rendered pages with Thymeleaf, or similar techniques.
That is, because I like to place the template-files on a subdirectory of the directory, that contains my webapp (src/main/webapp with Maven):


+ src/main/webapp/
  + css/
  + img/
  + fonts/
  + thymeleaf/templates/

I packed a simple example-project for developing static templates with LESS, nodejs and grunt, that shows the problem and the quick solution for Firefox presented later.
You can browse it on my juplo.de/gitweb, or clone it with:


git clone http://juplo.de/git/examples/template-development

Cross-Browser Solution

Unfortunately, there is no simple cross-browser solution, if you want to access your files through file:///-URI’s during development.
The only real solution is, to access your files through the HTTP-protocol, like in production.
If you do not want to do that, the only two cross-browser solutions are, to

  1. turn of the Same-origin policy for local files in all browsers, or
  2. rearrange your files in such a way, that they do not violate the Same-origin policy (as a rule, all resources linked in a HTML-file must reside in the same directory as the file, or beneath it).

The only real cross-browser solution is to circumvent the problem altogether and serve the content with a local webserver, so that you can access it through HTTP, like in production.
You can read how to extend the example-project mentioned above to achieve that goal in a follow up article.

Turn Of Security

Turning of the Same-origin policy is not recommended.
I would only do that, if you only use your browser, to access the HTML-files under development ‐ which I doubt, that it is the case.
Anyway, this is a good quick test to validate, that the Same-origin policy is the source of your problems ‐ if you quickly re-enable it after the validation.

Firefox:
Set security.fileuri.strict_origin_policy to false on the about:config-page.
Chrome:
Restart Chrome with --disable-web-security or --allow-file-access-from-files (for more, see this question on Stackoverflow).

Quick Fix For Firefox

If you develop with Firefox, there is a quick fix, to bypass the Same-origin policy for local files.

As the explanation on MDM stats, a file loaded in a frame shares the same origin as the file, that contains the frameset.
This can be used to bypass the policy, if you place a file with a frameset in the topmost directory of your development-folder and load the template under development through that file.

In my case, the frameset-file looks like this:


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">
<html>
  <head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8">
    <title>Frameset to Bypass Same-Origin-Policy
  </head>
  <frameset>
    <frame src="thymeleaf/templates/layout.html">
  </frameset>
</html>

Replace text by graphic without extra markup

Here is a little trick for you, to replace text by a graphic through pure CSS without the need to add extra markup:


SELECTOR
{
  text-indent: -99em;
  line-height: 0;
}
SELECTOR:after
{
  display: block;
  text-indent: 0;
  content: REPLACEMENT;
}

SELECTOR can be any valid CSS-selector.
REPLACEMENT references the graphic, which should replace the text.
This can be a SVG-graphic, a vector-graphics from a font, any bitmap graphic or (quiet useless, but a simple case to understand the source like in the first of my two examples) other text.
SVG- and bitmap-graphics are simply referred by an url in the content-directive, like I have done it with a data-url in my second example.
For the case of an icon embedded in a vector you simply put the character-code of the icon in the content-directive, like described in the according ALA-article.

Examples

  1. Example 1
  2. Example 2

What is it good for?

If you need backward compatibility for Internet Explorer 8 and below or Android 2.3 and below, you have to use icon-fonts to support these old browsers.
I use this often, if I have a brand logo, that should be inserted in a accessible way and do not want to bloat up the html-markup with useless tag’s, to achieve this.