-
-
Notifications
You must be signed in to change notification settings - Fork 4.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Server-side rendering #148
Conversation
What are the options for reusing elements created by the server? Wouldn't we have to diff the DOM against the client-side changes? I suppose if we know it's pre-rendered we can just skip the initial rendering and instead just grab the element (assuming we can find it.) |
I was wondering about something along the lines of the following pseudo-code: <!-- for a template like this: -->
<p>foo</p> var children = [ ...target.childNodes ];
var p;
var text;
if ( children[0] && children[0].nodeName === 'p' ) {
p = children.shift();
var p_children = [ ...p.childNodes ];
if ( p_children[0] && p_children[0].nodeType === 3 && p_children[0].data === 'foo' ) {
text = p_children.shift();
text.data = 'foo';
} else {
text = document.createTextNode( 'foo' );
p.appendChild( text );
}
while ( p_children.length ) detachNode( p_children.pop() );
} else {
p = document.createElement( 'p' );
text = document.createTextNode( 'foo' );
p.appendChild( text );
target.appendChild( p );
}
while ( children.length ) detachNode( children.pop() ); Which is pretty horrendous, though someone smarter than me could probably do a much better job. I'm curious about whether hydration has tangible benefits over simply trashing the server-rendered DOM. Does anyone know of any research into this? Here's how Vue deals with hydration, incidentally. Anyway, hydration is something we can tackle down the road – will merge this in for now and raise an issue for the CSS stuff. |
@Rich-Harris bootstrapping server side code would be awesome. The main benefit is that in many cases it allows the DOM to be intractable after the first meaningful paint. Basically a user can begin filling out forms (and interact with some pure css components) while the JavaScript is downloading. I have often been able to substantially improve perceived performance setting this sort of bootstrapping up and also leverage above the fold css components (accordions, toggles, menus, modals, etc). Another big benefit of bootstrapping from the server is that you could allow full page rendering (building the entire DOM with svelte). This opens up the ability to edit things like header information easily and also makes code bases very isomorphic. I'm going to be playing around these next few days with a Svelte+Rill combination and am excited to dig deeper. Looks like an awesome framework! |
This is a slightly bigger PR than just adding SSR, because we need to shuffle some files around. But the tl;dr is that you can now render Svelte components in Node.
How to use it
Note that components don't have the same API that they do in the browser, because they're doing a different job. Rather than being stateful, you call the
render
method anew each time you want to generate HTML.You can use default
data
,helpers
,computed
properties, nestedcomponents
and so on. The lifecycle hooks (onrender
andonteardown
) are not called.How it works
Just like the main Svelte compiler, the SSR compiler generates code specific to the component – though in this case, it has a much easier job which is to concatenate strings together.
Using
require.extensions
makes it nice and easy for nested components to work, without the app developer having to mess around adding resolver hooks and whatnot.Things to be aware of
<style>
tags are not currently supported. Coming soon. One of the things I'd like to do is make it possible to extract encapsulated styles from a component tree so that it can be rendered to a single CSS block, either as a standalone.css
file or as inline styles. There's a couple of pieces that need to be moved into place first thoughrequire.extensions
hooks that intercept.html
files, this will probably not end well. We'll figure out a way to handle that eventually, but for now I expect that's an imaginary problemimport
declarations are transpiled to the equivalentrequire
statements, meaning your components' dependencies will need to be Node-friendly otherwise your app will blow up. (If you're using browser-specific stuff inside methods or lifecycle hooks, that's fine – just as long as the mere presence of those dependencies doesn't break Node when they load. In most situations, you'll probably be fine.)