Skip to content

Instantly share code, notes, and snippets.

@halkhalil
Forked from phillipgreenii/README.md
Created August 5, 2017 10:31
Show Gist options
  • Save halkhalil/f4f153122e25dbaa5cabec4657257ae8 to your computer and use it in GitHub Desktop.
Save halkhalil/f4f153122e25dbaa5cabec4657257ae8 to your computer and use it in GitHub Desktop.
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment