7 ms·
Show HN: Purview – A server-side component framework
- slifin 8y agoSeems like the creator(s) of this need to take a hard look at Om next to solve their n query+net request problem
- robinduckett 8y ago<?php print("this is far easier lol"); ?>
- forgotmyhnacc 8y agoI 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 https://docs.hhvm.com/hack/XHP/introduction) and some people at fb developed react as a natural extension to xhp but in JavaScript.
- notJim 8y agoTime is a flat circle.
- rajangdavis 8y agoTIL. Thanks for sharing!
- macobo 8y agoThis smells a lot like meteor. Would love to see an actual semi-large app built with this approach.
- janpot 8y agolooks like it's the react version of https://dockyard.com/blog/2018/12/12/phoenix-liveview-interactive-real-time-apps-no-need-to-write-javascript https://dockyard.com/blog/2018/12/12/phoenix-liveview-intera... ? edit: nvm, it's listed in the readme as inspiration
- elmo2you 8y agoI 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".
- mcintyre1994 8y agoThis looks awesome, thanks for sharing! :)
- karthikksv 8y agoYes, 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 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/jsx.ts 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.
- yuchi 8y agoYou 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)
- chrismccord 8y agoNeat project! We indeed support nesting in LiveView :)
- karthikksv 8y agoThanks 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/ 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?
- k__ 8y agoHaha, 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.
- patgrdj 8y agohere we go again
- pennaMan 8y agoso it's a next.js clone?
- karthikksv 8y agoAll 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.
- erokar 8y agohttps://dockyard.com/blog/2018/12/12/phoenix-liveview-interactive-real-time-apps-no-need-to-write-javascript https://dockyard.com/blog/2018/12/12/phoenix-liveview-intera...
- solarkraft 8y ago> Applications that require minimal latency (e.g. animations, games) are not well suited for Purview It's not actually React compatible. Just why?
- janpot 8y agoBecause the DOM is not synchronously accessible, I guess.
- rienbdj 8y agonormally security would be implemented at an api level. you would have to be careful to implement that in the renderer here.
- karthikksv 8y agoYou'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.
- mplewis 8y agoIn 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.
- karthikksv 8y agoHigher 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.
- choeger 8y agoWait, 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?
- martell 8y ago> 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 :)
- ahamdy 8y agothis is a whole new level of security bugs
- kgwxd 8y agoI'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.
- karthikksv 8y agoWhenever 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.
- vlucas 8y agoIt'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.
- janpot 8y agoNot to me, if it's distributed on npm in its transpiled form it doesn't matter.
- karthikksv 8y agoYou'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.
- spyke112 8y agoWait... Didn’t Microsoft do this back in the day with ASP.NET Web Forms? Full circle for sure!
- Scooty 8y agoI'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.
- karthikksv 8y agoWe'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.
- deleted 8y ago[deleted]
- bloomca 8y agoShameless plug: I have a library for server-side react-like components (https://github.com/Bloomca/welgo 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.
- stevebmark 8y agoGod, 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
- benbristow 8y agoWhy's that garbage? Sometimes a full SPA is not needed.
- throwawayy1001 8y agoJust take a step back and look at it, you're combining HTML, SQL and JS, on the fucking server.
- ako 8y agoIf 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.
- weego 8y agoSo 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
- throwawayy1001 8y agoPersonally 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.
- thecatspaw 8y agoTrue, but you could move it into a model class, maybe use mobx or another state library
- karthikksv 8y agoA 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.
- 8y ago
- rudolph9 8y ago> 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/ https://github.com/zeit/next.js/
- chikien276 8y agoI am surprised that nobody mentions this similarly https://docs.microsoft.com/en-us/aspnet/core/razor-components/hosting-models?view=aspnetcore-3.0#server-side-hosting-model https://docs.microsoft.com/en-us/aspnet/core/razor-component...
- neurotrace 8y agoLooks 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.
- root_axis 8y ago> 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.
- karthikksv 8y agoPerhaps 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.
- root_axis 8y agoAh! I see what you mean. It reminds me of https://github.com/airbnb/hypernova https://github.com/airbnb/hypernova
- stigsb 8y agoEverything old is new again! Facebook once had a PHP extension called XHP which I guess you could call a server-side predecessor to React.