quarkusio / quarkus

Quarkus: Supersonic Subatomic Java.
https://quarkus.io
Apache License 2.0
13.57k stars 2.63k forks source link

Improve interaction with web frameworks like react, angular etc #588

Closed emmanuelbernard closed 2 years ago

emmanuelbernard commented 5 years ago

@dreab8 was pointing to me that he worked on a project with Protean. It had classical Java backend and a React front end. He wanted Protean to serve the front end content but having to put the react or angular directory structure under META-INF/resources is not convenient and would serve the whole project. In his situation he had two top level projects. But we could envision a subproject of protean with the react structure possibly.

@dreab8 can you add more info on the pains you felt and how you think it could work. @stuartwdouglas could you put down your ideas in this issue as well. You had some from last year on how to serve the front end as easily as possible.

FroMage commented 5 years ago

Yes, please provide more details, I don't understand why putting static files in one folder would lead to problems with two top level projects.

dreab8 commented 5 years ago

Being not an expert of front end frameworks and not using maven for quite a long time I'm facing difficulties to find and easy and clean way to integrate in a single build a React JS project with a Protean one in order to deploy it on OpenShift. Maybe having a tutorial with an example on how to integrate a JavaScript framework with Protean could be beneficial.

emmanuelbernard commented 5 years ago

I'm no expect either but I support React "default" structure would come with npm, babel to change your JS, ESLint and other tool chain. Do you want all of that in META-INF/resources?

iweiss commented 5 years ago

Have anyone investigated this, https://github.com/eirslett/frontend-maven-plugin? Maybe we can provide a separate Protean project that leverages this.

That's the way Spring recommends apparently, https://spring.io/guides/tutorials/react-and-spring-data-rest/.

quintesse commented 5 years ago

With the Frontend Maven plugin you could at least integrate the React code into the Maven directory structure and get it to build. You'd have to adjust the configuration to ensure the "build" result goes into the target META-INF/resources of course.

The downside I see to this, something that happens a lot within RH, is that it's very Java/Maven centric (both in the build process and the directory structure it imposes), which is just not how a lot of developers out there will be working (nor will they want to). So to them it would probably be more useful if we could come up with something that sees frontend and backend as separate projects handled be different people/teams.

How to link the two I'm not sure. Perhaps have a single project with a Java/Maven backend folder and a React/JS frontend folder and have a toplevel Maven pom that builds both and creates the final result?

dreab8 commented 5 years ago

I personally like the toplevel Maven project with 2 sub projects one for the backend (Protean) and the other for the frontend (React JS) and it is how I structured my toy project.

kenfinnigan commented 5 years ago

I don't recall doing an all in one (front and back), but I have used Frontend Maven plugin to create a website that can be run from a Thorntail uber jar: https://github.com/kenfinnigan/ejm-samples/tree/master/chapter2/ui

It only requires some tweaks to tell webpack to output the generated HTML into /target/{app-name} and then it just becomes static resources

emmanuelbernard commented 5 years ago

@quintesse so I do see your point and for a Java centric person, merging the two projects under one maven module structure is fine and we can work on a way where the React Hot Deploy approach integrates with Protean rendering these files.

In the case of two separate projects like Andrea did, it's assuming it's two teams really or at least that the output of the front end is copied by the CLI "on a regular basis" in the backend serving. That works but it means no fast development cycle. Maybe that's ok.

quintesse commented 5 years ago

@emmanuelbernard I think it can work if you combine what @kenfinnigan mentioned with a way to include the frontend project into the backend somehow. You could either just expect it to be in the same parent folder, but perhaps using something like git modules to include the frontend directly into the backend project might be a better option. That way you could have a standard React project that works normal in every way but if you run the backend build it will run the frontend build while oeverriding the output path. (Or you just copy the files yourself)

metacosm commented 5 years ago

If I understand correctly, the issue is figuring out how to best bundle and serve static files created by an external tool (angular-cli, etc.) from Quarkus? Maybe I'm missing something here but why use Quarkus in this scenario? If it's because the backend is also developed using Quarkus, wouldn't it make more sense to develop the projects separately (and even deploy them in different pods) anyway? Presumably, there are better solutions to serve static files for a JS/TS frontend, are there?

emmanuelbernard commented 5 years ago

What you describe is a valid and clean architecture. But for the not quite full on microservices person, an all in one app with quarkus:dev experience is really cool.

emmanuelbernard commented 5 years ago

Editing a UI screen + a Hibernate entity, REST endpoint hit save and look is what I'm looking for.

klearchos commented 5 years ago

Very good examples of what you describe can be generated with the help of JHipster. It would be great for the Quarkus project to be integrated with the JHipster generator.

edewit commented 5 years ago

So either you put the front-end inside the quarkus project and let the maven front-end plugin generate the site, or you have a separate project and let npm tooling (or front-end plugin) put the output in the quarkus project. But for both of these solutions you would need the quarkus:dev command to also watch the target folder for changes, right? Does that sum it up?

dhartford commented 5 years ago

Actively reviewing a similar challenge where using a quarkus application that is in need of a UI, that based on any large/enterprise organization may mandate react+their styling / angular+their styling / some-other-nodejs-based-solution-specific-to-environment-working-in.

Having a 'developer joy' example that interacts with a nodejs-built-static-asset UI (reactjs my preference), such as with the maven-front-end plugin and how to use quarkus:dev to watch/update on changes would be great, particularly for scenarios where the ideal would be an intuitive start-small-move-fast with a single project before getting buy-in to make it larger scale and break it out into separate projects with their own lifecycles (by project, I really mean repository, if its two maven reactor projects under a single parent that has a one-command-line devbuild, great).

stuartwdouglas commented 5 years ago

So most modern frontend web frameworks provide their own development server. We need to take advantage of this, as we also want to allow for hot reload in the web framework. This means there are two apprpaches we can use:

1) Map JAX-RS under a specific path (/api), then configure the frontend server to proxy /api to quarkus. 2) Add the ability to change the 'DefaultServlet' to a proxy servlet, that proxies requests to the frontend development server rather than serving static resources directly.

I think 1) is the way to go, as we can do this at the moment, so it is mostly just a case of documenting the workflow, and possibly adding some additional user friendliness (e.g. auto starting the dev server, auto redirecting to the correct port).

nimo23 commented 4 years ago

How does quarkus treats the src/main/resources/node_modules-folder (which can have a vaste amount of data in different formats(js, css, html, txt, ..)? Will it be scanned and included all over the time while (hot) compiling the project? Should such a folder be better placed on the root-path of the project instead of src/main/resources-folder? Where should all the client config files be placed (e.g., .bacelrc, gulpfile.js, webpack.js, package.json, tsconfig.js, ..)? Would it be better to have a special "marker folder" where all the client related stuff should be placed (something like src/main/resources/webapp/WEB_INF) seperated by stuff only needed during development (e.g., node_modules, webpack.js, package.json) and stuff needed to be packaged in the compiled project?

edewit commented 4 years ago

@nimo23 that is why I put organised the frontend project into 2 modules one for the frontend and one for the backend. That way only a pom.xml is needed extra in the frontend project (that also builds with the maven frontend plugin and copies the project into src/main/resources/) and using a proxy you can still to npm start and have hot replace

nimo23 commented 4 years ago

@edewit So we need to watchers: one for quarkus:dev (server code) and the other for the frontend-code (for example, by webpack hot redeploy).

Is it possible to bind tasks by pom.xml to quarkus:dev to watch/rebuild the frontend-module also on any change? If I got it right, I must rebuild the frontend-project on every change by myself to get it copied to quarkus-project/src/main/resources/.

nimo23 commented 4 years ago

While developing, the frontend-code (react) is bound to the backend-code (quarkus) by a proxy. So every change on the frontend-code is rebuild by its frontend-watcher while every change on the backend-code is rebuild by quarkus:dev. So there is no need to put the frontend-code in src/main/resources/ on every change.

edewit commented 4 years ago

right it's not needed on every change to put the frontend-code in src/main/resources only when you do a maven production build will that be done.

carldea commented 4 years ago

@dreab8 was pointing to me that he worked on a project with Protean. It had classical Java backend and a React front end. He wanted Protean to serve the front end content but having to put the react or angular directory structure under META-INF/resources is not convenient and would serve the whole project. In his situation he had two top level projects. But we could envision a subproject of protean with the react structure possibly.

@dreab8 can you add more info on the pains you felt and how you think it could work. @stuartwdouglas could you put down your ideas in this issue as well. You had some from last year on how to serve the front end as easily as possible.

In the npm/node world you don't want to watch files inside of the node_modules directory.

A popular thing I've seen in the React community is NextJS aka server-side rendering (different routing ability). You may be able to glean from their patterns and structure to get an idea. Maybe there should be an extension for each web framework (angular, reactjs(clientside rendering), nextjs/reactjs(serverside rendering) etc.)

I also heard the folk at GraalVM has a version of NodeJS having the GraalVM inside able to run Java code and Node/Npm(javascript) code.

But yea, I'm looking forward to this idea/ability. Decoupling is good, but this option just allows you to develop faster for small/medium projects.

ia3andy commented 4 years ago

btw we have a related blog article: https://quarkus.io/blog/quarkus-and-web-ui-development-mode/

ia3andy commented 4 years ago

For code.quarkus.io, we have a react frontend: https://github.com/quarkusio/code.quarkus.io

  1. The frontend is located in src/main/frontend as a standalone react app
  2. We use the frontend maven plugin for the production build which is configured to copy the build to the quarkus static directory in the target folder (no watch): https://github.com/quarkusio/code.quarkus.io/blob/master/src/main/frontend/package.json#L37
  3. For dev mode, we run 2 processes (quarkus:dev and react dev) using a Makefile: https://github.com/quarkusio/code.quarkus.io/blob/master/Makefile#L8

I think the dev mode could be improved by integrating it in the frontend maven plugin because it's the part responsible of dealing with yarn or npm.

Maybe we could have some kind of extension to make it easier and bind everything together?

johnbanq commented 4 years ago

Is it possible that we solve the problem by writing a small maven plugin that replaces the Makefile and spins up the servers for you at dev time?

manusa commented 3 years ago

Just for completeness, this weekend I finally managed to find the time to write yet another blog post about SPA frontend and Quarkus backend integrations. This is an approach I've been using for years with other frameworks, but I haven't seen it documented anywhere.

The main issue with building the frontend into the META-INF/resource directory approach is that front-end routers won't work as expected. This means that if you access http://localhost:8080/front-end/nested/path your index.html file won't be found and your front-end application won't load.

btw we have a related blog article: https://quarkus.io/blog/quarkus-and-web-ui-development-mode/

In Kabir's blog post, the issue is tackled using a Servlet or a Filter, which works great.

In my case, I'm just using a standard JAX-RS endpoint definition.It's a similar solution to that of the servlet/filter, but IMHO it allows more flexibility and control regarding the frontend build and assembly.

With respect to the frontend build, I'm using the standard Maven resources and exec plugin.

Regarding hot-reloading / Development mode, I find it quite easier running each application with its own dev server and configuring CORS in Quarkus. You can read more about this in the article too.

nimo23 commented 3 years ago

@edewit Why is https://github.com/edewit/quarkus-quickstarts/tree/react-example/react-rest not more available in https://github.com/quarkusio/quarkus-quickstarts?

edewit commented 3 years ago

@nimo23 it's an open PR https://github.com/quarkusio/quarkus-quickstarts/pull/286 leave a +1 on it ;)

ia3andy commented 2 years ago

Quinoa 1.0.0 has been released. We now have a elegant integrated way to deal with web frameworks: https://github.com/quarkiverse/quarkus-quinoa

https://code.quarkus.io/?a=quinoa-bowl&j=17&e=io.quarkiverse.quinoa%3Aquarkus-quinoa&e=resteasy-reactive

ia3andy commented 2 years ago

I think most of the concerns evoked in this issue are solved using Quinoa:

Link to the doc: https://quarkiverse.github.io/quarkiverse-docs/quarkus-quinoa/dev/index.html