Giter Site home page Giter Site logo

Comments (17)

zhangwilling avatar zhangwilling commented on May 16, 2024

let's talk about this together.

federation can request remotes and share modules, this is needed much in a single app that need to be decontructed.

if you want intergrate multi framework, no conflicts as well. high level things could be solved by high level lib or framework, such as 'single-spa'.

i often says 'systemjs is dead', cause federation can do all things that systemjs can do, and better than it. we can share some app modules and third-party libs and they can be versioned (this systemjs can't do).

At last, react should be same version, it is decided by react. otherwise, 'invalid hooks ' would come, image that app1 get a remote app's (app2) module which used hooks and this hooks used app2's react .

that is my thought above 😊.

from module-federation-examples.

sesigl avatar sesigl commented on May 16, 2024

alright, thanks for pointing me to single-spa. I checked this out and it felt like a very angular heavy product that is not as holistic as expected in the beginning.

I love the approach to push the complexity of composing application(-parts) down to the build system. It enables a lot of beneficial stuff. I am looking for a long term solution that enables us devs to create an application that scales.

What worries me a lot about the framework version dependence is:

We create bigger and bigger applications with more and more people. The architecture behind it needs to support it. What happens if you have multiple teams and maybe multiple applications is, that you start building frontend component libraries to reduce work and to have basically a corporate design framework. This works easily with CSS and HTML, because its simple to wrap the framework of your choice around it. But there is a need for universal js components that can be reused. Tools like storybook are good tools to gather and maintain these central components. And by components, I mean recurring components in any size like a header or a footer that might be a very big component composed of smaller ones or just a button.

From a team perspective that might have different needs it should be very easy to use.

import {Header} from '/some/path/header' // will be remotely fetched

...

return <div>Team's component content {universialReactConsumer(Header)}</div>

If the header is implemented in react it would take care itself to be universal:

const Header = () => {

   useEffect( () => render(".header"), [])

   return <div>header</div>
}

export const Header = universalProducer(Header)

It should not matter if this build with angular or react. Communication between the both can be done via other named exports and the components itself should take care to be usable from other libraries without any required depdencies.

For me, it's a must have. If you have 10 teams, running about 15 applications that are using components from some central component library, you want to have some independence. You should not be forced to render this serverside, nor should you be forced to render it on the client. Also, if you do a version upgraded von react v16 to react v17, you want to migrate slowly, step by step and teams should decide the if and the when on their own to keep the focus. If you want to choose a framework to implement a header that is not based upon react, you should just be able to do it.

In the backend you usually achieve this kind of things by using REST or gRPC as an API between different completely different technologies. In my opinion, this is what is missing nowadays and webpack might be able to support this with something like module federation.

from module-federation-examples.

ScriptedAlchemy avatar ScriptedAlchemy commented on May 16, 2024

through collaboration with ringcentral - we designed a framework for multi app / multi framework architecture.
https://github.com/ringcentral/web-apps

from module-federation-examples.

sesigl avatar sesigl commented on May 16, 2024

Wow! This sounds amazing! I will definitely try this out. Thanks for pointing me to this.

from module-federation-examples.

zhangwilling avatar zhangwilling commented on May 16, 2024

@Journerist

micro fe has two category.

  1. combine app with others (app1、 app2、app3...) - i call it micro page
  2. only host app which is composed of many modules. The module maybe comes from current app or remote app. - i call it micro module or micro component

choose which one depends on the granularity we needs.

feature-hub is a micro-module solution too.

But it could be better by using federation, now it uses externals.

from module-federation-examples.

ScriptedAlchemy avatar ScriptedAlchemy commented on May 16, 2024

Why not move to federation already?

from module-federation-examples.

sesigl avatar sesigl commented on May 16, 2024

I will give it a try for sure. It might be a bit annoying for production use case because it seems like a very early product that will probably change here and there. But it's fine, for now I only do research that is totally fine!

Thank you guys a lot by pointing me to the existing solution. I think, in case it's done right, this can be the game changer :).

from module-federation-examples.

ScriptedAlchemy avatar ScriptedAlchemy commented on May 16, 2024

Helped build this with ring central. https://github.com/ringcentral/web-apps
Then Single SPA is compatible as well with MF

from module-federation-examples.

sesigl avatar sesigl commented on May 16, 2024

I experimented a couple of hours with module federation. Before I jump in and use some framework I want to get hands dirty and craft some custom solutions and understand the basics.

My current strategy is based on the following concepts utilizing module federation:

  • consume and expose chunks using module federation
  • build and wire 2 different react versions, share versions if versions match.
  • it should work in the frontend and backend seamlessly

The last point is though. It already works in the frontend in a very nice way, that's impressive !!

I struggle a bit getting the server-side rendering part right. In my opinion, the host application should not server-side render the react app of another application that is consumed. If the implementation changes to, for example, an more CPU heavy implementation, or call to another external service that is only available in a certain network, then the other application should render its component by itself. Therefore, rendering should happen initially in the producer (the exposed app), which is loaded via for example Edge side includes and hydrated in the browser.

Current questions I have is:

  • how to make fetching and executing the other application when using react hydrate?

If I render in the frontend only then everything is fine. But if I render it in the backend and want to fetch the exposed part in the frontend then nothing is fetched. I implemented it like this:

if (typeof window !== "undefined") {
        import("header/HeaderApplication").then((app) => {
                 app.hydrate(this.headerRef)
         });
}

header is my consumed/loaded application. Is there anything available for dynamic imports like in nextjs {ssr: false} ? It does not fetch the chunk in the frontend when the host app is hydrated.

from module-federation-examples.

ScriptedAlchemy avatar ScriptedAlchemy commented on May 16, 2024

webpack does not handle implementation details. However, you could use shared and share a noop file, so by default it falls back to a local version.
Alternatively, on SSR builds, you could have the server config point the remote to a mocked one like header: ../header which contains some empty container

Or you can have dual exports. https://github.com/jherr/wp5-resilient-header

from module-federation-examples.

ScriptedAlchemy avatar ScriptedAlchemy commented on May 16, 2024

We are working on an example of two different react versions. Easy way is use a portal and some custom tooling we release for cross version mounting

from module-federation-examples.

sesigl avatar sesigl commented on May 16, 2024

It already works flawless for me with 2 different version. What is confusing is the module federation remote loading for client side only (conditional) as a first step if the component is server side rendered.

I will try to workaround. Let me see if I get a dirty way working.

from module-federation-examples.

sesigl avatar sesigl commented on May 16, 2024

Alright, got it working. It was a missing remoteEntry script tag on my server side, so all good.

I still have an issue and I am curious if you have an approach for it.

My Server side returns the correct HTML of my host app and my remote app like this:

<div>
   <span>host app</span>
   <div>remote app</div>
</div>

the remote app part is inserted in a dirty way via:

router.get('/', async (req, res) => {
    let reactComp = renderToString(<MyApp/>);

    // to be replaced with edge side includes
    reactComp = reactComp.replace("<div></div>", "<div>remote app</div>")

    res.status(200).render('pages/index', {reactApp: reactComp});
})

Now, react hydrate identifies correctly that the server HTML is off and purges the external app part away. Afterwards, module Federation kicks in and adds the part again in the frontend.

Do you have an idea of how to approach this?

My plan is to do a it within the react component to expose this information to react dom server.

if (server) {
   // process the edge side include
} else {
   // import the remote app via module federation
}

from module-federation-examples.

ScriptedAlchemy avatar ScriptedAlchemy commented on May 16, 2024

super dirty but will work :P

from module-federation-examples.

ScriptedAlchemy avatar ScriptedAlchemy commented on May 16, 2024

We can try to refine the technology as i open-source steaming, id love to flesh out edge-side rendering more

from module-federation-examples.

sesigl avatar sesigl commented on May 16, 2024

I still think about the definition and a practical example of a scalable architecture that covers backend and Frontend nicely. What I see in practice is usually a well crafted backend architecture and some frontend framework wired around. But it's rarely in balance, nicely crafted to make it technically and strategy (team-wise) scalable, flexible and evoleable.

If ssr is no requirement, using module federation solves it in a flexible way. You can share common dependencies but also just render applications independently by exposing simple methods that uses React.renderToNode method. Communication needs to be defined using existing web standards, but that's fine.

I see SSR as nice to have. If you need it it should be doable without a lot of issues.

Let's say some development team A wants to build an admin interface. They want to use some existing components that are build in a component library but don't need any SEO relevant stuff and don't need the user experience benefits of server side rendering.

Then there is a development team B and C that build customer facing parts. They require SSR from a SEO perspective. Each of them own and build a slice of a bigger application. Within their pages, it happens here and there that they need to display components that are owned by other teams like a header, footer, or a component that shows random items of interest.

If everything would be Frontend only, they could share components with module federation and align on some rules to keep some islotation requirements. it should always be possible to use a bigger component, like a header, independently without worrying about what react version / what framework is used. Teams should be autonomous and should define priorities on their own. A bottleneck like a global version upgrade should be avoided. Second, if one system of a team is down, other systems should still be working. This is still pretty easy just thinking in the Frontend by using some kind of cache that enables scalability, low response times, and if the origin system is down, also some resilience aspects.

So far so good... Now think about the backend. Backend can be different. They can monolithic, or Microservice based. Still, the basic architecture should allow to opt-in for server side rendering.

The bigger components should be exposed by module federation and in my opinion should also expose an endpoint that exposes rendered html.

Similar to the Frontend only solution, using edge side includes for server to server communication gives us resilience and performance at the same time. There might be things that are hard(er) to cache, but these are details that depend on detailed requirements.

In my target implementation, reusable bigger components like header should expose 3 things:

  • an endpoint that renders the exposed component for server to server communication and maybe SSR for self usage
  • the exposed entry.js for module federation for the Frontend part
  • optionally some kind of manifest that contains all important links to endpoints and maybe assets

I am interested in your thoughts and experiences :).

from module-federation-examples.

ScriptedAlchemy avatar ScriptedAlchemy commented on May 16, 2024

yeah ESI is a solution, but i consider it more work compared to federated SSR. IF you cant support federated backend architecture, then ESI will work - since I've got no edge-based examples handy, its likely a safe solution if you're willing to put the work into it.

The closest / easiest way I do it on the server is like-> https://github.com/jacob-ebey/vercel-federated-gql-module-a

With streamed code between apps, not SSR endpoints.
However, Ive also made videos about using multi-threaded rendering where webpack requires a string of HTML from the remotes own SSR, and passes the props back to the rendering endpoint.

ESI will work, but its more work than I want to put in at scale. If I design my server architecture toward node platforms, then I want it to be just as effortless, no implementation changes needed.

Moving to the edge, which is challenging - id use a tactic similar to streaming which can render the code for me but webpack still puts it together, the edge cannot compile modules, so we likely would have to require only strings in edge workers.

There are areas where Edge workers is the only solution, like personalization. But I try to stick with less infra to maintain when possible.

If you SSR parts of the app, an adapter might be good that can flip modes or translate between the remote server and host consumer - I've used this on the client to mix react and vue, but in your case, it might help avoid a hydration issue if one were to occur

from module-federation-examples.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.