hexops / vecty

Vecty lets you build responsive and dynamic web frontends in Go using WebAssembly, competing with modern web frameworks like React & VueJS.
BSD 3-Clause "New" or "Revised" License
2.8k stars 143 forks source link

Server-side rendering #23

Open slimsag opened 8 years ago

slimsag commented 8 years ago

Useful for two reasons:

  1. Needed for quicker page loads (other option is code splitting).
  2. Needed for compatability with web scrapers such as search engines etc.
dmitshur commented 8 years ago

I've suggested this idea to @neelance too, and we discussed it. @neelance told me it's a nice to have that is more long term, because it requires quite a bit if work that is completely separate from everything else.

This is primarily because of the difference between properties (what this package currently deals with at runtime) and attributes (what needs to be specified in static HTML).

Have you already had that conversation too @slimsag, or is the above info new to you?

slimsag commented 8 years ago

Yes, I've had a pretty similiar conversation.

I'm not 100% convinced that it should be put off until later (there might be unforeseen issues), but I do agree it's not the highest priority.

influx6 commented 8 years ago

What would the current approach look like, will there be a backend DOM library to provide the similar features that the HTML Dom library requires or will a headless rendering engine be used to get the rendered page and serve + cache also

slimsag commented 8 years ago

@influx6 I don't know exactly what the approach would look like. Using a headless rendering engine would not make sense at all, though. We would want to generate an HTML page from components and then reconcile those properly client-side in JS when the page loads attaching event listeners etc.

influx6 commented 8 years ago

I see @slimsag

influx6 commented 8 years ago

When thinking about this feature, the key is to have some kind of marker for the markup being generated that allows markup generators on the client to identify their markup counterparts from the server, this will allow you to either do a initial re-rendering on the client thereby letting the client side take over or continue to use those until a update forces a re-render, but I prefer the former,because each markup rendering take ownership and binds the necessary event handlers, the only problem is having a identification system that persists from server to client and over multiple runtime execution.

These is majorly the problems I faced when I tackled this issue. Hope this information helps, am not so sure yet how we should bring this feature into Vecty

slimsag commented 8 years ago

IIRC React made some changes recently such that they do not need the react-id's anymore. Should look into their new impl and see how exactly it works if it doesn't use the react-ids, I bet their experience could point us in the right direction

EDIT: I was wrong! They still use react-id's for server-side-rendered components.

slimsag commented 8 years ago

Found it -> @bep mentioned it in another issue https://github.com/gopherjs/vecty/issues/20#issuecomment-207502734

influx6 commented 8 years ago

Also, Luna notified me some months back that web scrappers, mainly all major search engines, run your JS first before crawling the pages, so let this focus on code splitting as this is not really anymore an issue.

slimsag commented 7 years ago

From http://stackoverflow.com/a/1785101/5905344

JavaScript is handled by both Bing and Google crawlers. Yahoo uses the Bing crawler data, so it should be handled as well. I didn't look into other search engines, so if you care about them, you should look them up.

The complexity we would gain from this may not be worth it. It might be easier to suggest that users create static versions of their website with e.g. html/template should they want both.

slimsag commented 7 years ago

I'm marking this as I currently see it. Discussion welcome.

influx6 commented 7 years ago

It's possible, Just just have to be willing to disconnect your implementation from the core browser DOM

On Nov 13, 2016 00:35, "Stephen Gutekanst" notifications@github.com wrote:

I'm marking this as I currently see it. Discussion welcome.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/gopherjs/vecty/issues/23#issuecomment-260155903, or mute the thread https://github.com/notifications/unsubscribe-auth/AAICLVX34ZcW5Dsj4WNOYpuJ8lq30o53ks5q9k04gaJpZM4HZkR3 .

slimsag commented 7 years ago

I see no reason to keep this issue around, except maybe in a FAQ of sorts. Let's close and anyone who has new ideas / thoughts around this can create a new issue or chat in #vecty on Gophers slack :)

slimsag commented 6 years ago

Back when I closed this issue, I closed it mostly on the grounds that:

  1. More and more search engines are beginning to execute JavaScript, and as such server-side rendering matters less and less in terms of SEO.
  2. Getting server-side rendering in a Vecty application working will likely be harder than just using html/template and serving an SEO-friendly version of your data.

But I quickly after closing this issue realized that the above does not cover the other primary use case of server side rendering: initial page load time.

A JavaScript bundle (especially GopherJS bundles) are quite a bit larger than a server-side-rendered HTML page. This transfer + render time can add 1s or more to page load times, which isn't great.

I think to be competitive we may have to offer a solution to this eventually, but it's not exactly clear what it would look like today.

dmitshur commented 6 years ago

Another important (IMO) benefit of server-side rendering is that it enables a gradual transition path for developers. If vecty rendering API allows for server-side rendering, then users can:

  1. Start with rendering HTML on server as they currently do, e.g., via html/template.
  2. Rewrite parts of their HTML rendering to use Vecty rendering API.
  3. After having a good experience and becoming more familiar with it, finish rewriting all their HTML rendering to use Vecty API, while maintaining existing behavior.
  4. Easily switch to or add frontend rendering, while reusing Vecty rendering code.

Without server-side rendering, users must:

  1. Start with rendering HTML on server as they currently do, e.g., via html/template.
  2. Rewrite their entire application to use Vecty API and move rendering to frontend. All in one huge step, and hope functionality doesn't break, and not able to see and evaluate partial results until a lot of work is done.

Of course, this assumes a server-side HTML rendering starting point. If users start with frontend rendering, e.g., via React, then this isn't applicable.

slimsag commented 6 years ago

Other things to consider here:

  1. With WebAssembly support eventually coming to Go, bundle sizes may be less of a problem (but probably still enough of a problem to warrant trying some server-side rendering).
  2. If we have to offer a solution for this, it will probably require some API changes or else we will end up with some duplicated / ugly methods in the Vecty API. So I'm tagging as 1.0 just to figure out what APIs would need to be in place before supporting this.
glycerine commented 6 years ago

you've probably seen https://github.com/olebedev/go-starter-kit/ which does react/server side rendering using goja. Might provide some inspiration/go code to borrow (MIT licensed).

progrium commented 6 years ago

Why can't we render the page and just let that first update on the client side blow it all away? They'd presumably start with the same state.

slimsag commented 5 years ago

https://github.com/rendora/rendora

pdf commented 5 years ago

Ouch, that's the brutal way of doing it (headless chrome).

slimsag commented 5 years ago

(Just thought it was interesting and relevant, not making any statements about its efficacy)

gh67uyyghj commented 5 years ago

brutal

it's probably the most logical and performant way to do ssr now, headless chrome on docker only takes around 200MB and rendora takes another 16-20MB of RAM, that's about it and the latency is below 100ms for my use case.