single-spa / single-spa

The router for easy microfrontends
https://single-spa.js.org/
Other
13.29k stars 916 forks source link

mounting the applications in base application #365

Closed Vibing closed 4 years ago

Vibing commented 4 years ago

I have a basic application and other sub-applications, I want to load the sub-application in the red box.

what should I do

frehner commented 4 years ago

we do not recommend creating a parent+child relationship between apps - there are too many problems with that.

instead, apps should all be siblings.

ghost commented 4 years ago

Is it really possible to do something like this?

joeldenning commented 4 years ago

The suggested way to do this is fully route-based: The sidenav should be a single-spa application and each of the main content is a single-spa application. When you click on a link in the sidenav, it triggers a routing event that results in single-spa unmounting the old main content app and mounting a new main content app.

Like @frehner said, I would not suggest adding a parent-child relationship between your applications. You can do so with single-spa parcels, but this is not the use case for single-spa parcels at all.

To see a demo of this working, you can check out http://coexisting-vue-microfrontends.surge.sh where the top nav is similar to the sidenav that you have screen shotted here.

I'm closing this issue because there's no bug here and also I've explained the options for doing this. Feel free to comment further or reopen.

Vibing commented 4 years ago

@joeldenning @frehner Thank you for your answer. I have a little trouble. This is the basic application:

render() {
    return (
      <Layout>
        <Menu/>

        <Layout>
          <Header/>

          <Content>
           This is content
          </Content>
        </Layout>
      </Layout>
    );
  }

I want to stuff the sub-application into Content. If apps should all be siblings, in the face of this situation, I don’t know what to do. The basic application contains Menu and Header,do I have to split them into two applications?

joeldenning commented 4 years ago

I would recommend making <Menu a separate single-spa application. And then have a few applications that fill the Content space.

Use a styleguide module for shared CSS or react components for layout between the applications.

Vibing commented 4 years ago

emm.. sorry,I'm not good at English,I do not quite understand you. But i know that I should making Menu a separate single-spa application.

look this screenshot: 006y8mN6ly1g8myxumiihj30ui0ex41m I think all the red boxes should belong to the basic application,because the Header and Menu are common parts of the entire application.

I can making Menu a separate single-spa application,but what should I do with Header?

qiankun can be solved, but I don't think this is a good way

joeldenning commented 4 years ago

sorry,I'm not good at English,I do not quite understand you

You're English seems great - it might be me not communicating clearly 😄

I can making Menu a separate single-spa application,but what should I do with Header?

Header could be a separate single-spa application, or it could be combined with the sidebar. Usually I've made it a separate single-spa application. The question to ask is "do I frequently change both the sidebar and header at the same time?" If the answer is yes, put them into the same single-spa application. If the answer is no, put them in separate single-spa applications.

ramos-lucas commented 4 years ago

I have the same doubt. If I put them into the same single-spa application, how will I put the content application on this position?

joeldenning commented 4 years ago

Navigation menus are usually position: fixed;, which means that it doesn't matter where they are in the dom. If your menu is not fixed, then you'd need to make sure it ends up in the correct spot in the dom. But most menus are fixed (or sticky, which is similar).

Vibing commented 4 years ago

Thank you for your answer, the following method solves my problem

in sub-app:

function domElementGetter() {
  let el = document.getElementById('sub-module-wrap');
  if (!el) {
    el = document.createElement('div');
    el.id = 'sub-module-wrap';
  }
  let timer = null;
  timer = setInterval(() => {
    if (document.querySelector('#main-layout')) {
      document.querySelector('#main-layout').appendChild(el);
      clearInterval(timer);
    }
  }, 100);

  return el;
}

const reactLifecycles = singleSpaReact({
  React,
  ReactDOM,
  rootComponent: Root,
  domElementGetter
});
zoxiyo commented 4 years ago

sorry,I'm not good at English,I do not quite understand you

You're English seems great - it might be me not communicating clearly

I can making Menu a separate single-spa application,but what should I do with Header?

Header could be a separate single-spa application, or it could be combined with the sidebar. Usually I've made it a separate single-spa application. The question to ask is "do I frequently change both the sidebar and header at the same time?" If the answer is yes, put them into the same single-spa application. If the answer is no, put them in separate single-spa applications.

How can I let the "sidebarr and header" not unmount if the browser url is changed?

joeldenning commented 4 years ago

How can I let the "sidebarr and header" not unmount if the browser url is changed?

Create an application called navigation, whose activity function is always there.

singleSpa.registerApplication('navigation', () => System.import('navigation'), location => true)
FazanLone commented 1 month ago

I have a similar issue. I need to render a child single spa angular app within a base single spa angular app on a specific route. I am also using a root-config project to manage the spa's. Can anyone please help?