Hacker News new | past | comments | ask | show | jobs | submit login
Show HN: Purview – A server-side component framework (github.com)
58 points by karthikksv 36 days ago | hide | past | web | favorite | 54 comments

Wait, why could we not render the HTML on the server and only let the browser to the compositing? If there only was a protocol that would allow us to exchange input events and some drawing commands over some arbitrary network.. let's phantasize for a moment and call that protocol X. I would use it when it's mature so maybe from X11 on onwards.

Naturally, sending draw commands has a big downside in efficiency. Maybe we could later exchange X with something that only sends bitmaps?

> Maybe we could later exchange X with something that only sends bitmaps?

Can we call the followup Wayland because that is the only way to go :)

So now we're stuffing sql in our react as well as html and CSS? React is on course to reinvent the PHP that everyone spent so long laughing about

A common criticism I heard about React a few years back was combining JS and HTML within the same file, as opposed to having them separate. As with most decisions, I think separation is an important trade-off you need to consider: it's easier to reason about the individual, separated parts that are well-contained, but it becomes harder to reason about the system as the whole.

If you have a complex front-end and back-end with a REST API, each time you modify a server route, you need to find all instances in your client where you make an AJAX request to that route and change them appropriately. The potential for inconsistency can cause numerous bugs.

GraphQL solves this by having a very flexible and standardized server (albeit complex), giving your client access to arbitrary structured information using a query language.

Purview solves this by moving your logic to the server-side, where you can access your database directly. Because everything runs on the server, the client-server interface is abstracted away, and you don't need to worry about using GraphQL or REST. You can make database queries, contact external services, etc. directly within your components.

To keep this maintainable, you split up your page into logical, reusable components, just like you would with React, and each component now not only contains your view logic, but also the server-side logic. Given that you've decomposed your components well, this makes it easy to reason about the whole system when it comes to any part of your page.

This is how cold fusion works, written by Adobe for too steep of a price. I wonder if we are just running circles around the same ideas. Are we really moving the ball with Purview? I’m lost.

> If you have a complex front-end and back-end with a REST API, each time you modify a server route, you need to find all instances in your client where you make an AJAX request to that route and change them appropriately. The potential for inconsistency can cause numerous bugs.

Sorry, but any sane codebase usually abstracts away HTTP info like routes through services which means that your components only know about the dataService and don't care if the data is coming from a REST API or localStorage

Personally I took a break from frontend work, I'll circle back in a few years once web assembly is ready.

The JS ecosystem is insane once you take a step back and look at it.

True, but you could move it into a model class, maybe use mobx or another state library

I've been playing around with a similar idea using nextjs. My idea was to create some kind of RPC interface with typescript that works seamlessly between server/client rendering, so during server rendering, RPC calls would just be regular function calls, and during client rendering/event handling, the calls would be made through sockets or HTTP requests.

There's a lot of criticism in this thread. I'm curious if you're using this in production. I love projects like this that really push the bounds of how these problems are typically solved.

We've been using this in production at the company I work at for about the past ~1.5 months. We've gone through a fair number of fixes and improvements throughout that time (bugs, race conditions, performance, etc.). It's definitely still a nascent project, but we're excited to continue using Purview and developing it. Would love to get your thoughts if you try it out sometime.

looks like it's the react version of https://dockyard.com/blog/2018/12/12/phoenix-liveview-intera... ?

edit: nvm, it's listed in the readme as inspiration

Yes, that was my inspiration! Chris gave a great talk about it at ElixirConf is anyone is interested in watching: https://www.youtube.com/watch?v=Z2DU0qLfPIY

Some differences compared to LiveView:

- Type-checking: there are extensive JSX typings (https://github.com/karthikv/purview/blob/master/src/types/js...) that ensure you're attaching event handlers with the correct signatures, specifying supported props, using valid HTML tags and attributes, etc. Static-typing guarantees are one of my big priorities.

- I'm not sure if LiveView intends to support nested components like React does. Having the ability to split up complex pages into components that you can nest and reuse (with mostly one-way data flow) is a key part of maintainability. I wanted to maintain a very familiar React interface, so you can pick up Purview quickly if you're comfortable with React.

Neat project! We indeed support nesting in LiveView :)

Thanks for chiming in Chris! If you don't mind, I have a few implementation questions about LiveView:

- I noticed that you said you use morphdom for LiveView. I originally started with this too, but found that the DOM diffing doesn't work well with any client-side JS that may modify the page (e.g. a date picker, a tooltip library, a custom dropdown, etc.). I ended up switching to snabbdom (https://github.com/snabbdom/snabbdom/), a virtual DOM implementation, to avoid updating parts of the page that the user doesn't directly intend to modify. This helps with client-side interop, and it also gave us a nice boost in performance. Did you run into any similar issues with LiveView? Do you still use a DOM diff rather than a virtual DOM diff?

- On that note, what's the recommend way to interop with client-side libraries like I mentioned earlier? We use the WebComponents custom-elements spec to define custom tags that encapsulate client-side JS logic (e.g. we have an <audio-player>, a <date-picker>, etc.), and then in our Purview components we can just send down these tags. We also had to provide the ability to integrate with DOM events triggered by these custom elements. Is there a recommended approach in LiveView to integrate with these libraries?

- With respect to nesting in LiveView, do you call live_render() directly within a view's render() function? Do you pass props in this call? There doesn't seem to be a differentiation between props and state for LiveView--are both consolidated into "assigns"? Hence both are mutable? I'm aware that you use immutable data structures in Erlang/Elixir, but I mean in the sense that you can assign a different value to a prop that was given to you by your parent. If this is the case, how would that work if there's a re-render and the prop passed by the parent changes?

You should have a look at JSF (Java Server Faces) that explored, and failed miserably, in the same context for the last 15 years or so. (Probably less, dunno)

I was thinking the same. I expect elixer/phoenix to easily outperform js/node. I believe with phoenix it actually makes sense what they are going, which I can't really say from this "thing".

This looks awesome, thanks for sharing! :)

> Not React compatible due to the differences listed below, so you can't use existing React components/libraries with Purview.

Existing components/libraries is the only reason I use react.

A good alternative that provides a nice setup for SSR on the initial page load as well as code splitting is nextjs https://github.com/zeit/next.js/

This smells a lot like meteor. Would love to see an actual semi-large app built with this approach.

In React, forms are often built with this pattern:

* Type/change events fire on the field (e.g. username)

* Username updates the internal model (this.username = 'karthikksv')

* The submit button fires an event so the parent page can act on the entire data model ({ username: 'karthikksv', password: 'fluffykittens' })

I'm concerned that this model won't work well using server-side React components on a network with high latency – each type event would have to round-trip to the server to update in the DOM.

Higher latency connections will certainly have longer delays, but it's quite fast on a reasonable connection thanks to the persistent WebSocket, even if you're sending each letter that's being typed. We're using Purview in production at the company I work at, and we haven't had issues with input-related delays.

If you don't need to send each letter, it's recommended to not do so; the submit event object includes all form data, so you can do one final validation at the end, similar to what you'd do with a normal web server.

Shameless plug: I have a library for server-side react-like components (https://github.com/Bloomca/welgo).

It does not help you with client side, so it is more like composable templates, but they are async, so you can query DB inside your components.

normally security would be implemented at an api level. you would have to be careful to implement that in the renderer here.

You're right, there's validation for the WebSocket messages sent to the server. For certain events (e.g. submit), the validation of user form data is left to you, just as you would normally be responsible for.

I am surprised that nobody mentions this similarly https://docs.microsoft.com/en-us/aspnet/core/razor-component...

<?php print("this is far easier lol"); ?>

I know this comment is a joke, but this is actually how react was created. Facebook made a templating language in php called xhp (https://docs.hhvm.com/hack/XHP/introduction) and some people at fb developed react as a natural extension to xhp but in JavaScript.

TIL. Thanks for sharing!

Time is a flat circle.

I'm sure there's a use case for this but, for me, it's pretty rare to need pull new data or persist anything after most events, let alone every event. A single fetch and single save is usually all that's needed.

Whenever any information needs to be saved or processed by the server, you can perform your server-side logic inline in the event handler (e.g. update the database, contact external services, etc.). There's no need to make an AJAX request and have a corresponding API route. This abstracts away the client-server interface, and you get safety guarantees with type-checking.

Looks an awful lot like old fashioned aspx pages. They're the bane of my existence. The syntax looks a lot nicer and there isn't the odd CodeBehind shenanigans so maybe it's better to work with.

Wait... Didn’t Microsoft do this back in the day with ASP.NET Web Forms?

Full circle for sure!

> What if your React components ran on the server-side?

Huh? React components can run on the server side, that is one of the primary benefits of React compared to its predecessors.

Perhaps I could've explained myself better. I meant that all the business logic of the components (i.e. event handlers, lifecycle hooks, setState() calls, etc.) run on the server, unlike just the initial server-side rendering that React provides. The server maintains the state of all components, and when an event occurs, the client notifies the server to run the appropriate event handler.

Ah! I see what you mean. It reminds me of https://github.com/airbnb/hypernova

Everything old is new again! Facebook once had a PHP extension called XHP which I guess you could call a server-side predecessor to React.

so it's a next.js clone?

All the business logic of the components (i.e. event handlers, lifecycle hooks, setState() calls, etc.) run on the server, unlike just the initial server-side rendering that Next.js provides. The server maintains the state of all components, and when an event occurs, the client notifies the server to run the appropriate event handler.

Haha, I saw people using it in WebWorkers, no nothing prevents them from using it on the back-end.

One Lambda per component would be interesting tho, haha.

> Applications that require minimal latency (e.g. animations, games) are not well suited for Purview

It's not actually React compatible.

Just why?

Because the DOM is not synchronously accessible, I guess.

Seems like the creator(s) of this need to take a hard look at Om next to solve their n query+net request problem

It's a JS framework that targets server-side (node.js), and is written in a language that is not natively supported - TypeScript, thus requiring transpilation right out the box to use. Does that seem odd to anyone else?

On the update: This does seem kinda neat, and certainly useful in some situations.

You're not required to use TypeScript. As janpot mentioned, the library is transpiled prior to being published on npm, so you can use it with regular JavaScript. This is true of most TypeScript libraries.

Not to me, if it's distributed on npm in its transpiled form it doesn't matter.

this is a whole new level of security bugs

God, GOD WHY. Whhhyyyyy. Build APIs, not database calls from templates like Rails or PHP garbage. We know how to do this nowwwwwwww don't make this Rails User.friends.comments garbage DB calls from templates

Why's that garbage? Sometimes a full SPA is not needed.

Just take a step back and look at it, you're combining HTML, SQL and JS, on the fucking server.

If you’re going this way, might as well put all of that as a stored procedure in the database. At least it Simplifies your infrastructure.

here we go again

Applications are open for YC Summer 2019

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact