Skip to content

feat: support rendering of dynamically referenced Stencil components #5246

@christian-bromann

Description

@christian-bromann

Prerequisites

Describe the Feature Request

Given I have a functional component like:

import { h } from '@stencil/core';

const CmpA = () => {
    return (<div>Hello World</div>);
};
export default CmpA;

which is re-exported in a "barrel" file like so:

import CmpA from "./help";

export const Components = {
    cmpA: CmpA
}

and then rendered in a components as follows:

import { Component, h} from '@stencil/core';
import { Components } from './components';
@Component({
  tag: 'my-cmp',
  styles: `svg { height: 24px; }`,
})
export class Icon {
  render() {
    const CmpA = Components.cmpA;
    return (
        <CmpA />
    );
  }
}

CmpA will not be fully rendered or rendered with flaws as Stencil doesn't fully analyses components imported by reference as shown above.

Describe the Use Case

Stencil analyses components, their child components and dependencies of them as a after step of the TypeScript compiler. The convertStaticToMeta method takes apart all details of a component and parses this metadata into an object that is later important for rendering the component and optimizing the output.

This mechanism works as long as we import a component and use it directly within the file. However once we attempt to reference a component that is imported from a while that has no component defined in it, e.g. a "barrel file", the Stencil compiler doesn't further analyse the imported component dependency and won't be able to correctly render the component.

Note: this limitation only effects functional components. Composing class components works without imports and can be seen as best workaround to this problem.

Describe Preferred Solution

Without having spent much time thinking about various option and alternatives, nor having in depth knowledge about all parts of the Stencil compiler, some initial thoughts on this would be:

  • either change the Stencil compiler to output components so they can be consumed independently e.g. as a standalone component without requiring the consumer to know anything about it
  • improve the component parser and e.g. follow up on imports, find the object behind it and trigger the parsing if object turns out to be a component

Describe Alternatives

An alternative consideration is to say Stencil won't support this since, it is actually not really needed. Based on the docs:

Components can be composed easily by adding the HTML tag to the JSX code. Since the components are just HTML tags, nothing needs to be imported to use a Stencil component within another Stencil component.

Related Code

This issue was brought up by #3953 describing a use case specific for SVG. Provided reproducible example can be used to work on a resolution for this.

Additional Information

When looking into #3953 I realised that the described bug is more general and requires a larger engineering effort. I requested advice from the Stencil team and we concluded to create this new feature request for us to be ingested into the backlog and re-prioritised.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Feature: Want this? Upvote it!This PR or Issue may be a great consideration for a future idea.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions