F# Bolero - A cóż to takiego? - wprowadzenie
Posty z tej serii:
- F# Bolero - A cóż to takiego? - wprowadzenie
- F# Bolero - A cóż to takiego? - HTML templates
- F# Bolero - A cóż to takiego? - view components
- F# Bolero - A cóż to takiego? - routing
- F# Bolero - A cóż to takiego? - routing - page models
- F# Bolero - A cóż to takiego? - remoting
Programowanie Webowe. Sposób wytwarzania oprogramowania, dzięki któremu produkt może zostać uruchomiony w przeglądarce internetowej. Zagadnienie jest bardzo obszerne. Możliwości realizacji można dzielić na różne kategorie, np. ze względu na miejsce generowania wyniku:
- Server Side - generowanie zawartości po stronie serwera, a następnie przesłanie do klienta - przeglądarki internetowej
- Client Side - generowanie zawartości po stronie klienta - przeglądarce internetowej
Inny podział to sposób generowania wyniku:
- Statyczny - pobieranie gotowej, wcześniej przygotowanej zawartości
- Dynamiczny - generowanie zawartości na żądanie, w momencie jej pobierania
Kategorie można łączyć ze sobą:
- Server Side / Statyczny - pierwsze strony internetowe
- Server Side / Dynamiczny - wyświetlanie strony internetowej w zależności od zapisanych danych
- Client Side / Statyczny - cache przeglądarki internetowej
- Client Side / Dynamiczny - początki języka JavaScript
Na bazie różnych kategorii powstało wiele podejść oraz technologii, które pozwalają realizować końcowe produkty.
Świat F# oferuje wiele z programowania webowego. Moją uwagę przykuło Bolero.

Jakbym miał zobrazować, na czym to polega to, zrobiłbym to tak:
Bolero umożliwia pisanie aplikacji webowych w języku F#. Kod konstruuje się w podejściu Elmish - implementacji architektury Model-View-Update, zapoczątkowanej wraz z pojawieniem się języka Elm. Wynikiem kompilacji jest program, który za pomocą Blazor oraz .NET uruchamiany jest w środowisku WebAssembly - alternatywy dla środowiska JavaScript.
Simple Program
Najszybszy sposób zapoznania się z możliwościami Bolero, to wygenerowanie przykładowego projektu, postępując wg wskazówek ze strony. Utworzony program zawiera implementację głównych feature’ów. Kod, generowany jest na podstawie Template’u, przygotowanego przez Loïc Denuzière - autora Bolero.
Template zawiera parametry, którymi można konfigurować końcowy efekt. Najprostszy program można wygenerować, postępując wg kroków:
- zainstalować Template
dotnet new -i Bolero.Templates- utworzyć projekt
dotnet new bolero-app -o Simple --minimal=true --server=false- uruchomić program
cd Simple
dotnet run -p src/Simple.Client- otworzyć stronę wpisując w przeglądarkę adres wypisany na konsoli np.
http://localhost:5000Najważniejsze elementy wygenerowanego programu to:
Main.fs- plik z głównym kodemStartup.fs- plik z konfiguracjąwwwroot- katalog zawierający statyczne elementy
Główy kod programu wygląda tak:
module Simple.Client.Main
open Elmish
open Bolero
open Bolero.Html
type Model =
{
x: string
}
let initModel =
{
x = ""
}
type Message =
| Ping
let update message model =
match message with
| Ping -> model
let view model dispatch =
text "Hello, world!"
type MyApp() =
inherit ProgramComponent<Model, Message>()
override this.Program =
Program.mkSimple (fun _ -> initModel) update viewPrzejdźmy przez poszczególne elementy:
Klasa MyApp
Komponent ładowany przy starcie. Plik Startup.fs zawiera konfigurację uruchomienia:
builder.RootComponents.Add<Main.MyApp>("#main")Klasa MyApp dziedziczy po klasie ProgramComponent, która w parametrach generycznych przyjmuje Model oraz Message. Uruchomienie następuje w momencie wywołania funkcji mkSimple, która w parametrach przyjmuje opisane poniżej wartości.
Funkcja view
Renderuje widok, czyli to wszystko, co użytkownik widzi na ekranie. Posiada dostęp do aktualnego stanu programu w postaci parametru model. Drugi parametr dispatch pozwala wysyłać Message’e do programu, które umożliwiają kodowanie zachowania.
Funkcja update
Uruchamiana w momencie obsługi Message’a. Parametr message określa jego rodzaj. Stan aktualizuje się, zmieniając wartości w parametrze model.
Discriminated Union Message
Definiuje rodzaje Message’y, jakie można zgłaszać np. sygnalizacja naciśnięcia odpowiedniego przycisku na stronie.
Value initModel
Początkowy stan programu, inicjalizowany przez mkSimple.
Record Model
Model reprezentujący aktualny stan programu.
Powyższy przykład zawiera najprostszą logikę działania - wypisanie tekstu na ekranie. Nie wykorzystuje on wszystkich wymienionych właściwości. Działanie kończy się na funkcji view. Zmieńmy to implementując prosty licznik.
Simple Counter
Definiujemy Model tak, aby przechowywał aktualną wartość licznika
type Model =
{
value: int
}Ustawiamy początkową wartość
let initModel =
{
value = 0
}Definiujemy Message’e
Increment- przesuwa licznik do przoduDecrement- przesuwa licznik do tyłuReset- ustawia początkową wartość
type Message =
| Increment
| Decrement
| ResetAktualizujemy funkcję update, ustawiając odpowiednią wartość licznika w zależności od Message’a
let update message model =
match message with
| Increment -> { model with value = model.value + 1 }
| Decrement -> {model with value = model.value - 1 }
| Reset -> { model with value = 0 }Aktualizujemy funkcję view tak, aby wyświetliła interfejs użytkownika zawierający:
- pokazanie aktualnej wartości licznika
- przyciski przesunięcia licznika w dwie strony
- zresetowanie licznika
Dodatkowo funkcja zgłasza odpowiedni Message w zależności od tego, który przycisk zostanie kliknięty.
Poniższy kod pokazuje jedną z właściwości Bolero - konstruowanie UI w kodzie F#:
let view model dispatch =
concat [
div [] [
button [on.click (fun _ -> dispatch Decrement)] [text "-"]
text (string model.value)
button [on.click (fun _ -> dispatch Increment)] [text "+"]
]
div [] [
button [on.click (fun _ -> dispatch Reset)] [text "Reset"]
]
]Uruchamiamy program
dotnet run -p src/Simple.ClientSprawdzamy efekt w przeglądarce internetowej

Zgodnie z implementacją przycisk + zwiększa wartość licznika, a przycisk - zmniejsza. Przycisk Reset ustawia początkową wartość.
Istnieje jeszcze jeden, bardziej znany, sposób konstruowania UI - za pomocą standardowych znaczników HTML. Strona napisana w HTML reprezentowana jest w kodzie Bolero w postaci tzw. Templates.
Początek Serii
Spędziłem wiele miesięcy w poszukiwaniu sposobu programowania webowego, który najbardziej by mi odpowiadał. Taki sposób znalazłem w świecie F#. Obecnie zapoznaję się z różnymi możliwościami Bolero. Wyniki będę umieszczał na GitHub’e, a poszczególne elementy opisywał w serii, której pierwszy artykuł właśnie czytasz. Zachęcam Cię do własnych eksperymentów. Może taki sposób pisania kodu będzie odpowiadał również Tobie.
W następnym artykule zobaczymy, w jaki sposób używać wyżej wymienionych Templates.
=