Hacker News new | past | comments | ask | show | jobs | submit login
React, but in Python (github.com/reactive-python)
238 points by filippofinke on June 6, 2023 | hide | past | favorite | 175 comments



Controversial, but I think that rather than trying to make Web stuff (e.g. React) work in Python, a more fruitful direction would be to make ML stuff (e.g. PyTorch, OpenCV) work in Typescript.

Javascript/Typescript is way faster than Python, is ubiquitous and can run pretty much everywhere, has many engine implementations, has an incredibly wide ecosystem, has a type system (Typescript) that blows any Python type system out of the water, runs in browsers, has non-stupid package management systems (PIP is a joke), is easy to get started, etc.

<The world if data scientists/ML/CV people used Typescript.JPEG>


The speed of the output of the compiler of the glue language almost does not matter. Whether it is Python or TypeScript, it will not matter. Typically people will not use pip directly in serious projects, except for quick and dirty package installs to prototype something. In any serious project I would expect people to use any of the package managers, that support creating a lock file. But then NPM for example is not better than poetry. Or at least I have not had a single case, where I thought: "Ah, if only it was behaving like NPM." Rather the opposite.

But anyway, the whole language specific package manager business is starting to annoy me. I would like to be able to simply use something like GNU Guix and sometimes I am able to do just that.


> The speed of the output of the compiler of the glue language almost does not matter. Whether it is Python or TypeScript, it will not matter.

Depends on the use case. For ML, sure, it doesn't. For web servers, it depends. For stuff like this React-like tool, it matters.


It matters if it's actually meant to be used on the web, but I suspect the use case here is an easy front end for small python program in which case it doesn't matter at all and python interop is critical.


> But then NPM for example is not better than poetry.

Poetry is good exactly because it copied the concepts from NPM / Yarn. It's almost a port of NPM to the Python ecosystem, 8 years later.


Citation needed.

Poetry itself said Composer and Cargo were the main inspirations[1]. Both of them work differently from NPM; Poetry has mostly the same differences that its claim checks out. You would be in quite some surprises down the road if the sperficial similarities persuade you to apply one tool’s paradigm to another.

[1]: https://github.com/python-poetry/poetry/tree/0.1.0#why


Poetry has more to do with pip and virtualenv than NPM to be honest.



That is not a typical lock file. If it is, then it is a bad one. Lock files need checksums, not version numbers (oh well, both.). Version numbers do not protect from changes. At least not in all important cases or scenarios. I've had packages in the PHP world change their checksum and when I alerted them about it, they were like "So? We only changed some documentation of that version." ... Who knows what else people change in the same version. No. You need checksums.


Pip supports checksums too. A better link might be https://pip.pypa.io/en/stable/topics/secure-installs/


PyPI does not allow file uploads to be changed [0] but while that means this particular scenario is not an issue for PyPI/pip I'm not completely confident it's impossible to come up with a problematic scenario. Perhaps if a broken wheel was later published for an existing release with a working source distribution. In practice this is not something I've run into though.

[0] https://pypi.org/help/#file-name-reuse


pip-compile provides exactly that: https://pip-tools.readthedocs.io


OK, I guess the question is how pip-tools relates to pip then.

Is it a random third party package (someone just grabbing that name) or who manages it? As it is, it looks like not part of pip. (But maybe you were merely posting it as an alternative?) I've never heard of it before. I have been using various tools already, including merely pip, pipenv, poetry. Do I need to look for the newest tool every month? It begins to feel like the JS ecosystem.


There are different tools for different purposes.


No please no. Can we just leave javascript and all of it's flavors behind already. All of this innovation and people want to program in _transpiled_ programming language? It's like turles all the way down but it's just hacks all the way down in the js world and it'll start catching up with us if it hasn't already.


It’s not transpiled. Only some implementations of it are. Just use Bun or Deno with TypeScript. There is literally zero runtime impact. It’s just natively TypeScript.


i believe deno compiles typescript on the fly, in a V8 isolate; it is not interpreted natively in the same way javascript is (but, yes, you don't have to bundle it or transpile it first)


JavaScript is a joke when you consider things like prototypes and classes. Not saying Python is perfect but JS really feels atrocious to me.

TypeScript requires you to compile, the whole point of Python for ML and data science is you're running in an interpreted environment where you delegate as much code out as you can for both data processing and algorithms to invisible C++.

The interpreted part is key as ML is about experimentation. It's not like there's any overlap between current web developers and ML people anyway to need an unified bridge.


You don't exactly need to compile Typescript to make it run, you can just strip the types out which is much faster than compilation. If you want you can run `tsc` to have the compiler compile it and check for errors, but this can be running as you develop to act more as a linter.


> It's not like there's any overlap between current web developers and ML people anyway to need an unified bridge.

I guess you have completely missed people running language models on WebGPU then.

I think webasm + webgpu will be a target for a lot of new ml libraries.


Well yeah, as a sort of compilation target for sure, not just for language models but all ML models need to be integrated somewhere. The ML code and web code will be independent though.


Why does it have to be like that long term? There is no reason to keep them separate if they use the same language and platform. See https://news.ycombinator.com/item?id=36006626


Running esbuild to strip types and then running node, or using deno/bun, is much faster than Python. There’s also nothing that would prevent interactive JS or TS either… That’s what the browser debug console does.


We do with Typescript what a lot of people do with Python. Handle most things with Typescript and then contract off the really compute heavy parts to C\C++ (slowly moving to Rust). I’ve worked extensively with both Python and JavaScript and while we use Typescript because it’s much easier to setup an environment where your code is protected from you than it is with JavaScript you can actually do the same with JSDoc. I want to love Python, hell I do love Python, but I just love JavaScript a lot more.

I think the key difference is that it’s hard to setup good governance for JavaScript. You’re going to need a fascist linter that is actually enforced, and you’re going to need a tight grip on your developers to force them to really, really, think about their dependencies, but once you have that it’s quite honestly the best language I can think off. The ability to use isolated functions instead of putting them into “classes” is just such a great way to do a solid mix of functional OOP programming, which is obviously heresy to hardliners of either, but it’s just so magical when you do it right.

I think Python is getting there, it was such a great language for such a long time that it sort of forgot to improve. But now it has copied the NPM/Yarn package handler, and hopefully it’ll soon be possible to actually do a Typescript sort of Python, so maybe it’ll be able to win me back. Or to be fair, I think it’s a great language until you have to work together. It’s just so hard to get the codebase governance up with Python that it only really becomes worth it in ML shops where your developers want to work with Python. I’m not sure how Instagram managed, and there are certainly the projects that fit into the Django box which absolutely should be put into the Django box, but the only general purpose language to me personally is currently JavaScript.

Part of that is because we need initiatives like this one. We need “React” in Python or Rust or whatever if we want small dev teams in non-tech enterprise to be able to work with other languages than Typescript. Yes I know we have some C++, and a little Rust, but unlike the rest of our many different projects I’m the only one who can maintain them. Which is actually the primary reason we work with JavaScript, because if we don’t, then the React developer won’t ever be able to go on a vacation. :p It helps that JavaScript has become such a great language, and it likely has exactly because the React dev wants to go on vacation in a trillion IT departments. But I’m all for Python having this React Python so ML heavy shops don’t need that React dev.

But to say JavaScript is atrocious is sort of silly to me and I’m not sure you would have that opinion if you gave it a real chance.


Personally I only use SvelteKit which I find is nice by building around what the web technology currently is.

As for static types to be honest I don't see how it's useful in the context of ML. You might use a Pandas dataframe, which already comes with types enforced inside of it. You shouldn't ever use a for loop on a Pandas dataframe or whatever because then you're running Python instead of C++, Pandas has inbuilt functions and operators.

However Python does have type hints but probably not strict enough, Mojo may improve in this if it really supports both AOT and JIT.

Package management in Python isn't that bad with requirements.txt. The real problem is Python versions are breaking and whatnot (very often ML libraries are months behind latest) but the main Python installation you have only supports virtual environments for packages. Really it should support something like conda out of the box where you create an environment with a Python version.


I think the whole environment thing in Python is sort of a thing of the past. I got into Python after containers were the default, but I can see why the environments would’ve been brilliant before that. Today they feel more like a really terrible to work with version of node_modules though. I think Python is one of the languages that does dependencies the absolutely most annoying because of how they sort of tie into that.

But it’s not too terrible, it’s it’s not Node or Cargo, but it is really hard to build governance around.


My experience of doing maths in JavaScript was terrible. Fairly simple things like [1,2] < [10,2] return false (unlike every other language I’ve ever used), as < is implement by converting to strings, then comparing.

Is that fixed by Typescript, or does it inherit all those kinds of weird JavaScript behavior?


I don’t get the example - how is it obvious what should be the result of comparison of 2 lists ?


In Python, when comparing lists using the less than (<) operator, the comparison is performed element-wise.

The first element of each list is compared, and if they are not equal, the comparison result is determined based on the comparison of the first unequal elements.

In this case, [1, 2] and [10, 2] both have different first elements (1 and 10). Since 1 is less than 10, the comparison result is True.

The second element of both lists (2) does not affect the comparison result because the first element is already sufficient to determine the outcome.

[1, 2] < [10, 2] evaluates to True.


All of these could be equally valid results of your list comparison: True, False, [True, False], [[True, True], [True, False]].

I like that typescript does not rely on an implicit choice, but let’s me express exactly what comparison I care about.


I agree there are a few versions you could do, but most languages tend to do lexicographic.

This has been a suprising thread to me -- I just assumed "everyone knew" that the vast majority of languages do lexicographic comparision of lists.

I will say typescript does "rely on an implicit choice", it has a default implement (the "convert to string"), which I'm going to be honest, doesn't ever seem like a sensible choice to me -- although maybe it feels more natural to javascript/typescript people.

My personal upset (I lost like a day to this) is that if you keep your numbers under 10, you do get the lexicographic ordering, as then lexicographic = string. I had a bunch of unit tests (all using numbers under 10), just larger inputs kept breaking, and it didn't occur to me to go read the docs for < :)


What's the use case for this?


Lots of mathematical algorithms sort lists lexicographically. It comes up in graphs and lots of other combinatorics problems. Often you want a total order on 2D coordinates, an this ordering is (usually) the simplest and best.


TypeScript is a JavaScript superset. It adds features, but doesn’t change the meaning of existing stuff. (Almost all of what it adds can just be stripped out syntactically to yield JavaScript, but there are a few features that generate actual code, like enums.)


> Fairly simple things like [1,2] < [10,2] return false (unlike every other language I’ve ever used)

What other languages, besides Python, does this builtin list comparison work in? What's the result when the comparison is `[1, 2] < ["10", "2"]`?


I've never seen this usage of list comparison before but apparently it works in Rust (both of these print true):

println!("{}", vec![1, 2] < vec![10, 2]); println!("{}", (1, 2) < (10, 2));


List comparison works lexicographically in Haskell, C++ (using std::vector or std::array), Rust, GAP, every language I personally use.

Comparing strings and bits is always going to be weird, so I’ve not tested it.


Good luck recreating all the data science libraries in Javascript, that was decades of work. We now have WASM so its far more likely JS just isn't needed


You might be surprised. https://news.ycombinator.com/item?id=36006626

But of course yes, The ML stuff should be Wasm and WebGPU. The point is you can access it from Typescript. Just like most data science libraries are not Python, they just have Python bindings.


Why not just implement a Typescript backend that outputs Python instead of Javascript? (-:


TS is a joke

tsc is the only compiler I've had to step through with a debugger multiple times.

No DS/ML researcher wants to deal with VM args just to use more than 1GB of memory. That alone would cause so much frustration.

Not to mention unpredictable generational GC.

Or the crazy crap people do with the type system (what you call better other people call a mess).

At least Python has some semblance of runtime type safety.


> TS is a joke

I'll discuss facts

> tsc is the only compiler I've had to step through with a debugger multiple times.

99.9% of Typescript developers never ever had to do that. Sounds like a "you" problem

> No DS/ML researcher wants to deal with VM args just to use more than 1GB of memory. That alone would cause so much frustration.

You're talking about NodeJS, which is just one of the many JS engines. It's also 200% easier to start NodeJS with a flag to increase the (sane) default memory limit, as compared to the insanity of setting up a Python environment.

> Not to mention unpredictable generational GC.

Is Python GC better? Really? The good thing with Python is that the whole language is so slow that GC is just a drop in the bucket. On the other hand, Millions (Billions?) have been spent optimizing JS engines and it shows. Also: GIL.

> Or the crazy crap people do with the type system (what you call better other people call a mess).

I don't know what you're talking about, TypeScript go Brrr and I get magnificent Intellisense and subtle type checking, while MyPy and friends keeps crapping their pants

> At least Python has some semblance of runtime type safety.

No. And critically it has no semblance of comp time type safety either.


The Python GC is slow, but predictable. I've seen the Node runtime falls apart past like 8gb heap all the time, but I have python scripts that run just fine with a 32gb heap.

Requiring the max old space flag is already too much. It's annoying.

Python does indeed have some runtime type safety. Way more than any JS runtime I've used. And I've written way more Node/JS/TS than Python.

In terms of the compiler, Nah. The whole ecosystem stinks. I cannot wait to move my larger Node projects to Java or something else. Idk how much dev time people waste on arcane tsc or npm issues but the answer is "too high" regardless. At least esbuild is okay.


I spent a good chunk of last year learning go, and felt dumber for doing so. I feel like Rust is the way to go in 2023 and beyond -- particularly if the rustaceans can get past their own stupidity.


I haven't used go for some reason but it always looked nice. I like the simplicity, for some things. I know old C programmers trying to write web services in C (with hand rolled json...) and I wish I could get them using Go. :)

Rust is neat. I wrote a decent sized side project backend (weatherfy.com) in Rust, with sqlx, postgres, and axum. Shared cache was tough to figure out but everything else was easy.

The whole backend has like one lifetime annotation, so that wasn't too bad. Honestly, I'd use it again, but the compile times scare me.


There's a bunch of negatives I found. I'll gloss over them here.

- New libraries can't just be deployed to the OS, they must be compiled into the project.

- A check for thing==nil doesn't always work for all types of nil. Yes nil does not always equal nil.

- Panics aren't necessarily a bug. They could be a feature (?). Crashes are always a bug in C.

- Garbage collection is mandatory in go. C people are used to managing memory themselves like going for a walk. It's kinda natural.

- GC causes hard to debug performance issues. This was true in Java. And it's true in Golang.

- Golang channel primitives has bugs of their own with deadlocks and other interesting behaviors, whereas a lot of the threading issues in C are pretty well understood.


You cannot really compare Rust and Go.

Rust is for when you really need to perform manual memory management. If you don't need that, then a GC language is better.

If you're choosing manual memory management over GC, you better have a really good reason to do so or a really small application that you're writing.


Literally the whole point of rust is to not do manual memory management and let a compiler handle that for you.


> Literally the whole point of rust is to not do manual memory management and let a compiler handle that for you.

Incorrect. The compiler forces you to handle memory properly. It doesn't, as far as I know, manage it for you.

The burden is on the programmer to do it correctly. The compiler stops the programmer from doing it incorrectly.

Compare with GC, where the programmer is freed from the burden of worrying about memory altogether.


I would make a distinction between managing memory (malloc, free) and then subsequently handling said memory in a safe manner.

The first part Rust does for you.

The second part you'll indeed have to do yourself and the compiler will force you to do it safely.


>Also: GIL.

javascript is terminally single threaded, with the only solution being either multiprocessing and message passing, or cooperative multitasking style promises/async. This is not a situtation where javascript pulls ahead, as hard as python seems to try to fall behind.


and before you question my experience again, I have 100k+ LOC Node projects.

You admitted your opinion would be controversial. Guess what? It is. Hardly anyone wants to do ML in TS. No ML researcher <wants ? <to> | deal | with < type signatures > (like ? This)>>>>


Interesting that you say that, this was the top voted comment on a post recently about using typescript for ML stuff: https://news.ycombinator.com/item?id=36007493


> > At least Python has some semblance of runtime type safety.

> No.

I mean.

  >>> 1 + "1"
  Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
  TypeError: unsupported operand type(s) for +: 'int' and 'str'


> I'll discuss facts

> the insanity of

welp, so much for that.


Whoops ¯\_(ツ)_/¯


> has non-stupid package management systems

Excuse me what


Isn’t mojo the future on that front?


Mojo looks cool. But I'll wait for it to be open sourced AND as easy to use as Typescript + React for real complex web apps before considering it. I expect this to take 2-5 years if it ever happens. It's a possible future, not the present.


I agree.


I'm lost.

React builds interactive UIs (web, mobile). After each interaction, the virtual DOM is programmatically recreated and reconciled to the actual DOM.

But reactpy is running on a backend sever??? Is each interaction resulting in a server call?

Can someone explain what is going on?

EDIT: Ah, okay, thanks. Every re-render is a network call. If people complained about web UI performance before..... :)


In reality, an important and large class of apps will hit the backend on roughly every click anyway, and having full control over in-browser interactivity is kind of overkill for those apps. Business apps with tables, charts, and forms, for example. You click the nav to load a new page, you scroll down or click a button to load more data, you fill a form and click submit, all those things hit the server.

For those types of apps, this 'backend-driven reactive apps' paradigm could be more efficient, because programmers don't have the option to build stuff like an inefficient network protocol or bloated frontend stack.


For a certain class of things, this could work.

You'd have to conscious of this.

It's defiantly not a "write a usual React app, but in Python"...every dropdown, menu, modal, etc interaction interaction is a backend call.


What about conditional form elements, modal dialogs with static text, or collapsible menus?

I understand the benefits, then again if interacting with these elements requires calling the backend then the cost is quite high.


Indeed something like a collapsible menu may call the backend to ask to open/close the menu.

But some frameworks may open the prefilled menu when you click it, and sync the state to the backend, instead of waiting for the backend to “approve” the request to open the menu.

Hypothetical example:

  m = menu(1, 2, 3)
  if m.opened:
    print(“It was opened.”)
Here there may not be any UI latency when opening the menu. The menu opens when you click it, and the state is synced to the backend. However,

  m = menu(1, 2, 3)
  b = button(“open the menu”)
  if b.clicked:
    m.opened = True
In this program, there will be a round trip to the backend when you click the button to indirectly open the menu.

Overall, it depends on how you design the framework and how you divide interaction control between backend and frontend. Controlling every little interaction thru the backend is probably not a good idea, and you should bake some frontend interactions into the UI components.


yes, from reading the docs, there's a websocket.

Making a 'server call' on each interaction is also what web apps used to do before SPAs were a thing. And in many cases it's what SPAs do as well.

Of course, it depends what counts as an 'interaction', but that's been the case since JavaScript existed.


> Making a 'server call' on each interaction is also what web apps used to do before SPAs were a thing.

One of the reasons behind the popularity around webapps was that they would no longer need to make 'a server call' on each interaction.

> And in many cases it's what SPAs do as well.

I feel you're grossly misrepresenting what SPAs do. SPAs do calls to send and receive data, not to fetch server-side rendered content.


> One of the reasons behind the popularity around webapps was that they would no longer need to make 'a server call' on each interaction.

Ironically, many modern SPAs are significantly slower than the traditional apps they replaced. Try using Twitter's webapp on a non-premium phone, for example.

Sometimes it's regrettable that the webdev truck has no rear-view mirror.


The entire internet is slower because it's being squeezed to oblivion for monetization and tracking purposes. No matter what technology you choose to render HTML with, your company is going to have a slew of systems for injecting 3rd party scripts, running A/B tests, collecting analytics that include recording user sessions, etc etc. Back "before SPAs" we just weren't doing as much crap in the browser.


Tracking doesn't help but modern frontend development practices lead to slowness.

Rerendering and recomputing too much (ever encountered these chains of map() and filter() in render()?), many API calls, huge icon sets, huge custom fonts, CSS frameworks and JS frameworks, huge dependency trees with many instance of the same lib running sometime in several versions, big bundles... This heaviness in the name of convenience and branding is not free, it forces people to ditch perfectly fine hardware, which has a high environmental cost... not directly paid by people funding the code).

One of my pet peeves is managed text inputs, where render() is called each time you type a character, for a whole component tree if you are not careful and you happen to pass the content to some parent for some reason. Typing a message in Mattermost on the PinePhone is painful for this reason, there's just no reason typing should be slow even on slow hardware but managed component is considered good practice.

Making people buy newer / powerful and making people wait and using too much energy should be considered bad practice.


I agree. I recently went to great lengths in the React app I own to make it so that only the affected components would re-render on each input keystroke, and the result is gross but performant. My opinion is relatively nuanced: I am a proponent of SPAs in situations where they make sense, but if I had a choice I would never use a framework. They always impose at least as many problems as they solve, if not more.

I attempted to build a startup product using a vanilla JS SPA when I was a founding engineer, and the result was predictable: it worked great for me, but nobody I hired wanted to learn some random guy's vanilla JS codebase. I've since resigned myself to using React simply because that's what developers expect, despite all the headaches.

For what it's worth, we ended up migrating to Mithril in the V2 of that startup's product. We all enjoyed Mithril and it scaled really well for us, but my team did have some apprehension about their React skills falling behind.


> Rerendering and recomputing too much (ever encountered these chains of map() and filter() in render()?), many API calls, huge icon sets, huge custom fonts, CSS frameworks and JS frameworks, huge dependency trees with many instance of the same lib running sometime in several versions, big bundles...

This hits the nail in the head.

A single high-res background image weights more than all the code in a complex webapp. If that image is required to pull the first contentful paint then the page will feel slow.

It matters nothing if your JavaScript is just a hello world console log. That background image is in the critical path.


> The entire internet is slower because it's being squeezed to oblivion for monetization and tracking purposes.

Bullshit. All you need to track a user is data you send as part of a HTTP request. Pushing metrics is a fire-and-forget HTTP request away.

The internet feels slower because we're using way more of it, not only in the increased complexity of webapps to improve user experience and implement features but also in the volume of data we're transferring around.

> running A/B tests

A/B tests just means settings/feature flags and metrics. Feature flags is used in way more things than behavioral studies.

> include recording user sessions

User sessions are recorded since ever with zero performance penalty. The very same HackerNews page you're now browsing is tracking your user session whenever you login. That's not it.

> Back "before SPAs" we just weren't doing as much crap in the browser.

Right, and life sucked back then. Why do you think Flash was so popular?

It's trendy to shit on the status quo but it also is low-effort and lacks any insightfulness.


> All you need to track a user is data you send as part of a HTTP request.

Browsers impose a limit on concurrent requests (usually 6 per hostname) for a reason - HTTP requests, be they too many or too large, are one of the largest performance problems in a typical site. Just because it's easy to fire-and-forget an HTTP request doesn't mean it doesn't have a performance impact, especially in apps that are already network-chatty. I think you know this because you go on to list "the volume of data we're transferring" as a performance bottleneck, and obviously that's done through HTTP requests. Also, in the real world analytics installations virtually always include installing a third party library i.e. google analytics, so you're taking hits to download the library, interpret the source, run the code alongside your app, usually in the same thread, all before you've fired any of those HTTP requests.

> A/B tests just means settings/feature flags and metrics

I'm aware of the definition. If you are implying that conditionally loading settings or feature flags and tracking associated metrics doesn't have a performance impact, I would disagree. It is usually possible to implement a given A/B test with minimal performance impact, but in practice these are absolutely a contributor to the kind of bloat I'm frustrated with.

> sessions are recorded since ever with zero performance penalty

It sounds like you're talking about logs. I'm talking about "session replay" features provided by companies like FullStory and Sentry that allow you to replay every mouse move and keystroke of your users.

> It's trendy to shit on the status quo but it also is low-effort and lacks any insightfulness.

By this point in your comment I think you forgot what we were talking about. I was arguing that the architecture of modern SPAs shouldn't bear the blame for bad performance; my point being that whether or not we continued to use server-generated HTML we would still be suffering from similar problems of bloat today. The "status quo" that I'm shitting on is taking lazy approach to performance management and injecting way too much cruft; unless you work for an analytics provider I'm not sure why you would be opposed to that stance.


Hell, try using the Twitter web app on something with 8GB of memory or that's older than 5 years old.


> Ironically, many modern SPAs are significantly slower than the traditional apps they replaced.

All software becoming slower is a already a meme. This isn't exactly a SPA issue.

> Sometimes it's regrettable that the webdev truck has no rear-view mirror.

The "software is getting slower" meme was the Hallmark of Java in the server when it was released in the 90s. This is nothing new, or specific to web dev.

Also, I feel you're grossly misrepresenting the problem. Reddit's mobile page is considerably slower than the old reddit page, but it's perceived performance is quite good. All posts are cached and instead of full page reloads it just switches content virtually instantly.

It might be fancy to shit on everyone else's work, but this only happens if you lack objectiveness and sincerity.


Yep. And nowadays you can deploy apps really close to users so latency is really low. If you have <100ms you don't really notice the latency.


But... 99% of insert-startup-product-built-on-React (or honestly, any framework) is typically super slow (for whatever reason that might be). Sluggish, not super responsive, laggy UI, however you want to describe it. A far cry from the snappiness of desktop apps from 25+ years ago.

Something or some collection of people are doing something wrong, somewhere in the chain. So isn't this just yet another way to further entrench the modern state of meh-ness in performant UI?


Your statement is very broad. Might be the startup culture and lacking technological expertise, no?

Was insert-startup-product-built-on-.NET fast 15 years ago, for example?

Not trying to be controversial, just wondering.

I agree that a product built by clueless developers stringing together random libraries or bad custom code in React would create slow products.

In your spirit, I might argue that thinking "reactively" and client-centric tends to lead to unneeded requests.

Developing without meaningful API contracts or basic CS skills also makes it easy to unintendedly blow up network payloads.

Caching is hard though.

Have you worked on bad PHP applications that reload on every interaction without caching?


As someone who has had the misfortune of working on poorly tuned WordPress and Drupal websites in a former life I can confirm this is an issue of culture, not and axiom of whether SPAs are intrinsically faster or slower.


manual network state sync between frontend and backend is the root cause of that


> A far cry from the snappiness of desktop apps from 25+ years ago

So apps without network latency are faster? Huh.


People notice the difference of < 10ms in input delay on a command line. I am pretty sure humans notice stuff >= 10ms, <= 100ms. It is perhaps the expectation, that is different. People do not expect websites to react immediately, like when they are typing a command in a terminal emulator.


> And nowadays you can deploy apps really close to users so latency is really low.

That sounds like blindly throwing money at the software architecture problem you created for yourself. Supposedly SPAs became popular because your line of reasoning was embarrassingly absurd, in the sense that you do not mitigate the penalty of a network call by microoptimizing the cost of a network call.


Proximity is only part of the equation. If a user has a slow router or a busy corporate firewall to go through their timings can be far higher than 100ms even if the server is a few miles away.


A no-op API call to FastAPI takes more than that. Even when running on localhost. And FastAPI is one of the better contestants.


If fast api didn't use pydantic (the slowest library in that space), I'm sure it might be more deserving of the name :D

Microbenchmark to compare with typedload (which I wrote) and apischema https://ltworf.github.io/typedload/performance.html

Note that pydantic and apischema use .so files, while typedload is just pure python code.


A no-op localhost call takes more than 100ms??


On my mobile i5 10-gen it's 23 ms.


Yeah this seems to combine the worst of both worlds: react headscratching (e.g. why useEffect do this weird shit) and slowness of the phoenix style send it all back to the server. The solution? For python people: learn some JS and use django.


The most popular stable diffusion UI uses gradio, which is the same paradigm of defining a web frontend in the backend, and the performance just falls apart after the code reaches a certain size. The need for most interactivity to roundtrip to the server and back opens up tons of places where a bad connection could leave the whole app in a half-broken state. And beyond that, it's just slow. So much so that mobile use on cellular is out of the question. Other SD user interfaces handle parameter adjustment in the frontend, but something as simple as swapping two integer inputs requires an seconds-long API call unless you bypass the whole framework with custom JavaScript.

Then there's the fact that your backend framework has to define the subset of all frontend features it supports in Python. The moment you hit on a usecase that isn't supported in Python, you have to learn JS anyway and write code in the frontend. Except it's the worst kind of frontend code: hacks around broken or missing frontend features that depend on implementation details specific to the framework that are subject to change at any time.

I feel that these kinds of frameworks are better suited towards researchers or backend devs who really do not want to have to set up an NPM project just to have a simple (and I really mean simple) frontend UI to interact with. But don't dare try to write the next gigantic ML app on top of it or you'll have to deal with the performance and maintenance issues that follow.


I mean, what if the app is only ever used by one person over localhost? Seems you would be blocked on access to the GPU, unless it also has GPU farm support?


I meant more in the context of basic user operations feeling sluggish and degrading the overall UX.


Sounds like Elixir LiveView.


That's how the new "react server components" work too. It's more sophisticated than this but the network concept is the same.

Blazor was the pioneer here.


If you're interested in using React-style frontend programming in Python but want an experience / API closer to that of React, I recommend checkout out Reacton [1].

Similarly to this library, it gives you a `@component` decorator that allows you to create components out of functions. But it also: 1. Includes all existing React hooks (use_state, use_memo, etc) -- so you don't have to learn new patterns. I believe this results in a bit less magic (and so easier debugging) than just using raw variables. 2. Works with ipywidgets, so many existing data apps can be ported over very easily -- Jupyter users celebrate.

I'm not associated with the project, but I know the maintainers (creators of Volia [2]) and they are honestly excellent. I haven't use the project in production, but the getting starting guide is pretty compelling.

[1] https://github.com/widgetti/reacton [2] https://github.com/voila-dashboards/voila


Thanks for the shout out.

The follow up of that is Solara: "NextJS, but in Python" :)

https://github.com/widgetti/solara/


I never expected to care about a UI library in Python, but my user research collaborators prefer Colab notebooks (as opposed to Observable, where my JS expertise would be relevant).

Now you (and the OP) have me pondering about building UIs in notebooks…

Not sure doing something in React is better than just learning the standard tools, but it's a good option to know exists.


I created something like this inside a tech giant once. It never saw the light of day with regard to usership. It's good to see someone doing the same in the open source world.

A brief summary of what I did:

* Python-powered apps, like this

* React was used to handle lifecycle. Basically, I avoided writing any kind of lifecycle management because I just wanted to do exactly what React would do. This was achieved via events firing when React lifecycle events fired. If props changed on the server, I'd send the new props to React to see if it would trigger a lifecycle event. If a lifecycle event was triggered, I'd replicate it onto the server which could again render new props.

* The result was a nice seamless support for both native React components and the newfangled Python components (which could be made up of either more React components or Python components).

* The purpose of all of this was to cater to ML engineers who didn't particularly like JavaScript and just wanted to build their analyses with Python and share them with coworkers. We had an automatic deployment system for them to share these.

* Only caveats were around session management. Much of the state was handled on the server via a websocket, so if your connection dropped, you lost all ability to update the layout. Load balancing was going to be tricky, since the sessions would have to be shared somehow. I was thinking about serializing and deserializing using Pickle but never really got around to deployment.

See also: [Dash](https://github.com/plotly/dash)


Oh, I had a case where I had built an ML based recommendation app, and utilized Flask for serving the results on my localhost. Would have loved to use React but my lack of sufficient JavaScript knowledge prevented me from doing so. Your tool seemed to have perfectly catered to my needs!


Dash could probably get close enough as well. It's a bit limited compared to React but provides quite a lot of interactivity. (Plus, the server is stateless which is nice.)


I'll have to give a try then!


The way to solve session management is to just store the state in html forms and send it back to a stateless http endpoint. That way you get a website that behaves the way all websites work, and can scale easily.


The trouble is though that you also have state in Python which can’t necessarily be represented in Javascript, such as a database connection. You could pickle it, but accepting a user-provided pickled value is a security risk. Also, doing so would leak database credentials, and recreating the state on the server every event is expensive anyway (especially when the state is something like a pandas dataframe). It’s better to just have one dedicated machine per application session that holds the state for the duration of the app.


Don't use pickle. Use JSON for stuff you can't represent in HTML forms.

For database connections, large datasets, etc (stuff you can't send off to the browser) use redis.

This is a trade-off between DX and UX. Holding session state means you need sticky session routing, and restarting servers kills your user's sessions. Plus imposing a websocket on your users is a cardinal sin, makes scaling incredibly hard, makes page load times abysmal, makes disconnects a nightmare for both you and your user.

Its fine if you're creating something like stable diffusion web ui though, which is meant to be a single user app.


I find these dogmas to be presumptuous. For the use case, Pickle would be fine. Scaling was essentially a non-concern… it was an internal tool behind a VPN and the usage was below a dozen (and at most would have grown to dozens).

JSON is an alright storage format but it can’t do infinity, nan, or many other values important to Python. Also, you would have to write a reifier and serializer for every value. These simply create a problem rather than solving one.

Not optimizing DX would be a mistake when the whole purpose of the project is to improve the DX by allowing the users to not write JS/React. Once the DX starts becoming that cumbersome you might as well just avoid it by switching back to native React.


ReactPy dev here. We haven't actually landed on how we want to solve this problem yet. We have some ideas though. Would be curious to hear your thoughts on this issue: https://github.com/reactive-python/reactpy/issues/828

We think option 4 looks the most appealing.


Wish I could help, but I never got as far as auth, and it sounds like ReactPy takes a bit of a different direction anyway. Looking forward to digging in but just haven’t gotten to it yet. Thanks for surfacing though!



Cool idea but it wouldn’t have worked for what we were doing. The Python side definitely needed to be on the server because it was dealing with database connections, talking to other services, and doing heavy duty dataframe manipulation.


At some point we'd like to add client-side components to ReactPy. This might be an interesting avenue to explore in that regard.


Shameless plug for a similar project called Collagraph (https://github.com/fork-tongue/collagraph).

From the README: Write your Python interfaces in a declarative manner with plain render functions, component classes or even single-file components using Vue-like syntax, but with Python!

  - Reactivity (made possible by leveraging observ)
  - Function components
  - Class components with local state and life-cycle methods/hooks
  - Single-file components with Vue-like syntax (.cgx files)
  - Custom renderers
Currently there are two renderers:

PysideRenderer: for rendering PySide6 applications PygfxRenderer: for rendering 3D graphic scenes with Pygfx

It is possible to create a custom Renderer using the Renderer interface, to render to other UI frameworks, for instance wxPython, or even the browser DOM.


If you're interested in this sort of thing, but want to code in Java, try Flavour: https://flavour.sourceforge.io/

Flavour is a fast, batteries-included, type-safe framework for making modern SPA web apps in Java (and other JVM languages).

* Great Lighthouse scores? Check!

* Real SPAs without sluggish network round trips? Check!

* Modern path-based routing? Check!

* Components (built-in and user-defined)? Check!

* Effortless service calls? Check!

* Refactor frontend and backend simultaneously using your current IDE? Check!

If this sounds interesting, check out these other resources:

* Article in Java Magazine: https://blogs.oracle.com/javamagazine/post/java-in-the-brows...

* 100% Flavour 5-letter word game: https://frequal.com/wordii

* Flavour podcast (created with Castini, a Flavour app): https://castini.frequal.com/cast/show/Flavourcast/f7e171e8-2...


None of these links seem to work?

This site can’t be reachedCheck if there is a typo in frequal.com. DNS_PROBE_FINISHED_NXDOMAIN


Not sure if your parent commenter fixed, but FYI all links worked for me.


Thanks hu3! No changes since posting, all links tested then and now, 100% working from here.


Does anyone have a list of full-stack Python frameworks for building interactive web apps? I feel like a new one comes out each week, and it would be nice to see them together to compare.


There are many, but here's a start:

pyjs, streamlit, brython, pyodide, pywebio, gleam, dash, bokeh, gradio, pglet, idom, anvil, pynecone, onu

The last two are YC-funded.

Edit: add https://flet.dev which has superseded pglet


I love OP’s project. I probably won’t use it, and I say that sadly. I chased that dragon for years, but ECMA was a sleeping giant.

I do not have the answer to your question, parent, but I feel the need to evangelize vanilla JS/ECMA.

You can do everything you could do with jquery and react with very simple constructs now. Web components are slightly awkward, but damn! Possible, and easier than it ever was before js components.

Introducing any additional technologies or node is no longer necessary. The frontend has evolved.

Now. You still have to learn ECMA, but that’s what browsers definitively run as of my writing.

I can pray to mdn for wasm to be a go-to every day tech, but that day is not today.


Not a list, but I've been trying out django-unicorn, which lets you build components in python and use things like unicorn:model and unicorn:click in your templates.



The slowest framework now available for the slowest language.

(this is a joke, it was my immediate thought when seeing this. More seriously, probably not for me but looks interesting technically, I'll need to check out how it works)


Long ago, before jsx and react, before hack, Facebook had a fork of php called xhp, which allowed xml data within php. I'm not suggesting anybody should maintain a fork of python with xml support but a pre-processor could parse xython and generate standard python with trees of html.xx() calls.

https://en.wikipedia.org/wiki/XHP


And long before transpiling became cool, FB had https://en.m.wikipedia.org/wiki/HipHop_for_PHP



xhp was honestly pretty nice - it was something watching the rapid codemods transform the language.

There was also ComponentKit, which was used heavily in fbobjc: https://github.com/facebook/componentkit


Could be fun to see this replacing jinja in old frameworks like django. Although inheritance had a better feel with templates..


ReactPy dev here. We're actually contributing to a WIP PEP that would add JS-like tagged template literals to Python. We think this will open up a whole new world of templating and DSL possibilities: https://github.com/jimbaker/tagstr


How much support does the idea have ? I like js tagged templates but I was wondering if it would impact the language too much.

Good luck nonetheless


Is reactpy a fork of IDOM or a rebranding of it?


Django doesn't use Jinja, does it? I thought it did its own thing.


They have their own template engine, but it can be swapped for Jinja2 optionally.


yeah my bad, but django and jinja are similar in nature, it's "fat" html template with inheritance and blocks.


Nice! I believe this is a really good approach for making web apps. Best part is probably that you save time by not having to implement some sort of JSON API for your frontend to communicate with your backend.

I've been working on a similar thing in Ruby. https://github.com/mayu-live/framework


Nowdays, with automatic api generation for your API, there's no difference in backend/frontend communication in type-safe way.


Curious what automatic generation you have in mind?


Say you have a function in the backend, for example in typescript:

function handler(a: A, b: B) {}

With a suitable tooling, you can generate the type for frontend to call handler(a, b) in a type-safe way, which could be validated on the backend and frontend.

So you're just a "generation" step away from bluring BE/FE communication.


Apologies, I know what generation is. But the ABI that is the wire between the front and the back is notorious for not being stable. Such that I was asking if you have experience with a generation stack that is favorable. Most folks I know do not have favorable experience in this realm. Best I know of, are those that drop down to something like protobuff to describe the messages.


I love this project. Having used Streamlit and Plotly Dash a lot, I find this project imposes fewer constraints. That said, it didn't support my target browser so I wrote my own and in the process (re)discovered fine grained reactive (e.g. solidjs) as an improvement over the VDOM. Anyway, the outcome was a similar approach but supporting the Kindle's browser. https://github.com/esensible/silkflow


No one knows what it means, but it’s provocative


from all the react clones I've seen there, this is the one that I'm mostly impressed by: https://yew.rs/ (React clone written in Rust, targeting webasm)


Hello world examples don't inspire confidence that this is anything more than a toy


I'm a little confused here, React might have a SSR component, but the thing that makes it React is that it runs client-side. So... how are you putting Python in the browser?


React doesn’t have to run client side. The DOM renderer is just one possible output, albeit the most popular. The output doesn’t even have to be human consumable.


That's like saying a ship doesn't have to sit in the water. You could put in in a dry dock too, and put wheels on it. But now it's not really a ship anymore. React, the UI framework, is a UI framework and is for user interfaces. The output _can_ be "not human consumable" but then it's not React, that's something else.


Does this offer any advantage over gradio? One big issue I have with gradio is that « simple » computations happen in the backend and make the UX very slow on deployment


Please try brython, it runs in the browser.

I find it so ironic that js, a language that runs in the browser, is now used on a server, to rebuild code that is sent back to browser.


Languages can run anywhere they have a runtime.


This is cute, but it would be more helpful to have react-style GUI programming in python, with Qt (Quick or widgets) as the backend (instead of DOM).


How is this different or better than Dash or Streamlit?


might just use pyxl4, by dropbox or Guido himself.

https://github.com/pyxl4/pyxl4

example:

# coding: pyxl

from some_module import x_user_badge

user = User.get(some_user_id)

content = <div>Any arbitrary content...</div>

print <user_badge user="{user}">{content}</user_badge>


This is what's missing from the reactive-python project IMO.

A huge draw for React is that it _extends_ the JavaScript Syntax. If you still had to compose your React components with a bunch of nested `React.createElement('Component')` calls (instead of `<Component />`) it wouldn't be nearly as useful.


Perhaps a Tkinter replacement, eh?


But... why?


Don't let Dan Abramov see this


I thought generating html from function calls went out with the dinosaurs. We back doing it again?



I haven't used htmx but it looks nothing like pyreact. htmx is about adding attributes to html, so again, you are still writing html.


Htmx is not only about adding attributes to HTML :) check how responses to requests are expected to contain full or partial HTML instead of, say, json.


yeah I get that, but the html that is returned from the server doesn't have to be generated with things like html.div(html.p('hello this is a p tag inside a div'))

you could still have your html in a template file and parse and return the contents of that.


To be clear, what this comment is talking about is using `p()` and `div()` calls instead of `<p>` and `<div>` tags like in JSX.

On first read, I thought by "generating html from function calls" the author was referring the react-style way of building a UI by writing a reactive function that returns HTML.


I mean, react does it. It never left. JSX compiles to function calls.


yes but no one generates html from the function calls directly in react (even though you could if you wanted), they use jsx which is at least a bit like writing html.



That page is very out of date. They did later adopt a build step and switch to using JSX in much of the FF DevTools codebase.

As an example, here's the Editor main component (same "latest" commit you pointed to):

https://github.com/mozilla/gecko-dev/blob/aec3a901e6f6b3041b...

The codebase is a mish-mash of very old-style React+Redux code, with newer files and usages.

(I know this because I work at Replay.io, which started as a fork of the FF DevTools source, and we spent all of last year modernizing our fork :) Migrated the entire codebase to TS, ripped out all remaining uses of the ancient `React.DOM` helper functions and converted those to JSX, modernized the 2015-era Redux logic, etc: https://github.com/replayio/devtools/pulls?q=is%3Apr+sort%3A... )


You're right, I totally missed they have tsconfig which include jsx preprocessor now. Too bad the devtools contributor documentation is not updated anymore, mozilla devs are probably stretched too thin to update obscure docs these days.


I feel like I'm talking to kids who have never used anything that came before react in this thread.


Still very much alive. This implementation with python, to me, doesn’t look promising, but Elixirs LiveView does.


LiveView is awesome. We've completely replaced React with LiveView and the user and developer experience is significantly better.


Why?


He means API calls, obviously overloaded the term "function calls" a bit

In this case, I think it's also clear that most things you'd call an "application" abhor this behavior, which is why heavy clients are so popular, and small shops without frontend engineering talent are making a big push away from heavy clients which raises all the hubbub about HTMX etc


> He means API calls, obviously overloaded the term "function calls" a bit

No they literally meant generating html like h1() rather than <h1></h1> in something like jsx templates

(I initially wasn't sure if they were talking about the model of server side rendering with client side events passed back to the server through a websocket either though)


No, he meant function calls as opposed to JSX, clarified in another comment.


> He means API calls, obviously overloaded the term "function calls" a bit

lol, no he doesn't


because ASP .NET webforms suck to work with




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

Search: