> Even though Erlang’s asynchronous message-passing model allows it to handle network latency effectively, a process does not need to wait for a response after sending a message, allowing it to continue executing other tasks. It is still discouraged to use Erlang distribution in a geographically distributed system. The Erlang distribution was designed for communication within a data center or preferably within the same rack in a data center. For geographically distributed systems other asynchronous communication patterns are suggested.
Not clear why they make this claim, but I think it refers to how Erlang/OTP handles distribution out of the box. Tools like Partisan seem to provide better defaults: https://github.com/lasp-lang/partisan
`<div>Hello, world!!</div>`
we can do:
`<Text>Hello, world!</Text>`
I want to be clear: this is not a web renderer. We are not rendering HTML. We're rendering actual native UI. So the above in SwiftUI becomes:
`Text("Hello, world!")`
And yes we support modifiers via a stylesheet system, events, custom view registration, and really everything that you would normally be doing it all in Swift.
Where this library comes into play: the headless browser is being built in Elixir to run on device. We communicate with the SwiftUI renderer via disterl. We've built a virtual DOM where each node in the vDOM will have its own Erlang process. (I can get into process limit for DOMs if people want to) The Document will communicate the process directly to the corresponding SwiftUI view.
We've taken this a step further by actually compiling client-side JS libs to WASM and running them in our headless browser and bridging back to Elixir with WasmEx. If this works we'll be able to bring the development ergonomics of the Web to every native platform that has a composable UI framework. So think of actual native targets for Hotwire, LiveWire, etc...
We can currently build for nearly all SwiftUI targets: MacOS, iPhone, iPad, Apple Vision Pro, AppleTV. Watch is the odd duck out because it lacks on-device networking that we require for this library.
This originally started as the LiveView Native project but due to some difficulties collaborating with the upstream project we've decided to broaden our scope.
Swift's portability means we should be able to bring this to other languages as well.
We're nearing the point of integration where we can benchmark and validate this effort.
Happy to answer any questions!
* our vDOM: https://github.com/liveview-native/gen_dom
* selector parsing: https://github.com/liveview-native/selector
* compile Elixir to ios: https://github.com/otp-interop/elixir_pack
Years ago I worked at Xamarin, and our C# compiler compiled C# to native iOS code but there were some features that we could not support on iOS due to Apple's restrictions. Just curious if Apple still has those restrictions or if you're doing something different?
we compile without the JIT so we can satisfy the AppStore requirements
It's pretty well-established at this time that cross-platform development frameworks are hard for pretty much any team to accomplish... Is work winding down on the LiveView Native project, or do you expect to see an increase in development?
What is changing is how the client libraries are built. I mentioned in another comment that we're building a headless web browser, if you haven't read it I'd recommend it as it gives a lot of detail on what we're attempting to do. Right now we've more or less validated every part with the exception of the overall render performance. This effort replaces LVN Core which was built in Rust. The Rust effort used UniFFI to message pass to the SwiftUI client. Boot time was also almost instant. With The Elixir browser we will have more overhead. Boot time is slower and I believe disterl could carry over overhead than UniFFI bindings. However, the question will come down to if that overhead is significant or not. I know it will be slower, but if the overall render time is still performant then we're good.
The other issue we ran into was when we started implementing more complex LiveView things like Live Components. While LVN Core has worked very well its implementation I believe was incorrect. It had passed through four developers and was originally only intended to be a template parser. It grew with how we were figuring out what the best path forward should be. And sometimes that path meant backing up and ditching some tech we built that was a dead end for us. Refactoring LVN Core into a browser I felt was going to take more time than doing it in Elixir. I built the first implementation in about a week but the past few months has been spent on building GenDOM. That may still take over a year but we're prioritizing the DOM API that LiveView, Hotwire, and Livewire will require. Then the other 99% of DOM API will be a grind.
But to your original point, going the route of the browser implementation means we are no longer locked into LiveView as we should be able to support any web client that does similar server/client side interactivity. This means our focus will be no longer on LiveView Native individually but ensuring that the browser itself is stable and can run the API necessary for any JS built client to run on.
I don't think we'd get to 100% compatibility with LiveView itself without doing this.
Holy this will be much bigger than I thought! Cant wait to see it out.
How is it different from Lynx? React Native? (probably is, besides the xml like syntax, again state management?)
Quite interesting !
As far as the differentiator: backend. If you're sold on client-side development then I don't think our solution is for you. If however you value SSR and want a balnance between front end and backend that's our market. So for a Hotwire app you could have a Rails app deployed that can accept a "ACCEPT application/swiftui" and we can send the proper template to the client. Just like the browser we parse and build the DOM and insantiate the Views in the native client. There are already countless examples of SSR native apps in the AppStore. As long as we aren't shipping code it's OK, which we're not. Just markup that represents UI state. The state would be managed on the server.
Another areas we differ is that we target the native UI framework, we don't have a unified UI framework. So you will need to know HTML - web, SwiftUI - iOS, Jetpack Compose - Android. This is necessary to establish the primitives that we can hopefully get to the point to build on top of to create a unified UI framework (or maybe someone solves that for us?)
With our wasm compilation, we may even be able to compile React itself and have it emit native templates. No idea if that would work or not. The limits come when the JS library itself is enforcing HTML constraints that we don't observe, like case sensitive tag names and attributes.
What about offline mode? Well for use cases that don't require it you're all set. We have lifecycle templates that ship on device for different app states, like being offline. If you want offline we have a concept that we haven't implemented yet. For Elixir we can just ship a version of the LV server on device that works locally then just does a datasync.
Didn’t Firefox build its UI in XAML long ago?
https://en.m.wikipedia.org/wiki/Extensible_Application_Marku...
Can you elaborate on this?
The writing was more or less on the wall with WASM. I don't know if this project is really The Answer that will solve all of the problems but it sounds like a step in that direction and I like it a lot, despite using neither Swift nor Erlang.
My output looked exactly like an embedded WebKit UIView though - so then the problem became - what was I making that was appreciably better?
cyberax•6h ago
Does this allow somehow to sidestep this? Since the data is all thread-local, it should be possible to use non-atomic counters?
dizlexic•6h ago
https://stackoverflow.com/questions/25542416/swift-with-no-a...
liuliu•6h ago
Swift introduced bunch of ownership keywords to help you to use value objects for most of the needs to sidestep reference-counting and minimize copying.
Of course, to my understanding, "actor" in Swift is a "class"-like object, so it will be reference-counted. But I fail to see how that is different from other systems (as actor itself has to be mutable, hence, a reference object anyway).
brandonasuncion•5h ago
Example here: https://forums.swift.org/t/noncopyable-generics-in-swift-a-c...
An added plus is that the Swift compiler seems to stack-promote a lot more often, compared to class/ManagedBuffer implementations.
llm_nerd•5h ago
https://g.co/gemini/share/51670084cd0f - lame, but it references core concepts.
cyberax•3h ago
slavapestov•3h ago
In Swift 6 this is only true if the value’s type is Sendable.
llm_nerd•3h ago
Though the vast majority of cases where ARC would come into play are of the trivial variety.
elpakal•2h ago
Someone•5h ago
See https://dl.acm.org/doi/10.1145/3243176.3243195:
“BRC is based on the observation that most objects are only accessed by a single thread, which allows most RC operations to be performed non-atomically. BRC leverages this by biasing each object towards a specific thread, and keeping two counters for each object --- one updated by the owner thread and another updated by the other threads. This allows the owner thread to perform RC operations non-atomically, while the other threads update the second counter atomically.“
(I don’t know whether Swift uses this at the moment)