bug: taskQueue: 'immediate' causes lifecycle events out of order
Prerequisites
- [x] I have read the Contributing Guidelines.
- [x] I agree to follow the Code of Conduct.
- [x] I have searched for existing issues that already report this problem, without success.
Stencil Version
4.25.0
Current Behavior
When taskQueue: 'immediate' is set in the configuration and lazyLoad is false then the render method is called before the connectedCallback is called.
In https://github.com/ionic-team/stencil/blob/v4.25.0/src/runtime/bootstrap-custom-element.ts#L91 the component is initialized before the originalConnectedCallback is called. When the component is intialized the first render is scheduled at https://github.com/ionic-team/stencil/blob/v4.25.0/src/runtime/initialize-component.ts#L187 and happens synchronously, so render is called before connectedCallback is called for the first time. This seems inconsistent with the documentation, and is a problem because any initialization code in connectedCallback is not run.
We want to use taskQueue: 'immediate' so that web-components behave more like regular HTML elements, in particular appearing in the DOM synchronously. The delayed rendering of taskQueue: async causes a lot of extra complexity around things like measuring the size of DOM elements that contain web components.
Expected Behavior
Lifecycle callbacks should be called in order, even with taskQueue: 'immediate'.
System Info
Steps to Reproduce
Use taskQueue: 'immediate' in stencil.config.ts.
Code Reproduction URL
https://github.com/k1w1/lifecycle-order-bug
Additional Information
The reproduction repo shows the problem. Note that you must explicitly visit /src/index.html to see the component run. Here is a screenshot of the output showing the out-of-order lifecycle callbacks.
@k1w1 thanks for raising the issue. Are you setting taskQueue: 'immediate' for any particular reason?
We have been using Stencil for a long time, very successfully, but one thing that has caused a lot of confusion to our developers, and complexity in our code, is that rendering is asynchronous. Our code mixes regular HTML and web-components. Code that works fine when you wrap regular HTML doesn't work when you wrap web components, e.g. because if it tries to measure the size of the children the result is wrong if you don't wait for the first render. This takes code that is simple when working with HTML and makes it more complex when web components are involved. Many of the people on our team (myself included) thought this was just a drawback of web components in general, and it was with surprise that I recently realized it was coming from Stencil.
With the component library our first priority is developer ergonomics - that is the reason to use a component library in the first place - and so the desire to use immediate rendering is to better match regular HTML.