Comments (7)
I thought about this some more and refined the idea a bit. What this boils down to is to support components as props to partially hydrated components. Not all components can be passed in as props, only those that don't need to be interactive. These can be marked by a special HOC.
withHydrate
will allow props and children which are marked by the special HOC. For these components, it will:
- Render them to an HTML string
- Encode it with something like base64 (otherwise the hydration marker breaks)
- Add a special JSON object to the hydration marker (something like
{"content": base64 encoded html, "__microsite_component": true}
).
On the client, the hydration logic will:
- Identify special JSON object
- Decode it to HTML
- Parse them into a VDOM/simple component (with something like
preact-markup
) (this is optional, the alternative is just to use dangerouslysetinnerhtml) - Pass them as arguments to the hydrated component
This lets you write normal components for partial hydration and have component props "magically work" to some extent. Obviously it's a bit complex and it would possibly introduce a new dependency (preact-markup
), but it would remove the restriction that props to hydrated components need to be simple JSON.
This would remove the 3rd caveat from the Automatic Partial Hydration
docs (to some extent).
from microsite.
This is a very awesome idea! I'm thinking this over, but your proposed implementation sounds right to me. I will start kicking the tires on this one 😄
from microsite.
I tried out some of the encoding ideas for a proof-of-concept. Not really in a shareable format yet, but I'll try and setup a branch or something. A few extra notes:
- The special encoding/decoding is actually really easy because of JSON reviver/replacer. For the encoding, I ended up not using a special HOC but rather just using the components directly and using
Preact.isValidElement
to decide when to encode to base64 (and add the__microsite_component
tag). - This needs an extra dependency in microsite runtime. AFAIK it's not possible to use dangerouslysetinnerhtml on a fragment (which means that the parsed HTML will always end up with a wrapper element). So the runtime will either need a dependency like
react-dom-fragment
orpreact-markup
to make this work. I thinkpreact-markup
is the neater option, especially since it allows the VDOM to be updated incrementally. - If the component being encoded contains a
withHydrate
anywhere inside it, there's the potential of weird things happening (possibly, haven't properly tested it). It doesn't find the parent hydrated component (since the rendering happens out-of-order). There needs to be some logic to detectwithHydrate
used in component props and error on it. An easy way to detect this might be to wrap component props with aHydrationContext
before rendering it to a string. Then nestedwithHydrate
can be detected in the same way as it currently is.
from microsite.
I created #148 for something tangentially related to the third point. Even if you choose to do it, using withHydrate
inside a component prop should be an error, because there is no chance that the prop is hydrated (since it is statically rendered on the server and passed as plain HTML), so the code will need a special case for that.
from microsite.
Nice! Excited to see what you've been playing with.
One other idea I've been thinking about in regard to optimizing hydration is somehow replacing any non-hydrated components with a noop
component using Preact's shouldComponentUpdate
to opt out of any DOM mutations for static components. Preact's hydrate
function does not try to reconcile the DOM so what was SSR'd won't be wiped out.
The client would render the entire component tree like a typical Preact app, but all static stuff would be removed via treeshaking. That would have the added benefit of all context
working normally and not needing to worry about nested hydration. The withHydrate
HOC would only instruct Microsite not to convert a given component to a noop
. Still need to explore how lazy hydration would work, though!
from microsite.
I like the tree-shaking idea as a different way to do hydration with less caveats. However, I don’t think it solves this particular problem.
In this case, I want to avoid hydrating children of a hydrated component. I’m not entirely sure how that would work with the tree shaking idea. I don’t think they are mutually exclusive, but at some point I think the work to serialise/deserialise children would have to be done (with the alternative being to not support it, which would be a shame).
I guess in that world, the default could be to treat children as rich components and have Preact hydrate them normally and introduce a HOC/wrapper to mark them as fully SSR?
from microsite.
I've made a minimal (hopefully working) PoC here.
It currently doesn't work because I can't figure out how to pass the new dependency (preact-markup
) to microsite-runtime.js
. But this is the implementation other than that (I tested it without preact-markup
, by just using a wrapper div
)
from microsite.
Related Issues (20)
- Remove defer from inline scripts HOT 3
- Move `microsite-templates` into this repo HOT 1
- Doesn't do the thing 🙃 HOT 3
- Partial hydration causes Preact to be fetched twice HOT 10
- production build fails when CSS module is imported on multiple pages HOT 2
- getStaticProps + node builtins + dev server fails HOT 1
- Preact import regex matches too much HOT 2
- Preact CDN lookup fails for non-hardcoded submodules HOT 1
- getStaticPaths uses module’s path when returning params object HOT 1
- [RFC] Built-in Markdown/MDX Support HOT 2
- Dynamic routes won't work in dev mode HOT 4
- Hydrated component isn't initialized in prod builds when it is exported/imported under a name different from the name of the component it decorates HOT 6
- Make withHydrate a no-op when nested rather than an error
- Hydration fails with nested props arrays/objects HOT 7
- Build fails with "Error: You must supply options.input to rollup"
- import.meta.env.SSR is true on the client HOT 1
- Preact modules are loaded with `modulepreload` even if they're not used
- dev server fails to load fetch HOT 1
- Add SCSS/SASS support?
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from microsite.