ivi
ivi copied to clipboard
Is it possible to render to documentElement directly?
In my previous experience with VDOM I creating isomorphic apps which attaches at root node of document (i.e. html). I suppose it should works in same way with ivi too. But I don't fully understand how ivi operates with existing DOM which is result of server side rendering the same app.
import {render} from 'ivi';
import {main} from './main';
render(main(), document.documentElement);
Where my main()
function looks like so:
function main() {
return html(_, _, head(...), body(...));
}
I get next error on client:
Uncaught Error: Container element should be attached to the document
at scheduler/index.js:240
ivi
doesn't support rendering into the documentElement
or directly into body
because there are many issues. One of the major issues in Safari were fixed just recently, but there are still many other issues.
Also, ivi
doesn't support rehydration because in many use cases it isn't worth it. So I'd recommend to just remove everything with appContainer.textContent = ""
and rerender everything.
Thank for explanation.
It sounds reasonable but I have some problems related to isomorphic apps. At least I need set content of meta nodes and title, which varies for different pages. I mean the isomorphic way to do it both on client and server from component point of view. It is very easy when we render (or patch) full page content beginning from html node. I suppose we can create some directives (like META, TITLE) to help with it but it doesn't looks clear. I think, first I can try to use props or context to do it.
I suppose we can create some directives (like META, TITLE) to help with it but it doesn't looks clear.
useEffect()
hooks are ignored during SSR.
const useDocumentTitle = (c: Component) =>
useEffect(c, (title: string) => {
document.title = title;
});
const App = component((c) => {
const setTitle = useDocumentTitle(c);
return (title: string) => (
setTitle(title),
h1(_, _, title)
);
});
Thank you for hints.
Despite the title content cannot be set directly to title node on server environment the app still need an isomorphic way to provide it for rendered page content.
I think that tradeoff solution it providing some interface with methods (like setTitle
, setKeywords
and etc.) through props or context. The implementation of this interface will be fully different for client and server.
And of course, in this case it is not an ivi care at all.
On the server you can render entire page and it will ignore useEffect
hook:
const FullPage = (t: string) => (
html(_, _, [
meta(_, _, [
title(_, _, t),
]),
body(_, _,
div(_, { id: "app-container" },
App(t),
),
),
])
);
renderToString(FullPage("Title"));
And on the client:
const container = document.getElementById("app-container");
container.textContent = "";
render(App("Title"), container);
ivi doesn't support rendering into the documentElement or directly into body because there are many issues. One of the major issues in Safari were fixed just recently, but there are still many other issues. Also, ivi doesn't support rehydration because in many use cases it isn't worth it. So I'd recommend to just remove everything with appContainer.textContent = "" and rerender everything.
this is a lot of FUD based on how React is/was unable to deal with third-party <body>
and <head>
augmentation. in my own testing, i was not able to come to the same conclusion as that google article, at all.
the perf and ux benefits of hydrating rather than re-rendering are significant, and i have found 0 issues so far in doing it. there are some tiny quirks like if you need to change <title>
afterwards, then textContent has no effect (you have to set document.title
), but it's amazing how everything "just works".
I using rehydrating long time starting from react 0.x and I use it with snabbdom-based apps up to now. Of course, the browsers usually doesn't allow us grossamer things like creating/removing nodes in/from head node, but simple attributes modification works fine.
I tried to change title like so:
document.head.querySelector('title').textContent = "new title";
...and this works with chromium and firefox. Which browser has problems with it?
the perf and ux benefits of hydrating rather than re-rendering are significant, and i have found 0 issues so far in doing it.
It is not about hydrating vs re-rendering, I just don't see any value in SSR except for SEO purposes. Creating good UX with isomorphic rendering is an insanely complicated task that requires injecting small scripts that collect events and provides early feedback to user interaction.
Of couse at present time the main purpose of SSR is a SEO, but also it helps give partial support of user-agents without JS. But because there no reliable way to determine user-agent capabilities (like JS support) using only data from request we need render pages on the server at least for each new client.
I agree, maybe, rehydrating not so valuable in this case.
It is not about hydrating vs re-rendering, I just don't see any value in SSR except for SEO purposes.
if you are building an SPA, like something behind a login that only needs to render the full page once, then i agree that SSR is a waste of time since it will only improve a single load for a potentially multi-hour session. however, if you're using a vdom layer to build a multi-page app or a more traditional site, then SSR is the main way to render and rehydration provides huge UX and perf benefits, not just SEO.
Creating good UX with isomorphic rendering is an insanely complicated task that requires injecting small scripts that collect events and provides early feedback to user interaction.
maybe if you're building photoshop or a 3d editor, then it is due to the massive amount of intricate state. but i can tell you from building out a pretty js-featured ecommerce site that this is not the case at all. i'll ping you when we launch it in a few months and you can test for yourself to see if the google article's claims hold up. i'll even spend an extra day making a version for you that re-renders instead of rehydrates and you can compare (though this could be a tricky since it currently renders <html>
itself. we'll see.
i would also add that claiming that a framework can do SSR, implies ability to do re-hydration (the difficult part), not the easy part of walking a vtree and barfing out markup ;)
maybe if you're building photoshop or a 3d editor, then it is due to the massive amount of intricate state.
This techniques were used even before React/isomorphic rendering on sites like Flickr. Displaying pages without any visible feedback for user interactions until main javascript is loaded on slow networks is a terrible UX.
i'll ping you when we launch it in a few months and you can test for yourself to see if the google article's claims hold up.
"SSR’d pages often look deceptively loaded and interactive, but can’t actually respond to input until the client-side JS is executed and event handlers have been attached. This can take seconds or even minutes on mobile."
i'll even spend an extra day making a version for you that re-renders instead of rehydrates and you can compare
re-rendering probably won't work with many edge cases like scroll positions. I know that it is a broken technique.
This can take seconds or even minutes on mobile.
we have a ton of features (gallery, touch carousel, modal overlays, nested tabs, off-canvas nav menus, 100 products on a single page, a shopping cart, a chat). the entire scripting time on pageload for script parsing/compiling & hydration is 10ms on desktop and 25ms on 2015 mobile, and 4.5Mbit 4G connection. the weight of the entire page without images (js, css, html) is < 20k. the total number of requests is 5 (all over http2), without images. this is a fully responsive site. the DOM size is < 700 on the busiest pages and more typically just 400 nodes.
by the time you have even 100ms of scripting time during page load, you're already doing a lot of things wrong.
for "typical" sites, none of this applies because they're universally complete shit in terms of perf anyhow.