From enterprise to next-generation web: celebrating 11 years with WebSharper
(This article is my contribution to F# Advent - a huge thanks to Sergey Tihon for organizing and running this initiative! - and it is the first part of a string of F# + WebAssembly articles lined up for you in coming days and weeks.)
F# web development is teeming with ideas and OSS projects, and it's often hard to figure out what to pay attention to with all the social media noise. With WebSharper being 11 years old soon, I wanted to take this opportunity to briefly outline the historical circumstances around WebSharper (just some notes in no particular order) that position it for a bright future outlook, and give a quick glimple of what we are working on with it to advance the current state of F# web programming. If you'd rather just skip the history part, feel free to skip to the whats-coming part and see a full WebSharper application run on WebAssembly.
Not your typical community project - a historical perspective
Some of these web abstractions that WebSharper pioneered:
- Sitelets - a server-side abstraction for building microservices and server-sides to web clients.
- Typed endpoints, safe URLs - unique to WebSharper and part of the sitelet abstraction, these enable representing all entry points to an application's client and/or server-side in the type system.
- Type-safe remoting - asyncronous client-server communication and message passing, with the ability to supply server-side functionality via multiple server sides, using an attribute-based notation or interfaces to mark/describe server-side functionality.
- Formlets - declarative user interfaces, also available as reactive formlets built on WebSharper UI. Formlets can be arbitrarily composed and can be used to build highly complex UIs, albeit without much control for render customization.
- Piglets and reactive Forms - providing the same consice, declarative notation as formlets, but with explicit control of the output structure.
- WebSharper UI (previously called UI.Next) - an alternative to React and other reactive libraries, UI provides a reactive application foundation with dynamic data flow.
Back around 2007, open source in the .NET community was not widespread, and we quickly found a solid business opportunity to sell WebSharper as a commercial tech, keeping a free/shareware option (under what we coined as WebSharper Professional and Community.) Customers included Fortune 500 organizations and startups alike. In parallel, we also developed commercial WebSharper applications, for instance, we presented the first line-of-business application written entirely in F# (later followed by an entire umbrella of related services and applications) in CUFP 2009, the commercial users workshop organized under ICFP, one of the most prestigious international FP research/academic conferences. These applications were already in the 30-50k LOC range, proving WebSharper to be a worthy, mature, enterprise-ready technology.
As a proprietary code base at the time, WebSharper met with a fair amount of resistance from the early F# community. Misconceptions like "WebSharper is trying to do too much", "WebSharper is hard to understand", and "WebSharper is too monolithic, frameworks are evil" all came from this prejudice. We listened to this criticism. To juggle our ongoing commercial contracts and further developing WebSharper in parallel, we released WebSharper on a dual license model (GNU GPL for open source projects and commercial license for closed source use), which ensured the viability for the time being, but failed to attract indy developers due to the "copyleft" issues associated with GPL. So ultimately, we released the entire code base on Apache 2.0 (under WebSharper 3 in late 2014).
While I urge everyone to always explore all options to formulate an educated opinion (after all, anything that raises awareness to any F# web development tool helps WebSharper become more visible as well), do consider that popular topics nowadays with other F# web tech (Giraffe, Fable, SAFE, Saturn, etc.), such as creating microservices, calling remote functions, server and client-side debugging, source maps, composable and reactive UI forms, IDE integration and various project templates (just have a look at the last few editions of F# Weekly) have been available for years in the WebSharper ecosystem. Instead, you will find us most active with multi-server RPCs; reactive, native and highly performant UI abstractions; advanced templating for client-server apps and SPAs; client-server reactive models; enhanced performance with web workers; shared, type-safe routing on the client and the server; and other not-so-obvious themes. But all in all, WebAssembly sits very high on our list and we are fully committed to it.
These features ensure that your WebSharper applications scale properly as their complexity increases. Some of the largest WebSharper apps we worked on included 25-30 library projects, compiled incrementally on demand.
npm and friends, the correct approach is to let this happen automatically by using proper WebSharper extensions that declare and embed/reference their dependencies.
Teaser: Bolero - taking WebSharper and F# to WebAssembly
Armed with the above, one of the upcoming things we have been working on is to enable adapting WebSharper applications to run on WebAssembly via Blazor. This is a project we codenamed Bolero that we will be announcing next.
Blazor has a similarly ambitious goal: it aims to run any .NET code on WebAssembly by implementing/compiling a .NET runtime in WASM. This will ultimately enable running .NET applications anywhere where WASM can run. Blazor also aims to implement an IL to WASM path, allowing all .NET languages to compile to WASM directly.
Built on top of these, Bolero enables you to use WebSharper's key features/abstractions to develop Blazor applications. In its ultimate form, it will allow to adapt most WebSharper applications with minimal changes to run on WebAssembly via Blazor. In the first cut we are shipping next, sitelet endpoint types, a slightly modified version of UI's HTML templating type provider as an alternative to Razor, and RPC client-server communication is enabled. Bolero also integrates the Elm Architecture natively via Elmish, making it easy to develop Model-View-Update (MVU) apps that you may have seen with Fable+React, but this time without the JS dependencies and running entirely in WASM.
Consider the TodoMVC challenge:
render function that operates on read-only views of the underlying composite model instead of the model value itself, and doesn't depend on React.js as noted above. It is also considerably shorter due to the use of lenses, UI's V notation and templating.
The matching Bolero implementation (F# to Blazor/WASM) is almost identical, except that the
render function here uses model values as in Elmish, exactly like in the Fable+React version mentioned above. Minor changes were also applied in the app's HTML template to accommodate the change in attributes that the Bolero templating type provider works with, to be more in line with Blazor's data binding notation.
You can see the app running in WASM live. Note the short delay initially as you load the page: this is the time it takes to initialize the Blazor runtime in WASM and download the required .NET framework assemblies.
We are very excited about moving more WebSharper features under the Bolero umbrella, providing an a solid framework to adapt WebSharper applications to run fully in WASM. But even in its current form, the key basic WebSharper features and Elmish/MVU integration are available, and you can develop Blazor SPAs and client-server applications entirely in F# in much of the same way as you are used to with WebSharper.
And one last bit: you may have also noticed in the commits in the past 12 months to the core WebSharper repo, that we have been working on enabling WebSharper to produce TypeScript output as well. Here, we considered tailoring this output to play well with technologies that can translate a subset of TypeScript to WASM. But overall, this approach would be inferior to what Bolero already offers.
11 years is a very long time for any project. WebSharper might just be the oldest F# tech around with a tremendeous track record and impact (at the time of writing, there are 147 NuGet packages for WebSharper) . This would not have been possible without a great deal of perseverance, hard work, and overcoming a great number of challenges.
I would like to thank our WebSharper users, customers, and contributors who continue to appreciate the kind of brevity, abstraction, and productivity that WebSharper brings to web development, our IntelliFactory WebSharper team members, who over the years have worked on WebSharper and its tooling, in no particular order: Loic Denuziere, Andras Janko, Jozsef Uri, Anton Tayanovskyy, Joel Bjornson, Simon Fowler, Ernesto Rodriguez, Diego Echeverri, Istvan Gansperger, Sandor Rakonczai, Sandor Szaloki, Adam Abonyi-Toth, Gergely Fabian, Ramon Snir, Maciej Lopatka, Gyula Kiss, Csaba Hruska, Joel Huang, and our other F# developers, interns, contractors, and staff for the engaging technical and strategic discussions.
I would also like to thank the multitude of people in the community who have contributed to applying F# in web programming. It would be impossible to list everyone, but a very special thanks goes to Dustin Moris Gorski, Ryan Riley, Andrew Cherry, Alfonso Garcia-Caro, ncave, Zaid Ajaj, Krzysztof Cieslak, Maxime Mangel, Eugene Tolmachev, Steffen Forkmann, Henrik Feldt, Robert Pickering, Justin Greene, Zach Bray, Vladimir Matveev, Don Syme, Tomas Petricek, the past and current Microsoft F# team, Colin Gravill, Catalin Bocirnea, Kimserey Lam, Youenn Bouglouan, Taha Hachana, Flechner Romain, Jonathan Nolis, Mariusz Wasak, Andrei Degtiarev, Abelardo Mieres, among many-many others for running inspiring initiatives and building F# web communities. You guys rock!
And last, but not least, I would like to thank Art Scott for making me curious about WebAssembly back in 2015, ahead of everyone else in the community, whose clear vision was spot on, and the Blazor team for bringing .NET to WebAssembly.
Happy coding and Merry Christmas soon!