Fastoch 0.4.5

There is a newer prerelease version of this package available.
See the version list below for details.
dotnet add package Fastoch --version 0.4.5
                    
NuGet\Install-Package Fastoch -Version 0.4.5
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Fastoch" Version="0.4.5" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Fastoch" Version="0.4.5" />
                    
Directory.Packages.props
<PackageReference Include="Fastoch" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Fastoch --version 0.4.5
                    
#r "nuget: Fastoch, 0.4.5"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Fastoch@0.4.5
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Fastoch&version=0.4.5
                    
Install as a Cake Addin
#tool nuget:?package=Fastoch&version=0.4.5
                    
Install as a Cake Tool

Fastoch !

Fastoch is a virtual DOM for Elmish with minimal dependencies.

What does it mean ?

Fastoche (fastɔʃ, reads like 'fast-osh') means 'easy peasy' in French. Thank you Emmanuelle for the title. I removed the silent 'e' to make it more compact.

Why Fastoch ?

Elmish is a great model to develop robust web applications in F#.

However, having a dependency on React has three main drawbacks:

  • React does more than what is needed by Elmish, and is a bit heavy for the job.
  • React must be added using npm as is it not a Fable component.
  • React is developed by Facebook which is an awful company lead by a masculinist billionaire CEO.

This last point especially was a problem since I'm working on the online version of Transmission(s), a board game against discriminations and sexist violences in public spaces.

How to use it ?

Create a console F# project with fable dotnet tool

mkdir Sample
cd Sample
# create the console app
dotnet new console -lang F#
# add fable as dotnet tool
dotnet new tool-manifest
dotnet tool install fable

Add the Fastoch nuget to your project:

dotnet add package Fastoch

Fastoch copies the Feliz model to build HTML views, and is based on Elmish for the Model View Update part.

The only differences are the namespaces to open, and the function to call on Program to start it.

Write your elmish application in the Program.fs file:

open Elmish
open Fastoch.Feliz
open Fastoch.Elmish

type Model = 
    { Counter: int}

type Action =
    | Increment
    | Decrement
    | Reset

let init() =
    { Counter = 0}, Cmd.none

let update cmd model =
    match cmd with
    | Increment -> { model with Counter = model.Counter + 1}, Cmd.none
    | Decrement -> { model with Counter = model.Counter - 1 |> max 0}, Cmd.none
    | Reset -> { model with Counter = 0}, Cmd.none

let view model dispatch =
    Html.div [
        Html.ul [
            Html.li [
                
                prop.text   $"{model.Counter}"
                if model.Counter = 0 then
                    prop.style [ style.color "green"]
                elif model.Counter >= 10 then
                    prop.style [ style.color "red" ]
            ]
        ]
        Html.button [
            prop.text "+"
            prop.onClick (fun _ -> dispatch Increment )
        ]
        Html.button [
            prop.text "-"
            prop.onClick (fun _ -> dispatch Decrement )
        ]
        Html.button [
            prop.text "Reset"
            prop.onClick (fun _ -> dispatch Reset )
        ]
    ]

Program.mkProgram init update view 
|> Program.withFastoch "app" // here we use: withFastoch
|> Program.run

Add a index.html file to your project:

<!DOCTYPE html>
<html>
    <head>
        <title>Fastoch</title>
        <script src="Program.fs.js" type="module"></script>
    </head>
    <body>
        <div id="app"></div>

    </body>
</html>

Now run it with fable watch and vite:

dotnet fable watch . --run vite .

Et voilà, Fastoch!

Hot Module Replacement (HMR)

Fastoch implements directly HMR.

Without HMR, on code change, fable will emit new js files, vite will reload the application, and the application will restart from initial state like after pressing F5.

With HMR, the state will be persisted between reloads, providing the best development workflow.

To enable HMR Open the Fastoch.Elmish.HMR namespace instead of Fastoch.Elmish:

open Elmish
open Fastoch.Feliz
open Fastoch.Elmish.HMR

HMR is only active in debug, and all specific code will disapear in release mode.

Now run it again with fable watch and vite:

dotnet fable watch . --run vite .

Fable watch mode runs in debug by default, so HMR will be active Change the counter value, and edit the view. Changes are reflected instantly without affecting the counter value.

When building the project with fable, the default mode is release, so HMR code will not be emited.

dotnet fable .
vite build .

Thanks

Thank you Zaid Ajaj for Feliz. All the Html DSL is totally similar, and simply adapted to Fastoch virtual DOM. All code in Fastoch.Feliz namespaces is directly adapted from Feliz. Feliz is under MIT License

The HMR code is imported from Fable.Elmish.HMR do get rid of the indirect React dependency. Fable.Elmish.HMR is under Apache-2.0 License

The Virtual Dom implementation has been tweaked and converted to F# from Matt Esch original implementation.

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.5.0-beta2 69 6/20/2025
0.5.0-beta1 127 6/19/2025
0.4.5 78 6/20/2025
0.4.4 134 6/19/2025
0.4.3 136 6/19/2025
0.4.2 135 6/18/2025
0.4.1 134 6/18/2025
0.4.0 131 6/18/2025
0.3.4 138 6/17/2025
0.3.3 138 6/17/2025
0.3.2 132 6/16/2025
0.3.1 131 6/16/2025
0.3.0 138 6/16/2025
0.2.1 137 6/16/2025
0.2.0 195 6/16/2025
0.1.3 137 6/16/2025
0.1.2 135 6/15/2025
0.1.1 130 6/15/2025
0.1.0 128 6/15/2025