Skip to content

[🐞] Containers do not work sometimes #7494

@Karam2B

Description

@Karam2B

Which component is affected?

Qwik Runtime

Describe the bug

I'm trying to work with containers to support microfrontend application, I'm using gioboa/qwik-microfrontends approach (the the issue is here) gioboa/qwik-microfrontends#4 which relies on SSRStreamBlock and SSRStream component to fetch remote containers, but it doesn't work all the time (it works when it is rendered at the server only)

Reproduction

https://github.com/Karam2B/qwik_microfrontend_bug

Steps to reproduce

to replicate the error run pnpm dev and visit localhost:12340

the resultant DOM is

<!-- does not work -->
<div q:shadowroot>
    <template>...</template>
</div>

<!-- works -->
<div q:shadowroot q:key="...">
    #shadow-root (open)
    <template>...</template>
</div>

System Info

(node:32355) ExperimentalWarning: Support for loading ES Module in require() is an experimental feature and might change at any time
(Use `node --trace-warnings ...` to show where the warning was created)

  System:
    OS: Linux 6.11 Ubuntu 24.04.2 LTS 24.04.2 LTS (Noble Numbat)
    CPU: (16) x64 13th Gen Intel(R) Core(TM) i7-1360P
    Memory: 9.47 GB / 15.31 GB
    Container: Yes
    Shell: 5.2.21 - /bin/bash
  Binaries:
    Node: 23.0.0 - ~/.nvm/versions/node/v23.0.0/bin/node
    Yarn: 1.22.22 - ~/.nvm/versions/node/v23.0.0/bin/yarn
    npm: 10.9.0 - ~/.nvm/versions/node/v23.0.0/bin/npm
    pnpm: 9.12.2 - /usr/local/bin/pnpm
    bun: 1.1.31 - ~/.bun/bin/bun

Additional Information

The bug is about qwik's containers, the bug can be found in following component ./host/src/routes/remote.tsx

export const Remote = component$(() => { 
    return <template shadowRootMode="open">
        <SSRStreamBlock>
            <SSRStream>{getSSRStreamFunction(remote.url)}</SSRStream>
        </SSRStreamBlock>
    </template>
});

the component works when it is rendered like this:

<Remote remote={{
    name: "works",
    url: "http://localhost:5174"
}} />

but doesn't work when is rendered like this

{
    state.value.state === "browser_state" &&
        <Remote remote={{
            name: "does_not_work",
            url: state.value.url
        }} />
}

I think the bug is that SSRStreamBlock or SSRStream should be rendered at the server first to work, but my use case require the remote url to be only known at the client (otherwise I don't need containers/microfrontend, I would just have one big monolith)

my use case is an app that features plugins, where each plugin provide its own UI, and the information about where that UI is hosted is provided over HTTP request

export default component$(() => {
    let state = useSignal<{ state: "server_state" } | { state: "browser_state", url: string }>({ state: "server_state" });

    useVisibleTask$(() => {
        // there might be auth wall before the following information is known
        // it is only known at the client/browser
        state.value = { state: "browser_state", url: "http://localhost:5174" }
    })

    return <div>
        {state.value.state === "browser_state" &&
           <Remote remote={{
               name: "does_not_work",
               url: state.value.url
           }} />
        }
        <Remote remote={{
            name: "works",
            url: "http://localhost:5174"
        }} />
    </div >
})

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions