Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement a micro frontends prototype with JHipster #10189

Closed
mraible opened this issue Aug 7, 2019 · 44 comments · Fixed by #15286
Closed

Implement a micro frontends prototype with JHipster #10189

mraible opened this issue Aug 7, 2019 · 44 comments · Fixed by #15286
Labels
area: feature request 💡 $$ bug-bounty $$ https://www.jhipster.tech/bug-bounties/ theme: front theme: microfrontend theme: microservice $500 https://www.jhipster.tech/bug-bounties/
Milestone

Comments

@mraible
Copy link
Contributor

mraible commented Aug 7, 2019

Overview of the feature request

JHipster has a monolith frontend when using microservices. I think it’d be hip if we supported micro frontends too. It probably won’t be easy to implement since the patterns I’ve seen call for serving up the UI on the microservice itself, then including it into a gateway via that URL using SSI, ESI, or h-include.

Motivation for or Use Case

Micro frontends have moved from trial to adopt in ThoughtWorks Radar.

These resources explain some implementation options:

And this is a great podcast on how IKEA has implemented them:

There are a couple of frameworks that aim to simplify micro frontends too:

Once this prototype is complete, I'll open a new issue to create a blueprint or integrate it into JHipster itself.

@mraible mraible added $$ bug-bounty $$ https://www.jhipster.tech/bug-bounties/ $500 https://www.jhipster.tech/bug-bounties/ area: feature request 💡 labels Aug 7, 2019
@atomfrede
Copy link
Member

atomfrede commented Aug 7, 2019

My 2 cents to this and ideas:

So why microservices and microfrontends? Fo rme the most important part is the independence/freedom of each team responsible for a service. This contains independent deployments, freedom of choice when it comes to technology (within certain boundaries of course).

The current monolithic frontend leads to coupled deployments and each team is coupled to one frontend technology. So you can't select the technology which fits best for your team or the requirements.
We have switched to a microfrontend architecture via tailor (started in 2016 and in production since mid 2016). So I would go with the "fragment" approach as described by tailor.

There are some things we should keep in mind. The current menu bar must be a separate UI, either served by e.g. the gateway or a dedicated service, such that the menu is only defined once.
bitmap

To support inter fragment linking without using absolute urls we defined a custom uri schema, we could do same (if required). E.g. jh:user-management would resolve to the concrete url e.g. via a js api from the header bar. The header/menu fragment must be framework agnostic (e.g. using preact) and must be rendered blazing fast as there are possible hard page reloads when switching fragments.

The gateway must decide where to route a request. Either it is an api request so it must be routed to the backend service api. It can be an asset request (e.g. images, scripts delivered by the microservcice) or a layout request which must go to the layout service.

PSun3i8m38NXFQV81Ne5L5XO40nL3n2bXaQaCN8TK6-FG81UyMJfVuE_TjOWMgViCftLAtj9br7za8IY9YukH6Nn_KpY8aytBbJKxuFI8onG3c7XgXt9FKM2tesKiyqxvgkjsweZY-r7xfEjVJgLl7oxUn5zqsn-kCzzjpKF5mJYW4JiY5mloCJ-3rrPhC7EAB4hUinklhTKXZhb9m00

So the most challenging part is the gateway and developer experience imho.

As there must be a lot of routes defined (or auto discovered), not sure what to use there. The related project mosaic projects seem quite good and they can be configured via an api (we have a custom UI gateway based on vert.x so routes are fixed).

There are now multiple components required to develop a service (layout, shell/menu, gateway).

So whats the concrete idea here?

  • Simple example with tailor and some ui fragments to get the principle
  • Decide which gateway technology to use (Spring Cloud Gateway seems good as e.g. authentication etc. can be easily ported as it based on spring security)
  • Real word prototype with authentication and services using different technologies

@atomfrede
Copy link
Member

I will provide a small proof of concept using tailor/mosaic here https://github.com/atomfrede/jh-10189-poc/tree/master. If that works out well we can go on with a real world prototype using real jhipster services and authentication etc.

@atomfrede
Copy link
Member

@mraible Just to keep you updated, I have first version with spring cloud gateway, a simple shell service, tailor based layout service and will try to create two fragment services during the next week. When that is done we should have a look at how to integrate auth etc.

@mraible
Copy link
Contributor Author

mraible commented Sep 13, 2019 via email

@joewhite101
Copy link
Contributor

To add some support, thoughts, and potential opportunities for contributions around MFEs.

The TL;DR
We find micro-frontends very interesting. We're doing a bunch of JHipster and micro-frontend (MFE) work in a JH blueprint in the open source world. Might be a chance to promote some of that up to mainline JHipster.

I am the CTO at Entando (an open source company) that is doing a lot of work around Micro Frontends and modernizing what we do from a development perspective. We're migrating our plugin and widget architecture to JHipster generated microservices and micro-frontends now.

We're actively working on generating a collection of micro-frontends using JHipster from JDL or an entity that we can then composed into a complete application using our engine and App Builder application. For example, each entity will have an MFE for a table, detail view, and form in MFE form. All exposed as custom elements.

We're using JHipster for our microservice generation (with customizations via blueprint) and adding the MFE generation to our blueprint.

As we get further into our development, if it is interesting to the community/team, we would be open to moving our MFE generation code up into the mainline generator and out of our blueprint.

We're also going to be doing work around making the spring boot services for JH more kubernetes focused. We've got an operator and some sidecars now to tie it all together including our JH services. If there is ever interest in a more K8s flavored Jhipster we could pull some of that up into the main project as well.

You can follow along on our github as well if there is interest:
Our blueprint (no MFEs yet but soon):
https://github.com/entando/entando-blueprint

The base POCs for generated widgets that we'll eventually migrate into the blueprint:
https://github.com/entando/generated-widgets

Some K8s stuff:
https://github.com/entando/entando-k8s-operator
https://github.com/entando/entando-component-manager

cc @salaboy for k8s and operator thoughts

@joewhite101
Copy link
Contributor

We've updated our blueprint to generate Micro-frontends using custom elements based on entities processed through JHipster.

For each entity we generate a React MFE including a table, details view, and form. Each MFE also exposes custom events that are consumable by the other MFEs on the page. We're working through the full flow between MFEs now.

An example event flow,

  • user clicks a table row --> the corresponding detail is displayed
  • user clicks the edit button in the detail --> detail hidden, edit form displayed
  • user saves data from the form --> form hidden, detail displayed

The objective is to standardize the custom events so that they can be easily consumed by other MFEs (or other assets generally) on the page.

Latest is here
https://github.com/entando/entando-blueprint

@salaboy
Copy link
Contributor

salaboy commented Oct 25, 2019

@joewhite101 awesome stuff!

@sendilkumarn
Copy link
Member

@joewhite101 Good stuff!

@mraible
Copy link
Contributor Author

mraible commented Dec 10, 2019

@joewhite101 Can you please provide the steps necessary to try out your blueprint? I'd like to take a look and try it.

Related: I stumbled across https://github.com/eavichay/microfronts today. Seems lean and mean, but also pretty new.

@MathieuAA
Copy link
Member

@mraible if you try microfronts, keep us posted! I, too, found my way to the repo. Unfortunately I haven't had the time to dive into it.

@atomfrede
Copy link
Member

Microfronts looks a lot like zalandos approach with tailor but done in the frontend, very interesting. Need to find some time to complete the prototype with project Mosaic/tailor

@joewhite101
Copy link
Contributor

joewhite101 commented Dec 12, 2019

Hey @mraible, @MathieuAA and @atomfrede, and others,

Here are some intro instructions and links. We're also working to keep the READMEs up to date and the generator itself creates a README inside of the generated MFEs. Refer to those as this post ages for more up to date instructions.

A quick summary of where we are at now is at the bottom. Some of the work here is related to things we have specifically in flight at Entando but it should be relatively straightforward to disconnect the MFEs for other uses as desired.

Run JHipster with the Entando blueprint
Detailed Steps:
0. Note that we're on 6.3.0 jhipster still but it works with later versions. You may need to add --skip-checks to the blueprint call

  1. Clone the Entando blueprint git clone https://github.com/entando/entando-blueprint.git
  2. Go into the blueprint on the command line cd entando-blueprint
  3. Link the blueprint npm link
  4. Create a new project to run your jhipster (not inside the entando-blueprint) mkdir myproject
  5. Go to the project cd myproject
  6. Link the entando blueprint npm link generator-jhipster-entando
  7. Run jhipster with the blueprint jhipster --blueprints entando
  • In step 6 above you'll go through the steps for JHipster. You'll note that we have overridden some of the default options. This is tied into what we're doing at Entando and the environments we're targeting but it could be extended to support other JHipster architectures.
  1. In the prompts there is a required choice. If not noted below you can pick whatever makes sense.
    7.a must pick microservice

Now add entities to the project (make sure you're still linked to the blueprint. Mine gets unlinked for some reason but i seem to be alone on this). You can follow the normal flow for adding entities here. Once difference is that at the conclusion of the entity flow a call to npm install will be made to install prettier to format the generated MFE code. If your npm requires sudo see known issues below.

Detailed steps for the entities

  1. jhipster entity <myEntityName>
  2. Add fields as desired
  3. Required choices:
    3.a For Do you want to use separate service class for your business logic? You must Pick one of the two Yes options if you want to use the out of the box filtering available in the table MFE. If you don't pick it the MFEs will still work but won't have filtering.
    3.b For Do you want to add filtering? Pick Dynamic filtering for the entities with JPA Static metamodel. It is used for filtering in the table MFE (but can be skipped if you don't want filtering)

At the end you'll be prompted to override a file called descriptor.yaml. You can safely pick Yes for this prompt. It is a file used in generating Entando bundles.

Output
For each entity the blueprint will generate a details, table, and form MFE. You can see the MFEs in your project in ui/widgets/<entity>/

Running the MFEs
There are detailed instructions on running the generated MFEs in the README file in the folder for the MFE itself (like /ui/widgets/<entity>/tableWidgets). Or you can read the version that lives here:
https://github.com/entando/generated-widgets/tree/master/react/details

Known Issues

  • If your npm command requires sudo the command at the end of adding entities that runs prettier will fail.
  • We're going to rename the MFEs to widgets/<entity>/list | form | detail sometime soon for purposes of clarity so if you do any scripting let us know so we can get that merged ahead of time

@joewhite101
Copy link
Contributor

You can also follow along with our work in progress for our general docs updates here with instructions that are more nicely formatted. The general steps are the same but there is additional focus outside of the MFEs

https://es-entando.github.io/build-your-first-app/#entando-blueprint

@mraible
Copy link
Contributor Author

mraible commented Feb 13, 2020

@joewhite101 I tried the tutorial today and was able to make everything work. Nice work!

A few things I thought of:

  1. If we allowed microservices to have a keycloak.yml for Docker Compose, it would greatly reduce the steps in your tutorial because you could just start Keycloak.
  2. Your blueprint uses Create React App, which is cool, but I believe we should be able to use JHipster's React CRUD support.
  3. How do you envision including this micro frontend in a JHipster gateway?

I propose we use something like the following to implement micro frontends in JHipster:

  1. Prompt the user for micro frontend support as an option (or make it the default).
  2. If micro frontend, generate the client code in the microservice instead of in the gateway.
  3. Modify the gateway when the UI is generated to add a route and lazy-load the code from the microservice.
  4. Initially, only support OAuth 2.0 for micro frontends. That way, we won't need to generate client code for authentication. We can just add .oauthLogin() to the microservice and it'll redirect to the IdP, then back to the UI.

The only micro frontends with this setup would be entities that are generated. Since we already have those available at different routes, I think this will work. We might need to do some additional work to figure out how to load a micro frontend into another micro frontend, but I think using segmented-by-route is a good start.

@jhipster/developers What do you think?

@joewhite101
Copy link
Contributor

joewhite101 commented Feb 14, 2020

@mraible Great points. A few notes and thoughts.

  1. We allowed microservices to have a keycloak.yml for Docker Compose, it would greatly reduce the steps in your tutorial because you could just start Keycloak.

Good idea. We will add this.

  1. Your blueprint uses Create React App, which is cool, but I believe we should be able to use JHipster's React CRUD support.

I don't remember exactly why we chose create react app but we can take a look at the JHipster CRUD for sure. I'll have to check with my team. Giuseppe or Martynas can you add some more detail here?

  1. How do you envision including this micro frontend in a JHipster gateway?

This step is where we diverge a bit from the JHipster architecture. We are building a Micro Frontend composition engine for Kubernetes and our objective is to take the SpringBoot service and the MFEs and wire them into our composition engine. And our users can also use an Entando Digital Exchange (marketplace) to deploy the services and MFEs. So rather than embedding them in the gateway we plan to provide builds and steps to deploy them to an Entando app.

However, it doesn't look like it would be a huge amount of work to provide different options post generation on how/where somebody wants to deploy and host their MFEs. Could also be useful to use JHipster MFEs to embed in legacy applications via custom elements. Provides a path for JHipster as a way to modernize legacy apps in a modular way.

So as long as we design carefully we could have multiple good choices. The Gateway support would be a great area for somebody to join us on the MFE generation journey. We'd help with the blueprint understanding if somebody wants to jump in.

  1. Prompt the user for micro frontend support as an option (or make it the default).

Good idea. We will add the option.

  1. If micro frontend, generate the client code in the microservice instead of in the gateway.
    Modify the gateway when the UI is generated to add a route and lazy-load the code from the microservice.

Makes sense to me. I think gateway as a follow on step or integration option makes a lot of sense given the utility of MFEs in different deployments.

Initially, only support OAuth 2.0 for micro frontends. That way, we won't need to generate client code for authentication. We can just add .oauthLogin() to the microservice and it'll redirect to the IdP, then back to the UI.

We'll review this and can help if the team thinks it is the right way forward. Seems like a good approach. We have some built in identity management assumptions in our environment for the composition layer. But we can look at abstracting so that what you recommend could be the default or an option and give some flexibility on how the MFEs tokens are managed.

@pascalgrimaud
Copy link
Member

@atomfrede : what is the state of this ticket plz ?

@atomfrede
Copy link
Member

Sadly I didn't made much progress. But I think Matt tried a different approach which might fit better.

@mraible
Copy link
Contributor Author

mraible commented May 30, 2020

Yes, I plan on trying the Module Federation that's coming in Webpack 5.

https://github.com/module-federation

If folks are interested in helping with this effort, I can create tickets with small tasks and assign bounties to them. Here's a high-level plan:

  1. Create a microservices architecture using JHipster 6.9.x. My blog + store JDL is probably a good start.
  2. Modify things so the UI code for each microservice resides within each microservice.
  3. Modify Webpack build to use module federation.
  4. Integrate Micro Frontends as an option in the generator (only for microservice)
  5. Upgrade to Webpack 5 beta.
  6. Add Webpack module federation and make Micro Frontends work.
  7. Test and iterate ensure you can develop a microservices UI stand-alone or with an app shell (aka a gateway app).

I think we should only target OIDC for now because it'll make authentication into the standalone apps the easiest. If we want JWT support, the stand-alone apps will need their own shell and login UI.

@gidesan
Copy link

gidesan commented May 30, 2020

Hey @mraible, I'd like to help. I'm not a webpack guru but I'm following with great interest all the module federation stuff since a couple of months. I'm working with @joewhite101 at Entando.

@mraible
Copy link
Contributor Author

mraible commented May 31, 2020

@gidesan Cool! Do you have any feedback on the high-level plan? Are there things I'm missing?

@mraible
Copy link
Contributor Author

mraible commented May 31, 2020

I started trying to upgrade a microservices architecture with Angular to use Webpack 5. I made progress, but ultimately failed. You can see my PR with changes at mraible/jhipster-microfrontends-angular#1.

@gidesan
Copy link

gidesan commented May 31, 2020

@mraible your high-level plan sounds good to me, but MF is not feature-complete yet, lots of things are being added. Does it make sense to wait for a Webpack 5 RC / final version?

@mraible
Copy link
Contributor Author

mraible commented May 31, 2020

@gidesan Possibly. However, I think trying to make it work now may give us an opportunity to provide feedback and fixes before everything is final.

@mraible
Copy link
Contributor Author

mraible commented May 31, 2020

I created a couple repos with PRs to try and upgrade JHipster v6.9.0 to use Webpack 5. Both attempts failed. The respective PRs have more information.

@joewhite101
Copy link
Contributor

I may try and pick up where @mraible left off. However, i'm the furthest thing from a webpack expert so it will be slow going. If there is a webpack expert out there who wants to take the lead I'm happy to follow.

FWIW We're looking at module federation as a pretty key technological update in webpack 5 for micro frontends. Seems like a pretty compelling use case.

cc @gidesan

@mraible
Copy link
Contributor Author

mraible commented Nov 2, 2020

Commenting to keep open and active.

@mshima
Copy link
Member

mshima commented Feb 3, 2021

@mraible https://github.com/mshima/jhipster-microfrontend

@mshima
Copy link
Member

mshima commented Feb 3, 2021

Just made cypress to succeed.
A few notes about the implementation:

  • It's using webpack5 + yarn resolutions (npm doesn't supports, but it's ok to use npm 7 on top of yarn.lock)
  • Blog microservice contains a full copy of the shell (gateway).
    Otherwise it's very difficult to get module federation happy.
  • Articles is loaded dynamically from the microfrontend
  • The only non dynamic Blog info is the menu.

@github-actions
Copy link
Contributor

github-actions bot commented Mar 6, 2021

This issue is stale because it has been open 30 days with no activity.
Our core developers tend to be more verbose on denying. If there is no negative comment, possibly this feature will be accepted.
We are accepting PRs 😃.
Comment or this will be closed in 7 days

@mshima
Copy link
Member

mshima commented Mar 6, 2021

Support is almost ready, waiting for angular 12.

@mshima mshima removed the area: stale label Mar 6, 2021
@github-actions
Copy link
Contributor

github-actions bot commented Apr 6, 2021

This issue is stale because it has been open 30 days with no activity.
Our core developers tend to be more verbose on denying. If there is no negative comment, possibly this feature will be accepted.
We are accepting PRs 😃.
Comment or this will be closed in 7 days

@avdev4j
Copy link
Contributor

avdev4j commented Apr 6, 2021

Keep it open

@pascalgrimaud
Copy link
Member

@avdev4j : I'd like to know what can be done on generator-jhipster side ? I thought this part was done by Entando blueprint, unless I'm wrong ?

@avdev4j
Copy link
Contributor

avdev4j commented Apr 6, 2021

@pascalgrimaud here are several things here. Entando's blueprint allow the user to generate an MFE app within his entity to deploy it into the Entando platform. It matches well with the Entando way of work and features but not probably with the a most common micro frontend architecture.

This is @mshima worked on the Webpack 5 upgrading to be able to use the module federation feature (yes, it comes with Webpack 5) to make the JHipster generated app a micro frontend based application.

From my POV, another step would be to be able to directly generate MFE with JHipster as we can do with microservices (aka adding a new applicationType). But for this last thing, I don't really know if it's something some people work on or just an idea in my mind :D.

@mraible
Copy link
Contributor Author

mraible commented Apr 6, 2021

@pascalgrimaud We currently generate a monolith UI, which kinda breaks the whole point of microservices. A monolith UI on the gateway means a microservice + gateway needs to be redeployed when there's changes. With microfrontends, only the microservice that's updated needs to be redeployed.

@github-actions
Copy link
Contributor

github-actions bot commented May 8, 2021

This issue is stale because it has been open 30 days with no activity.
Our core developers tend to be more verbose on denying. If there is no negative comment, possibly this feature will be accepted.
We are accepting PRs 😃.
Comment or this will be closed in 7 days

@mshima
Copy link
Member

mshima commented May 8, 2021

The generator part is kind of ready.
Needs angular 12.

@github-actions
Copy link
Contributor

github-actions bot commented Jun 8, 2021

This issue is stale because it has been open 30 days with no activity.
Our core developers tend to be more verbose on denying. If there is no negative comment, possibly this feature will be accepted.
We are accepting PRs 😃.
Comment or this will be closed in 7 days

@mraible
Copy link
Contributor Author

mraible commented Jun 8, 2021 via email

@mshima
Copy link
Member

mshima commented Jun 11, 2021

Rebased the microfrontend branch, and took a while to discover that zone.js needs to be imported as umd.

PR created, I will create a series of PRs for minor improvements.
The last commit will need much more work, so I will try to remove it in the end.

i18n is not working correctly for microservices, need to fix lazy loading microservice translations.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: feature request 💡 $$ bug-bounty $$ https://www.jhipster.tech/bug-bounties/ theme: front theme: microfrontend theme: microservice $500 https://www.jhipster.tech/bug-bounties/
Projects
None yet
Development

Successfully merging a pull request may close this issue.