Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Running NPM Scripts through maven

I am in the process of introducing single page applications to where I work. For development, using node based build tools is much easier for the single page applications. However, the build process for our organization is based upon maven. Our solution started with the maven plugin frontend-maven-plugin. It worked great at first, but then we ran into a situation that I couldn't make work with it.

As stated before, at our organization, we have the older ecosystem which is maven and the newer ecosystem which is node. Our goal was to keep the hacking to a minimum. We did this by putting all of the hacks into a single super node based build file. This is what maven calls and the reason frontend-maven-plugin wasn't sufficient. The super node based build script calls all of the other build scripts by spawning npm run. Try as I might, I could not figure out how to make the spawn work. front-end-maven-plugin downloads npm and calls it directly within itself and I was not able to fix my PATH to allow spawn to work.

The following files demonstrate our build process as of today. The gulp file has been simplified, but that part isn't important for this discussion. Gulp could be replaced with grunt or brocolli or anything else. The significant part is that maven calls npm scripts; how the npm script is defined doesn't matter. I included gulpfile.js to show how we use the skipTests flag

###References

var gulp = require( 'gulp' );
var gutil = require('gulp-util');
var argv = require('yargs').argv;
var del = require('del');
var mkdirp = require('mkdirp');
var touch = require('touch');
function stringToBoolean(string){
if(!string) {
return false;
}
switch(string.toLowerCase()) {
case "false": return false;
case "no": return false;
case "0": return false;
case "": return false;
case "true": return true;
default:
throw new Error("unknown string: " + string);
}
}
argv.skipTests = stringToBoolean(argv.skipTests);
/* TASKS */
gulp.task('clean', function(cb){
del(['./build'], cb);
});
gulp.task( 'build', function () {
mkdirp.sync('./build');
touch.sync('./build/index.html');
} );
gulp.task( 'test', function () {
if(argv.skipTests) {
gutil.log(gutil.colors.yellow('Skipping Tests'));
return;
}
gutil.log('Running Tests');
} );
gulp.task('prepare-for-maven-war', function(){
return gulp.src('./build/**')
.pipe(gulp.dest('target/gulp'));
});
{
"name": "npm-to-maven-adapator",
"version": "0.0.1-SNAPSHOT",
"description": "Example of node project with maven build scripts",
"private": true,
"scripts": {
"clean": "node node_modules/gulp/bin/gulp.js --no-color clean",
"build": "node node_modules/gulp/bin/gulp.js --no-color build",
"test": "node node_modules/gulp/bin/gulp.js --no-color test",
"prepare-for-maven-war": "node node_modules/gulp/bin/gulp.js --no-color prepare-for-maven-war"
},
"devDependencies": {
"del": "^1.1.1",
"gulp": "^3.8.11",
"gulp-util": "^3.0.1",
"mkdirp": "^0.5.0",
"touch": "0.0.3",
"yargs": "^1.3.3"
}
}
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>phillipgreenii</groupId>
<artifactId>npm-to-maven-adapator</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.test.skip>false</maven.test.skip>
<gulp.output.directory>target/gulp</gulp.output.directory>
</properties>
<build>
<plugins>
<!-- Standard plugin to generate WAR -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.1.1</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
<webResources>
<resource>
<directory>${gulp.output.directory}</directory>
</resource>
</webResources>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.3.2</version>
<executions>
<!-- Required: The following will ensure `npm install` is called
before anything else during the 'Default Lifecycle' -->
<execution>
<id>npm install (initialize)</id>
<goals>
<goal>exec</goal>
</goals>
<phase>initialize</phase>
<configuration>
<executable>npm</executable>
<arguments>
<argument>install</argument>
</arguments>
</configuration>
</execution>
<!-- Required: The following will ensure `npm install` is called
before anything else during the 'Clean Lifecycle' -->
<execution>
<id>npm install (clean)</id>
<goals>
<goal>exec</goal>
</goals>
<phase>pre-clean</phase>
<configuration>
<executable>npm</executable>
<arguments>
<argument>install</argument>
</arguments>
</configuration>
</execution>
<!-- Optional: The following will output the npm configuration.
I do this so my CI logs will show the npm information used
for the build -->
<execution>
<id>npm config list (validate)</id>
<goals>
<goal>exec</goal>
</goals>
<phase>validate</phase>
<configuration>
<executable>npm</executable>
<arguments>
<argument>config</argument>
<argument>list</argument>
</arguments>
</configuration>
</execution>
<!-- Required: This following calls `npm run build` where 'build' is
the script name I used in my project, change this if yours is
different -->
<execution>
<id>npm run build (compile)</id>
<goals>
<goal>exec</goal>
</goals>
<phase>compile</phase>
<configuration>
<executable>npm</executable>
<arguments>
<argument>run</argument>
<argument>build</argument>
</arguments>
</configuration>
</execution>
<!-- Optional: The following runs the script that copies the
appropriate files from the npm build directory into the location
'maven-war-plugin' is expecting. The copying could be done
during the 'build' script, but I like to keep it separate.
Idealy in the future, I won't need maven at which, I can just
delete the 'prepare-for-maven-war' script. -->
<execution>
<id>npm run prepare-for-maven (prepare-package)</id>
<goals>
<goal>exec</goal>
</goals>
<phase>prepare-package</phase>
<configuration>
<executable>npm</executable>
<arguments>
<argument>run</argument>
<argument>prepare-for-maven-war</argument>
</arguments>
</configuration>
</execution>
<!-- Optional: The following will publish to npm if you run
`mvn deploy`. -->
<execution>
<id>npm run publish (deploy)</id>
<goals>
<goal>exec</goal>
</goals>
<phase>deploy</phase>
<configuration>
<executable>npm</executable>
<arguments>
<argument>publish</argument>
</arguments>
</configuration>
</execution>
<!-- Required: The following will run unit tests. My test scripts
in npm look for the property 'skipTests', so I map it to
'maven.test.skip'
Note: the douple '-' syntax used below only works with npm >= 2. -->
<execution>
<id>npm run test (test)</id>
<goals>
<goal>exec</goal>
</goals>
<phase>test</phase>
<configuration>
<executable>npm</executable>
<arguments>
<argument>run</argument>
<argument>test</argument>
<argument>--</argument>
<argument>--skipTests=${maven.test.skip}</argument>
</arguments>
</configuration>
</execution>
<!-- Required: The following calls the npm script that cleans
up the build. -->
<execution>
<id>npm run clean (clean)</id>
<goals>
<goal>exec</goal>
</goals>
<phase>clean</phase>
<configuration>
<executable>npm</executable>
<arguments>
<argument>run</argument>
<argument>clean</argument>
</arguments>
</configuration>
</execution>
</executions>
<configuration>
<environmentVariables>
<!-- The following parameters create an NPM sandbox for CI -->
<NPM_CONFIG_PREFIX>${basedir}/npm</NPM_CONFIG_PREFIX>
<NPM_CONFIG_CACHE>${NPM_CONFIG_PREFIX}/cache</NPM_CONFIG_CACHE>
<NPM_CONFIG_TMP>${project.build.directory}/npmtmp</NPM_CONFIG_TMP>
</environmentVariables>
</configuration>
</plugin>
</plugins>
</build>
</project>
@ben-bourdin451

This comment has been minimized.

Copy link

ben-bourdin451 commented Apr 20, 2017

This was super useful, thank you! 😄

@celsoagra

This comment has been minimized.

Copy link

celsoagra commented Mar 9, 2018

Awesome!
Thanks a lot

@nicolaisueper

This comment has been minimized.

Copy link

nicolaisueper commented Mar 20, 2018

Thanks for the good example 💖

@pvpkiran

This comment has been minimized.

Copy link

pvpkiran commented Apr 19, 2018

Nice one. Helped a lot.
Thanks

@narendrakumarachari

This comment has been minimized.

Copy link

narendrakumarachari commented Jul 11, 2018

Good one - Helpful

@edcolcode

This comment has been minimized.

Copy link

edcolcode commented Aug 1, 2018

Amazing, thanks for share.

@techieBrandon

This comment has been minimized.

Copy link

techieBrandon commented Dec 8, 2018

Great integration hooks.

@mahajay

This comment has been minimized.

Copy link

mahajay commented Aug 26, 2019

I am looking for executing my npm script on different environments. For each of the environments I have different set of values. I can do it locally something like this
npm --my-module:env=dev start
But, I need to do it as part of my maven build running on Jenkins.

Please let me know if you need more information.

@jing2020

This comment has been minimized.

Copy link

jing2020 commented Aug 30, 2019

pom.xml is very helpful for my vue app

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.