Using Bundled Webpack Instance with Gradle
April 22nd, 2016
Using Bundled Webpack Instance with Gradle
Recently I was given the task to get a new project started from ground zero. This is the day I always dreaded since jumping into an existing project is easy but starting from scratch involves a lot of time just setting up the project scaffolding and creating a lot of configuration items. Oh and one more thing was tossed in: the build server doesn’t have node.js or npm (Node Package Manager) installed but we really wanted to use it. At this point I was thinking this is a not-so-fun situation but after researching how to do this, I found out not only is it possible but it actually makes sense to have your node.js and npm version defined in the build script so that the developers and build server are all using the same build tool versions. Not just that, but some places still have environments so locked down that developers still aren’t able to install applications. There are workarounds of course to this but a universal solution is talked about here.
For this example, I’m going to show you how to get node.js and npm installed via gradle. In a post coming up later, I’ll explain how I got react working with webpack to transcompile all my scripts for me, all with using gradle only and not needing to have node.js or npm globally installed. Let’s start with a simple Spring Boot application with a few modifications:
buildscript {
ext {
springBootVersion = '1.3.3.RELEASE'
}
repositories {
mavenCentral()
jcenter()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
classpath 'com.moowork.gradle:gradle-node-plugin:0.12'
}
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'spring-boot'
apply plugin: 'war'
apply plugin: "com.moowork.node"
node {
version = '5.8.0'
npmVersion = '3.8.0'
download = true
// distBaseUrl = Custom artifactory location here for node/npm.
}
war {
baseName = 'gradlenpm'
version = '0.0.1-SNAPSHOT'
}
sourceCompatibility = 1.8
targetCompatibility = 1.8
repositories {
mavenCentral()
}
configurations {
providedRuntime
}
dependencies {
compile('org.springframework.boot:spring-boot-starter-web')
providedRuntime('org.springframework.boot:spring-boot-starter-tomcat')
testCompile('org.springframework.boot:spring-boot-starter-test')
}
eclipse {
classpath {
containers.remove('org.eclipse.jdt.launching.JRE_CONTAINER')
containers 'org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8'
}
}
task wrapper(type: Wrapper) {
gradleVersion = '2.12'
}
clean.delete << file('node_modules')
A few things of note here:
To get node and npm downloaded, just run:
gradlew npmInstall
after the gradle items are setup and that’s it. That’s great and all but I haven’t given you enough to actually use it. Common tasks for npm are normally to install and delete dependencies. Let’s start with an empty package.json file in the root of our project:
[object Object]
If npm were installed, we could something like ”npm install –save angular
” or something similar. We can do this as well but we’d have to change to the node_modules/.bin directory and run the command. Now there are plenty of ways to solve this problem and this shouldn’t be taken gospel if you have a better idea. I tried really hard to get this to work via gradle but I ran into a lot of issues. One of the issues is that if you have bootRun running, you can’t run any gradle commands since it locks a gradle file. Not a huge deal but once I got it working, I found out it worked great by itself but then always ran before bootRun would start and then would fail since I added error checking which threw an error if the task wasn’t passed in the dependency parameter. Bummer. The gradle idea wasn’t too good though since gradle doesn’t handle command line parameters that well. I was running commands like “gradle npmInstallSave -Pdep=angular” and I would need to create a task for every common task or create longer command line arguments for a generic task. The -P arguments don’t exactly role off the fingers at all. The other solutions for this are to change to the directory or write a script. I went the script route and committed these to the root of the project.
Here are the super complex scripts to get this working (be kind and commit both):
Windows - npm.cmd
@echo off
echo Running Project Level npm
node_modules/.bin/npm.cmd %*
*nix - npm
#!/usr/bin/env bash
echo "Running Project Level npm"
node_modules/.bin/npm "$@"
Now I can run npm from the root of the project and use it as if the command was installed system wide. These simple scripts pass all the parameters you give it to the actual npm program. You can test it by running ”npm install -save angular`" and you should see the custom banner at top and also the package.json file should be updated. Full working example is available [here](https://github.com/Blastman/gradlenpm "Gradle nodeJS Example"). Check back later for another example showing how to use Webpack, React, and gradle together to compile and package javascript files with gradle.`
Using Bundled Webpack Instance with Gradle
In this second installment on the MEAN stack, we are going to complete an integration between a service layer module written in NodeJS, and MongoDB as our document persistence.
This blog assumes you are new to MEAN, and would like to install the components, and build your first MEAN application.
Jeff is a full stack developer with experience in the government/defense and finance industry. He has experience ranging from thick client Eclipse RCP programs to microservices using Spring Boot for data access and Elasticsearch. He enjoys learning about anything related to the IT field and has even managed Linux and Windows servers and setup deployment pipelines. He is a true believer in that if something is worth doing, then it’s worth doing right the first time and fully unit/integration tested.