node-gradle / gradle-node-plugin

Gradle plugin for integrating NodeJS in your build. :rocket:
Apache License 2.0
601 stars 117 forks source link

How to correctly configure multi project builds for spring boot? #218

Open cbtum opened 2 years ago

cbtum commented 2 years ago

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:

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???

deepy commented 2 years ago

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

cbtum commented 2 years ago

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:

=> 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)
}