Closed WorldSEnder closed 3 years ago
There're a couple issues that prevents a Context
or StyleSheetManager
approach:
I think there're a couple potential solutions:
StyleOptions
/ StyleBuilder
(Works universally, but difficult / unergonomic to use)yew::agent
or Arc<Mutex<>>
, might need unsafe if storing web_sys::Element
).There're a couple issues that prevents a
Context
orStyleSheetManager
approach:1. There's no Context in Yew 0.18 (only agents). 2. To use a Context, the API needs to be either a Component or a hook.
I'd say that's a problem for the bindings, sure, but will be fixed in the upcoming version of yew. Inside stylist
I'd prefer to see a binding agnostic solution (also so it's easier to adapt to potential server side rendering when that comes up). E.g: some kind StyleSheetManager
trait coming from stylist
. Implement it for a dummy struct GlobalDocumentManager
that replicates the current behavior of mounting to window().document().head()
. Add an additional mount(&self, &dyn StyleSheetManager)
and forward to that in mount(&self)
. Up to debate: how to ensure that the same manager is passed to unmount
and the interaction with unregister
.
For the yew-bindings, there could be a impl StyleSheetManager for ComponentManager
where ComponentManager
holds a ComponentLink
and the impl implements idea (3) of using the link to detect the iframe in which the component is rendered in (or fowards to the context whenever yew is updated).
I'm not sure Style
itself should be the "smart" part that knows where to mount:
Sheet
in a global cache. Don't wanna do that too oftenStyle
already holds an Arc
so that can be used as the identity later on instead of the SheetStyle
, but the place to mount is sensitive to that userLet me know what you think :)
I have added an experimental implementation of StyleManager in the manager branch. You can see the example below for usage.
https://github.com/futursolo/stylist-rs/blob/manager/examples/yew-shadow/src/main.rs
Let me know if it works.
- Creating a new Style is kinda expensive since it looks up and compares the Sheet in a global cache. Don't wanna do that too often
- On the other hand Style already holds an Arc so that can be used as the identity later on instead of the Sheet
- Multiple components want to use the same Style, but the place to mount is sensitive to that user
I am not sure if looking up cached Styles in the Registry is "expensive".
During the rewrite, I kept the StyleRegistry
to reduce mounting (and parsing in the past).
Looking up cached Styles in the Registry is a simple HashMap look up and a clone of Arc'ed reference, even with Rust's default Hashing algorithm being "slow", there should be no problem to facilitate millions of look ups per second.
I wrote some simple benchmarks, which is now available on the master branch, on my machine, the benchmark gives me the following result:
Benchmark | Result |
---|---|
Parse Simple (100,000 iterations) | 150.000ms |
Parse Complex (10,000 iterations) | 162.000ms |
Cached Lookup (1,000,000 iterations) | 371.000ms |
Mounting (1,000 iterations) | 177.000ms |
With the benchmarks above and my comments in #14, I think we have established that:
StyleRegistry
.If you have a case where the cache is slow, please let me know.
I want to use stylist for elements that are quarantined in an
iframe
. The problem with the approach taken with the currentmount
is then that the wrong document is used, i.e. the top-level document instead of the one of the nested iframe.Further in the future, when server-side rendering is available in yew, yet another context - a server-side stylesheet container attached to the request - should be used when mounting an element.
Somehow, a
Style
must thus have a sense of in which context it is used and do the correct thing in each case. In material-ui this is done using aStyleSheetManager
which is obtained from the context of a component, I believe falling back to document->head if none is found.