gradle-node-plugin icon indicating copy to clipboard operation
gradle-node-plugin copied to clipboard

How to correctly configure multi project builds for spring boot?

Open cbtum opened this issue 2 years ago • 2 comments

Thanks for this plugin and for your example shown in https://github.com/node-gradle/gradle-node-plugin/tree/master/examples/spring-boot-angular.

While my current setup already triggers some npm tasks and compiles without any problem, localhost:8080 still shows some json with my spring repositories/ data structures instead of the angular app. The only way to use my angular app is ng serve on localhost:4200 and annotate @CrossOrigin(origins = "http://localhost:4200") in the controllers.

May I ask some questions regarding this problem / related to your example:

  • Is it really correct to have the spring application on the root level while the webapp is a subproject? From the gradle documentation (https://docs.gradle.org/current/userguide/multi_project_builds.html), I actually expected a more parallel structure without any src folder on the root level and rather two subprojects spring and webapp in parallel. In case both structures are possible, how do I configure the gradle-node-plugin to handle this parallel structure?
  • Is gradle-node-plugin actually intended to also support local development of an angular app, i.e. are angular sources updated automatically under localhost:8080 just as I am used to it with ng serve under localhost:4200? If that is possible, I could actually remove the @CrossOrigin(origins = "http://localhost:4200") annotation in my controllers, right?

Any help is much appreciated, thanks in advance!

PS: I think part of the problem might be that in a parallel setup (spring and webapp as subprojects, no src folder on root level), webapp has it's own build-folder and hence the static resources are not copied into the output of spring???

cbtum avatar Feb 24 '22 22:02 cbtum

Some of these would be specific to your environment, but to get rid of CrossOrigin you might be interested in something like webpacks devServer.proxy to serve your JS and proxy to your webapp.

But in short, this plugin is to get node and npm to fit into your Gradle project, it doesn't add anything beyond the ability to integrate these so it would rely on your own setup.

I fully agree with you, two subprojects is generally a good fit here, it is possible to have both the webapp and the spring project in the same project but I find two subprojects much cleaner. The example is using the root project and one subproject just for simplicity.

As for local development it is certainly possible to use the plugin for that, setting up tasks matching your node build and using that to develop but I find that a lot of people prefer to work directly with local installations and node "native" tools when they work on the UI (for hot-reloading and similar).

So for the example the way it works is described in the README

The webapp is built and added into the Jar produced by the webapp project (think webjars but for applications) The root project then depends on the webapp project and gets the built application that way

deepy avatar Mar 03 '22 10:03 deepy

Thanks for your reply, @deepy. Please excuse me for these beginner questions. I highly appreciate your help!

Right, so what you are saying is that having a separate ng-serve for hot reloading is actually not a bad idea, I only need to link it properly to my spring application, e.g. with webpack?

Assuming, I like this idea of two subprojects, could you help me with the correct configuration of gradle-node-plugin? What I did so far:

  • There is a settings.gradle on root with two subprojects (inlucdes spring and webapp).
  • There is a build.gradle on root without any special build logic, it only contains publishing extensions.
  • The build.gradle of spring links the implementation of project webapp
  • The build.gradle of webapp is shown below. Can I just keep the outputs.dir as shown in the buildTask of your example?
  • Should I use the same output path for the angular.json as shown in your example?
  • After bootRun and opening localhost:8080, I still don't find my webapp. I am not aware of any specific configuration in the SpringBootAngularApplication.

=> Where would I expect the output of gradle-node-plugin to verify that it works as expected? How would spring load this output?

plugins {
  id 'java'
  id "com.github.node-gradle.node" version "3.2.1"
}

task lintTask(type: NpxTask) {
  command.set("ng")
//  args.set(listOf("lint"))
  dependsOn(tasks.npmInstall)
  inputs.dir("src")
  inputs.dir("node_modules")
  inputs.files("angular.json", ".browserslistrc", "tsconfig.json", "tsconfig.app.json", "tsconfig.spec.json",
    "tslint.json")
  outputs.upToDateWhen { true }
}

task buildTask(type: NpxTask) {
  command.set("ng")
//  args.set(listOf("build", "--prod"))
  dependsOn(tasks.npmInstall, lintTask)
  inputs.dir(project.fileTree("src").exclude("**/*.spec.ts"))
  inputs.dir("node_modules")
  inputs.files("angular.json", ".browserslistrc", "tsconfig.json", "tsconfig.app.json")
  outputs.dir("${project.buildDir}/webapp")
}

task testTask(type: NpxTask) {
  command.set("ng")
//  args.set(listOf("test"))
  dependsOn(tasks.npmInstall, lintTask)
  inputs.dir("src")
  inputs.dir("node_modules")
  inputs.files("angular.json", ".browserslistrc", "tsconfig.json", "tsconfig.spec.json", "karma.conf.js")
  outputs.upToDateWhen { true }
}

sourceSets {
  java {
    main {
      resources {
        // This makes the processResources task automatically depend on the buildWebapp one
        srcDir(buildTask)
      }
    }
  }
}

tasks.test {
  dependsOn(lintTask, testTask)
}

cbtum avatar Mar 03 '22 15:03 cbtum