Fork me on Github

Combining the Angular 2 Profile Projects

This guide will take you through the process of creating a single build starting with the Angular 2 profile.

Authors: James Kleeh

Grails Version: 3.2.8

1 Getting Started

The Angular 2 profile in Grails 3 provides a multi project build out of the box. Today there are many options for how to build and package your applications. It is important to decide for yourself what is best for your needs. For those who prefer to have the client side application bundled together with their Grails application, this guide is for you. In this guide I will cover some quick simple steps to get up and running with a combined project starting from the multi project build created from the Angular 2 profile.

1.1 What you will need

To complete this guide, you will need the following:

  • Some time on your hands

  • A decent text editor or IDE

  • JDK 1.7 or greater installed with JAVA_HOME configured appropriately

1.2 How to complete the guide

To complete this guide, you will need to checkout the source from Github and work through the steps presented by the guide.

To get started do the following:

You can go right to the completed example if you cd into grails-guides/angular2-combined/complete

2 Writing the Application

2.1 Combining the Applications

Since a single project is desired, the settings.gradle file is no longer necessary.

rm -f settings.gradle

Move all of the contents of server to the current directory

mv server/* ./

Delete the server directory

rm -r server

Move the client directory to the src/main directory

mv client src/main/

Delete the no longer used build.gradle file in the client directory

rm -f src/main/client/build.gradle

Now you have a single Grails project with the client side application living in src/main/client!

2.2 Combining the Builds

It would be ideal if the application would just "work" by executing run-app similar to how typical Grails applications with the web profile do. In order to achieve that, additional configuration is required.

To support the build process, first we need to add some NPM scripts. Add the following to the package.json file.

src/main/client/package.json
{
  ...
  "scripts": {
    "build": "ng build --prod",
    "buildDev": "ng build",
    "buildWatch": "ng build --watch=true",
  ...
}

The next step is to add the Gradle Node Plugin.

build.gradle
buildscript {
    dependencies {
        classpath "com.moowork.gradle:gradle-node-plugin:1.0.1"
    }
}

apply plugin:"com.moowork.node"

Now that we have the plugin, we need to configure it and use it to create some tasks to hook into the build process of the Grails application.

build.gradle
node {
    version = '6.9.1'
    download = true
    nodeModulesDir = file("src/main/client")
}

task buildClientDev(type: NpmTask, dependsOn: 'npmInstall') {
    group = 'build'
    description = 'Compile client side assets for development'
    args = ['run', 'buildDev']
}

task buildClient(type: NpmTask, dependsOn: 'npmInstall') {
    group = 'build'
    description = 'Compile client side assets for production'
    args = ['run', 'build']
}

task buildClientWatch(type: NpmTask, dependsOn: 'npmInstall') {
    group = 'application'
    description = 'Builds and watches the client side assets for rebuilding'
    args = ['run', 'buildWatch']
}

task clientTest(type: NpmTask, dependsOn: 'npmInstall') {
    group = 'verification'
    description = 'Executes client side unit tests'
    args = ['run', 'test']
}

task clientIntegrationTest(type: NpmTask, dependsOn: 'npmInstall') {
    group = 'verification'
    description = 'Executes client side integration tests'
    args = ['run', 'e2e']
}

bootRun.dependsOn(buildClientDev)

war.dependsOn(buildClient)

test.dependsOn(clientTest)

integrationTest.dependsOn(clientIntegrationTest)

clean {
    delete fileTree(dir: "src/main/webapp")
}

2.3 Changing Configuration

We need to change where the client side assets will be stored after they are built and bundled. Modify the apps.outDir setting to point to the webapp folder.

src/main/client/angular-cli.json
...
  "apps": [
    {
      "root": "src",
      "outDir": "../webapp",
...

Because CORS is no longer a requirement of this application, it should be turned off in configuration. Find grails.cors.enabled and remove the configuration or set it to false.

grails-app/conf/application.yml
grails:
    cors:
        enabled: false

In order to resolve our index.html without the /static prefix, it is necessary to set the resources pattern.

grails-app/conf/application.yml
grails:
    resources:
        pattern: /**

When a user vists your page, it should direct them to the client side application. By default in a rest-api application, it will show some metadata about your application. To change that behavior, modify UrlMappings.groovy.

grails-app/controllers/angular2/combined/UrlMappings.groovy
"/"(uri: "/index.html")

3 Running the Application

That is everything required to combine the Angular 2 multi project build into a single project.

To run the application use the ./gradlew bootRun command which will start the application on port 8080.

4 Do you need help with Grails?

OCI sponsored the creation of this Guide. OCI offers several Grails services:

OCI Grails Team includes Grails co-founder and the core development team. Gain access to the engineers who developed, matured and maintain Grails

Grails OCI Team