Road to v5 š
This issue is a tracking issue to collect feedback for potential breaking changes and new features in Stencil v5. We appreciate everyone interested to participate and comment on urgent issues or often requested features they would like to see in the new major version. We will collect all acknowledged issues in here and resolve comments that mention it.
Accepted v5 Bug Fixes / Features / Breaking Changes
- Support for Scope Elements (see #2957)
- remove
dist-typesoutput target (already invalid output target, but remains are still around)
Under Consideration
- Support importing JSX classes and use them to reference Stencil components in JSX - current state: more investigation needed to validate how we can provide type support, see branch
cb/jsx-object - Migrate to new compiler as Stencil is currently using an old Rollup version - current state: general acknowledgement within the Stencil community, however we need to validate whether we should migrate to something new like Rolldown or continue with Rollup and work on update the version
Really happy to hear that the StencilJS compiler will finally be updated! Weāre looking forward to significant improvements in development performance. Also, the ability to import JSX classes to reference Stencil components is an amazing feature.
Thank you, StencilJS team, for your hard work!
Rolldown would be a great choice for the new StencilJS compiler! Since it's built in Rust, it offers significantly better performance than Rollup, which is JavaScript-based. This means faster builds, lower memory usage, and improved scalability, especially for large projects.
Additionally, Rolldown maintains compatibility with Rollupās plugin ecosystem while leveraging Rustās speed, making it a practical upgrade with minimal migration friction. Given Stencilās focus on performance, adopting Rolldown could be a major step forward.
Looking forward to seeing the compiler improvementsāthank you for considering this upgrade!
I would like Stencil to remove (or at least deprecate in preparation for removal) a bunch / most of the extras:
-
experimentalSlotFixes< rename toscopedSlotFixes. Encompasses all current slot polyfill behaviour.trueby default when anyscoped: truecomponent is detected. -
appendChildSlotFix< remove -
cloneNodeFix< remove -
enableImportInjection< change totrueby default -
experimentalImportInjection< remove -
experimentalScopedSlotChanges< remove -
scopedSlotTextContentFix< remove -
scriptDataOpts< remove -
slotChildNodesFix< remove
Related, I'd like Stencil to mark as deprecated (or remove) a few of the slot monkey-patches.
I think Stencil should concentrate on the minimum footprint required to make scoped: true components work in all the environments / libs they need to - not shim the whole DOM api.
-
patchSlotInsertAdjacentHTML< deprecate or remove -
patchSlotInsertAdjacentText< deprecate or remove -
patchSlotInsertAdjacentElement< deprecate or remove
^ perhaps we could add a hook which Stencil would call, allowing users to add more if they require them?
Lastly, I think it would good for Stencil to unify / simplify scoped: boolean | shadow: boolean
Prepare for the removal of:
@Component({
tag: 'tag-1'
})
@Component({
tag: 'tag-1',
scoped: false,
})
@Component({
tag: 'tag-1',
shadow: false,
})
Potentially changing the api to something like:
@Component({
tag: 'tag-1',
scoping: 'shadow' | 'class', // more could be added later - 'shadow-closed' etc
})
I would like Stencil to remove (or at least deprecate in preparation for removal) a bunch / most of the extras:
šÆ a question: are we removing patches like experimentalScopedSlotChanges because there is no need for them anymore, because you have been fixing them or because experimentalSlotFixes contains all the fixes already?
^ perhaps we could add a hook which Stencil would call, allowing users to add more if they require them?
Do you mean like a extra package / plugin for folks who want to use scoped components?
Lastly, I think it would good for Stencil to unify / simplify
scoped: boolean|shadow: boolean
IMHO all Stencil components should be shadow by default. Users can switch them to scoped components by setting scoped: true. Wdyt?
are we removing patches like
experimentalScopedSlotChangesbecause there is no need for them anymore, because you have been fixing them or because experimentalSlotFixes contains all the fixes already?
At the moment to get the best / most consistent behaviour from scoped: true components you need to apply both experimentalScopedSlotChanges (does a bunch of vdom improvements) and experimentalSlotFixes (activates all the polyfills in dom-extras).
I, as someone who knows stencil pretty well, have no idea why experimentalScopedSlotChanges and experimentalSlotFixes are separate š
.
I'm guessing it's not obvious to others coming from outside that they should apply these 1) at all 2) why they need both.
Also add to this that that Stencil runs all it's internal tests with these 2 flags on all the time now, it'll make our (Stencil devs) lives much easier and more determinative.
Do you mean like a extra package / plugin for folks who want to use scoped components?
I haven't thought about it much so maybe it doesn't make sense, but I just mean some kind of config hook / function that users can leverage...
When Stencil monkey patches it's scoped: true component prototypes, we could call the user hook.
This would allow users to provide their own monkey-patch for innerHTML or whatever. We could provide an example in the docs.
IMHO all Stencil components should be shadow by default. Users can switch them to scoped components by setting scoped: true. Wdyt?
Yeah - as a default that makese sense. But still tweaking might make sense(?)
e.g. We don't want scoped: false and it might be good to have something more extensible for the future (e.g. for shadowRoot#closed)
it'll make our (Stencil devs) lives much easier and more determinative.
Afaik these patches were introduced as feature flags for users to opt-in because they had breaking character. v5 allows us to "merge them in" and consolidate this tech debt. If you suggest to make these patches the "default" behavior, I am all in.
This would allow users to provide their own monkey-patch for
innerHTMLor whatever. We could provide an example in the docs.
Is this something a common StencilJS user would do? My only concern is that opening up these hooks to users means we introduce interfaces that require maintenance and documentation when it is not clear how much this would be actually useful for a common Stencil user.
We don't want
scoped: falseand it might be good to have something more extensible for the future (e.g. forshadowRoot#closed)
I see. That makes sense, especially the extensibility part. scoping: 'shadow' | 'class', // more could be added later - 'shadow-closed' etc makes most sense to me then, making "shadow-open" the default choice.
My original desire was it to keep the upgrade effort minimal, while not dragging old interfaces (scoped: true) along into v5. With this, every large project that uses scoped: true would need to go through all files and change the value. However we could create a codemod for this, e.g. npx upgrade-stencil v5 to help make this process seamless.
Is this something a common StencilJS user would do? My only concern is that opening up these hooks to users means we introduce interfaces that require maintenance and documentation when it is not clear how much this would be actually useful for a common Stencil user.
Agreed - let's not make more work before we need to!
My original desire was it to keep the upgrade effort minimal, while not dragging old interfaces (scoped: true) along into v5. With this, every large project that uses scoped: true would need to go through all files and change the value. However we could create a codemod for this, e.g. npx upgrade-stencil v5 to help make this process seamless.
Gotcha, happy to 'just' make shadow: true the default / deprecate the other options for now if that simplifies things
Gotcha, happy to 'just' make
shadow: truethe default / deprecate the other options for now if that simplifies things
You are right though when it comes to extensibility. It makes sense to have ensure we can seamlessly add "closed" shadow roots in the future.
One thing I like about stencil about ShadowDOM. I got introduced to ShadowDOM through stencil. However functional component doesn't support shadowDOM.
For example, if I am creating a Button component or some DUMB component without a state or lifecycle hook, I would like to use functional components but I don't want to missout shadowDOM. Can you add support for this.
One issue with shadowDOM I have noticed is we don't need to do exportparts="somepart" to access the child components' part in CSS file.
I have tried giving the exported parts a name like this below image. source: https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/exportparts. But I can't access the part in CSS with those customNames.
Can you do something about it?
Can you add support for this.
I am not sure what you like to see here. Functional components don't define a CSS file, so there would be no reason to wrap them into a Shadow DOM. Maybe you can provide more clarity providing a concrete example.
Functional components don't define a CSS file, so there would be no reason to wrap them into a Shadow DOM.
Yes. This. Can we add support for shadowDOM in functional Component. As of now we can't do that. Shadow DOM stops outside styling to affect component styling. Functional compoenent are the best cases when we need to use Dumb component which takes data and render it.
Would the support for "importing JSX classes" have an option to import it without shadowDOM?
Here i'm thinking a case would be if i have a custom label component and i want to import it into a custom input component, it cannot be shadowDOM enabled due to shadowDOM restrictions, and that would break references like "for" "aria-describedby", "aria-labelledby" etc which makes it impossible to be accessible compliant and reuse components.
Only way forward currently I see is that one maintain "two of the same component" label-base.tsx (no shadowdom) -> label.tsx (enables shadowdom) label-base.tsx (no shadowdom) -> input.tsx
I would like to see the browser support policy be updated for v5: https://stenciljs.com/docs/support-policy#browser-support
Stencil is using some features like adoptedStyleSheets that didn't exist until iOS 16.4, but Stencil v4 supports iOS 14+, so it needs fallbacks.
In addition Chrome 98 is very, very old without mutable adoptedStyleSheets https://github.com/stenciljs/core/issues/6326
More ideas :)
- An experimental flag to enable
Rolldown - An experimental flag to enable
typescript-go - Removal of CJS bundles
- Run-time decorators; make the current decorators actual decorators (as well as static-analysis hooks), re-writing the current run-time reactivity logic.
- Experiments with signals (might be related to previous point)
- Potential experiments into alternative
lazy-loadersolution; using globalMutationObserverto fetch modules; removing the need to proxy components.- Would simplify a lot of the runtime logic
- Common dist / dist-custom-elements bundle < lazy loader would just be an additional thing
- Smaller initial bundles (no-more proxy, meta objects)
Would obviously need a lot of thought and perf experimenting. Could just be an additional script added to
dist-custom-elementsfor now
- Add api surface / ability to explicitly set property / attribute (and boolean handling?) within Stencil (.e.g like lit -
.prop={...},?boolean={this.isBoolean}) - Add api surface (within
@Propdecorator?) for prop / attribute serialize / deserialize - predominantly useful for SSR / hydration but has potentially other usecases. e.g. ifssrOnlyoption is set, the deserialize logic would only be present in the client bundle, the serialize logic only in the server bundle. -
slotAssignment: "manual"
A idea: "Stencil compiler plugin system":
- Extend compiler to transform components in different way e.g extend the
@Component-decorator to support additional cases which are currently not part of the compiler - API oriented not necessary to know to much about typescript AST
- but has the possible to touch the AST directly
btw @johnjenkins Lets pin the issue to give it more visibility?
Happy to see all these good ideas. Here's more (+ support some already mentioned):
-
Component class extension: to add common props, states, methods, render method, or logic to multiple components
-
Reactivity improvements: using a signal-based reactivity?
-
Transform property method in the Prop decorator: to customize the attribute transformation in any type (example: object serialization). Similar to the "transform" input option in Angular.
Component class extension: to add common props, states, methods, render method, or logic to multiple components
@mamillastre check-out 4.37 š Stencil can now extends!
Additionally, theres a new Mixin utility from core https://stenciljs.com/docs/api#other