Git Product home page Git Product logo

hmr's Introduction

Elmish: Elm-like abstractions for F# applications.

Gitter Windows Build status NuGet version

Elmish implements core abstractions that can be used to build applications following the “model view update” style of architecture, as made famous by Elm. The library however does not model any "view" and is intended for use in conjuction with a DOM/renderer, like React/ReactNative or VirtualDOM. Those familiar with Redux may find Elmish a more natural fit when targeting React or ReactNative as it allows one to stay completely in idiomatic F#.

Elmish abstractions have been carefully designed to resemble Elm's "look and feel" and anyone familiar with post-Signal Elm terminology will find themselves right at home.

See the docs site for more information.

Using Elmish

v2.0 and above releases use dotnet SDK and can be installed with dotnet nuget or paket:

For use in a Fable project: paket add nuget Fable.Elmish -i

For use in a WebSharper project: paket add nuget WebSharper.Elmish -i

If targeting CLR, please use Elmish package: paket add nuget Elmish -i

For v1.x release information please see the v1.x branch For v2.x release information please see the v2.x branch For v3.x release information please see the v3.x branch

Building Elmish

Elmish depends on dotnet SDK 6:

  • dotnet fsi build.fsx or ./build.fsx on a *nix system.

Contributing

Please have a look at the guidelines.

hmr's People

Contributors

akoslukacs avatar alfonsogarciacaro avatar chrsteinert avatar forki avatar kspeakman avatar mangelmaxime avatar olivercoad avatar theimowski avatar vbfox avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

hmr's Issues

Error Partially Qualified Path

Description

When trying to use HMR out in a template, when I try to compile the project after adding

open Elmish.HMR

Below the other open statements, the compilation fails with the message

src/Main.fs(9,6): (9,16) error FSHARP: This declaration opens the namespace or module 'Lit.Elmish.HMR' through a partially qualified path. Adjust this code to use the full path of the namespace. This change will make your code more robust as new constructs are added to the F# and CLI libraries. (code 893)

Repro code

The template is https://github.com/AngelMunoz/Fable.Lit.Templates/tree/main/templates/elmish-lit

I did nothing aside from adding Fable.Elmish.HMR using femto

femto src/App.fsproj install Fable.Elmish.HMR

added open Elmish.HMR below the other open statements.

the final code

module Main

Fable.Core.JsInterop.importSideEffects "./styles.css"

open Elmish

open Lit
open Lit.Elmish
open Elmish.HMR

type State = { counter: int; name: string }

type Msg =
    | Increment
    | Decrement
    | Reset

let private init _ = { counter = 0; name = "World" }

let private update msg state =
    match msg with
    | Increment ->
        { state with
              counter = state.counter + 1 }
    | Decrement ->
        { state with
              counter = state.counter - 1 }
    | Reset -> init state


let private counter
    (props: {| counter: int
               decrement: unit -> unit
               reset: unit -> unit
               increment: unit -> unit |})
    =
    html
        $"""
        <button @click={fun _ -> props.decrement ()}>-</button>
        <button @click={fun _ -> props.reset ()}>Reset</button>
        <button @click={fun _ -> props.increment ()}>+</button>
        <div>{props.counter}</div>
        """

let view state dispatch =
    let counterEl =
        counter
            {| counter = state.counter
               decrement = fun _ -> dispatch Decrement
               increment = fun _ -> dispatch Increment
               reset = fun _ -> dispatch Reset |}

    html
        $"""
        <div>Hello {state.name}!</div>
        {counterEl}
        """


Program.mkSimple init update view
|> Program.withLit "elmish-lit"
|> Program.run

Expected and actual results

Expected the program to compile and run after exectuting npm start

Actual result is the error message mentioned above.

Related information

  • elmish version: 3.1.0
  • fable-compiler version: 3.4.9
  • fable-core version: 3.3.1
  • Operating system: ArchLinux x64

HMR and lazyView

Description

Just wanted to continue the discussion from elmish/react#22 and the somehow related issue from #6.

Repro code

Usage of both packages Fable.Elmish.HMR and Fable.Elmish.React combined result in subparts of the view not updated when using HMR and one of the lazyX functions from Elmish.React.

Expected and actual results

Expected:

One of two behaviors:

  • Both modules work in combination without modification of users code.
  • When using both modules in combination give a meaningful warning/error message that the combination of both modules isn't supported OOB.

Actual:

Certain parts of the view aren't updated and it is hard for the consumer of the two libs to figure out why views aren't updated anymore.

Needs update for Fable 4

Description

Need update for Fable 4 as it fails below error

/src/Client/fable-output/fable_modules/Fable.Elmish.HMR.5.2.0/common.fs(64,9): (64,15) error FSHARP: The value or constructor 'ofType' is not defined. (code 39)
./src/Client/fable-output/fable_modules/Fable.Elmish.HMR.5.2.0/common.fs(90,9): (90,15) error FSHARP: The value or constructor 'ofType' is not defined. (code 39)
./src/Client/fable-output/fable_modules/Fable.Elmish.HMR.5.2.0/common.fs(116,9): (116,15) error FSHARP: The value or constructor 'ofType' is not defined. (code 39)
./src/Client/fable-output/fable_modules/Fable.Elmish.HMR.5.2.0/hmr.fs(184,12): (184,74) error FSHARP: Type mismatch. Expecting a
    'Program<'arg,'model,'msg,'view> -> Program<'arg,obj,obj,obj>'    
but given a
    '(('msg -> bool) * ('model -> unit) -> (Msg<'msg> -> bool) * (Model<'model> -> unit)) -> Program<'a,'model,'msg,'b> -> Program<'a,Model<'model>,Msg<'msg>,'b>'    
The type 'Program<'arg,'model,'msg,'view>' does not match the type '('msg -> bool) * ('model -> unit) -> (Msg<'msg> -> bool) * (Model<'model> -> unit)' (code 1)
./src/Client/fable-output/fable_modules/Fable.Elmish.HMR.5.2.0/hmr.fs(184,62): (184,74) error FSHARP: Type mismatch. Expecting a
    '('model -> Sub<'msg>) -> Model<'model> -> Sub<Msg<'msg>>'    
but given a
    '('model -> Cmd<'a>) -> Model<'model> -> Cmd<Msg<'a>>'    
The type 'SubId * Subscribe<'msg>' does not match the type 'Effect<'a>' (code 1)
./src/Client/fable-output/fable_modules/Fable.Elmish.HMR.5.2.0/hmr.fs(213,44): (213,52) error FSHARP: The value, constructor, namespace or type 'Internal' is not defined. (code 39)
./src/Client/fable-output/fable_modules/Fable.Elmish.HMR.5.2.0/hmr.fs(218,44): (218,52) error FSHARP: The value, constructor, namespace or type 'Internal' is not defined. (code 39)
./src/Client/fable-output/fable_modules/Fable.Elmish.HMR.5.2.0/hmr.fs(223,44): (223,52) error FSHARP: The value, constructor, namespace or type 'Internal' is not defined. (code 39)
./src/Client/fable-output/fable_modules/Fable.Elmish.HMR.5.2.0/hmr.fs(226,36): (226,44) error FSHARP: The value, constructor, namespace or type 'Internal' is not defined. (code 39)
./src/Client/fable-output/fable_modules/Fable.Elmish.HMR.5.2.0/hmr.fs(229,36): (229,44) error FSHARP: The value, constructor, namespace or type 'Internal' is not defined. (code 39)
./src/Client/fable-output/fable_modules/Fable.Elmish.HMR.5.2.0/hmr.fs(231,28): (231,36) error FSHARP: The value, constructor, namespace or type 'Internal' is not defined. (code 39)
Please provide a succinct description of your issue.

HMR crashes the app with Fable.Core 4.3 or/and Fable 4.10.0 and above

Description

HMR crashes the app with Fable.Core 4.3 or/and Fable 4.10.0 or 4.11.0. Downgrading to Fable.Core 4.2 and Fable 4.9.0 makes HMR work again.

Repro code

I encountered this bug when converting a non-trivial Elm app to F# Elmish. I could reproduce it exactly with https://github.com/laurentpayot/fsharp-fable-elmish-example. Inside this repo just do dotnet paket update or dotnet tool update fable and the bug will appear.

Related information

  • elmish version: 4.1
  • fable-compiler version: 4.10.0 and above
  • fable-core version: 4.3
  • Operating system: Ubuntu 23.10

Wrap HMR code in try ... with

Sorry @MangelMaxime, forgot to ask you in #30 to wrap the code for HMR with try ... with. This would be helpful because I recently tried to create a bundle with --define DEBUG but this didn't work because the bundle complained module was not defined (I assume something similar will happen with import.meta) when it was not served by a dev server like Webpack or Vite.

Latest release has a dependency on FSharp.Core 5.0.2

This triggers warnings when restoring from an app using a lower dotnet SDK version.

alfon@LAPTOP-V7RGQGT0 MINGW64 ~/repos/Fable.Lit/sample (main)$ dotnet restore
  Determining projects to restore...
C:\Users\alfon\repos\Fable.Lit\sample\Sample.fsproj : warning NU1605: Detected package downgrade: FSharp.Core from 5.0.2 to 5.0.0. Reference the package directly from the project to select a different version.
C:\Users\alfon\repos\Fable.Lit\sample\Sample.fsproj : warning NU1605:  Sample -> Fable.Elmish.HMR 4.3.0 -> FSharp.Core (>= 5.0.2)
C:\Users\alfon\repos\Fable.Lit\sample\Sample.fsproj : warning NU1605:  Sample -> FSharp.Core (>= 5.0.0)
  All projects are up-to-date for restore.

I'm still confused by this but I think if you add <DisableImplicitFSharpCoreReference>true</DisableImplicitFSharpCoreReference> to the .fsproj PropertyGroup you don't even need the FSharp.Core dependency for libraries (e.g. Fable.AST has no dependencies). Or you can just specify a low FSharp.Core version like 4.7.2.

Add snowpack configuration for the tests

Description

It would be nice to add snowpack to the tests projects.

In #30, I was not able to configure snowpack because it was complaining about react-native not installed which I don't need for the browser. And if, I tried to install it of course it didn't work.

Depending on how snowpack works, it could be added in its own folder like tests/webpack and tests/parcel or use the tests/index.html file as entry point like Vite.

Adding snowpack would also require to:

  1. Add a tests:watch-snowpack to the package.json with a dedicated port
  2. Add Snowpack to the bundler list in tests/App.fs and fix the warning/errors.

When using subscription every version of code is being invoked

Description

When dispatching message from subscription (e.g. timer) and using HMR application is "looping" through all versions of code.

Repro code

Repository: https://github.com/Novakov/fable-elmish-hmr-bug
It's Fable.Template.Elmish.React stripped down from almost everything to minimal Elmish + React + HMR app.

Expected and actual results

Expected:
After changing code, newest version should be used in browser.

Actual:
After changing code, every version of it is used

Related information

  • fable-elmish version: 1.0
  • fable-compiler version: 1.3.1
  • fable-core version: 1.3.1
  • Operating system: Windows 10 x64, Chrome 63, Node 9.10

Fix build.sh permissions for travis

I am under windows and seems like I can't change the permission of ./build.sh and Travis is failing because of that.

@et1975 If you are under a *nix system can you please fix it for me ?

Explore if we can shadow equalsButFunctions or FunctionComponent from Fable.React

Description

If you have a component like:

let private colorCircle =
    FunctionComponent.Of(fun (props : {| Rank : int
                                         Color : Color.Marker.ColorReferences
                                         OnPick : int -> unit |}) ->
        Button.button [ Button.OnClick(fun _ -> props.OnPick props.Rank) ]
            [ str props.Color.Name ]
    , "ColorSelector"
    , equalsButFunctions
    )

Then if you have an HMR call triggered the component instance in the DOM will not be re-render and still have a reference to the old OnPick callback. OnPick callback is created using dispatch for example ChangeColor >> dispatch.

The reason, is we are ignoring functions when determining if we need to redraw it.

We had the same problem with LazyView coming from Elmish and wrote our own version of it source

Bool expressions are unexpectedly false when a module is reloaded.

Description

Bool expressions are returning false unexpectedly.

For example the following will always return false when reloaded with HMR:

prop.classes [if state.Filter = Completed then "is-active"]

As a workaround I'm having to use match instead:

prop.classes [(match state.Filter with | Completed -> "is-active" | _ -> "")]

I noticed this issue when trying out HMR on my Todo App from the Elmish Book and the filter tabs were not getting the "is-active" class.

let filterTabs (state: State) (dispatch: Msg -> unit) =
    div ["tabs"; "is-toggle"; "is-fullwidth"] [
        Html.ul [
            Html.li [
                prop.classes [(match state.Filter with | All -> "is-active" | _ -> "")]
                // prop.classes [if highlight = "All" then "is-active"]
                prop.onClick (fun _ -> dispatch ShowAll)
                prop.children [
                    Html.a [
                        prop.text "All"
                    ]
                ]
            ]
            Html.li [
                prop.classes [(match state.Filter with | Completed -> "is-active" | _ -> "")]
                // prop.classes [if state.Filter = Completed then "is-active"]
                prop.onClick (fun _ -> dispatch ShowCompleted)
                prop.children [
                    Html.a [
                        prop.text "Completed"
                    ]
                ]
            ]
            Html.li [
                prop.classes [(match state.Filter with | NotCompleted -> "is-active" | _ -> "")]
                // prop.classes [if state.Filter = NotCompleted then "is-active"]
                prop.onClick (fun _ -> dispatch ShowNotCompleted)
                prop.children [
                    Html.a [
                        prop.text "Not Completed!"
                    ]
                ]
            ]
        ]
    ]

Repro code

module App

open Elmish
open Elmish.React
open Feliz
open System
open Elmish.HMR

type Todo = {
    Id: Guid 
    Description: string
    Completed: bool
}

type TodoBeingEdited = {
    Id: Guid 
    Description: string
}

type Filter =
    | All
    | Completed
    | NotCompleted

type State = {
    TodoList: Todo list
    NewTodo: string
    TodoBeingEdited: TodoBeingEdited option
    Filter: Filter
}

type Msg = 
    | SetNewTodo of string
    | AddNewTodo
    | ToggleCompleted of Guid 
    | DeleteTodo of Guid
    | StartEditingTodo of Guid 
    | SetEditedDescription of string
    | CancelEdit
    | ApplyEdit
    | ShowAll
    | ShowCompleted
    | ShowNotCompleted


let init(): State = {
    TodoList = [ 
        { Id = Guid.NewGuid(); Description = "Learn F#"; Completed = true } 
        { Id = Guid.NewGuid(); Description = "Learn Elmish"; Completed = false } 
    ]
    NewTodo = ""
    TodoBeingEdited = None
    Filter = All
}

let update msg state = 
    match msg with
    | SetNewTodo todoText -> { state with NewTodo = todoText }
    | AddNewTodo when state.NewTodo = "" -> state
    | AddNewTodo ->
        {
            state with
                NewTodo = ""
                TodoList = List.append state.TodoList [
                    { 
                        Id = Guid.NewGuid()
                        Description = state.NewTodo
                        Completed = false
                    }
                ]
        }
    | DeleteTodo todoId -> 
        {
            state with TodoList = 
                        state.TodoList
                        |> List.filter (fun todo -> todo.Id <> todoId) 
        }
    | ToggleCompleted todoId ->
        {
            state with TodoList = 
                        state.TodoList
                        |> List.map (fun todo ->
                                if todo.Id = todoId 
                                then { todo with Completed = not todo.Completed } 
                                else todo
                            )
        }
    | StartEditingTodo todoId -> 
        {
            state with TodoBeingEdited = 
                        state.TodoList
                        |> List.tryFind (fun todo -> todo.Id = todoId)
                        |> Option.map (fun todoBeingEdited -> { Id = todoId; Description = todoBeingEdited.Description })
        }
    | SetEditedDescription newText ->
        {
            state with TodoBeingEdited =
                        state.TodoBeingEdited 
                        |> Option.map (fun todoBeingEdited -> { todoBeingEdited with Description = newText })
        }
    | ApplyEdit ->
        { 
            state with 
                TodoBeingEdited = None;
                TodoList = 
                        match state.TodoBeingEdited with 
                        | None -> state.TodoList 
                        | Some todoBeingEdited when todoBeingEdited.Description = "" -> state.TodoList
                        | Some todoBeingEdited -> 
                                    state.TodoList
                                    |> List.map (fun todo -> if todo.Id = todoBeingEdited.Id 
                                                                    then { todo with Description = todoBeingEdited.Description} 
                                                                    else todo ) 
        }
    | CancelEdit -> { state with TodoBeingEdited = None}
    | ShowAll -> { state with Filter = All }
    | ShowCompleted -> { state with Filter = Completed }
    | ShowNotCompleted -> { state with Filter = NotCompleted }


let appTitle = 
    Html.p [
        prop.className "title"
        prop.text "Elmish To-Do List"
    ]

let inputField (state: State) (dispatch: Msg -> unit) =
    Html.div [
        prop.classes [ "field"; "has-addons" ]
        prop.children [
            Html.div [
                prop.classes [ "control"; "is-expanded" ]
                prop.children [
                    Html.input [
                        prop.classes [ "input"; "is-medium" ]
                        prop.valueOrDefault state.NewTodo
                        prop.onChange (SetNewTodo >> dispatch)
                        prop.onKeyPress (key.enter, fun event -> dispatch AddNewTodo )
                    ]
                ]
            ]

            Html.div [
                prop.className "control"
                prop.children [
                    Html.button [
                        prop.classes [ "button"; "is-primary"; "is-medium" ]
                        prop.onClick (fun _ -> dispatch AddNewTodo)
                        prop.children [
                            Html.i [
                                prop.classes [ "fa"; "fa-plus" ]
                            ]
                        ]
                    ]
                ]
            ]
        ]
    ]

let div (classes: string list) (children: Fable.React.ReactElement list) =
    Html.div [
        prop.classes classes
        prop.children children
    ]

let renderTodoEdit (todoBeingEdited: TodoBeingEdited) (dispatch: Msg -> unit) =
    div [ "box" ] [
        div [ "columns"; "is-mobile"; "is-vcentered" ] [
            div [ "column" ] [
                div [ "control"; "is-expanded" ] [
                    Html.input [
                        prop.classes [ "input"; ]
                        prop.valueOrDefault todoBeingEdited.Description 
                        prop.onChange (SetEditedDescription >> dispatch)
                        prop.onKeyDown (fun event -> 
                                                match event.key with 
                                                | "Enter" -> dispatch ApplyEdit 
                                                | "Escape" -> dispatch CancelEdit 
                                                | _ ->  ())
                    ]
                ]
            ]
            div [ "column"; "is-narrow" ] [
                div [ "buttons"] [
                    Html.button [
                        prop.classes [ "button"; "is-success"]
                        prop.onClick (fun _ -> dispatch (ApplyEdit))
                        prop.children [
                            Html.i [ prop.classes [ "fa"; "fa-floppy-disk" ] ]
                        ]
                    ]

                    Html.button [
                        prop.classes [ "button"; "is-danger" ]
                        prop.onClick (fun _ -> dispatch CancelEdit)
                        prop.children [
                            Html.i [ prop.classes [ "fa"; "fa-times" ] ]
                        ]
                    ]
                ] 
            ]
        ]
    ]


let renderTodo (todo: Todo) (dispatch: Msg -> unit) =
    div [ "box" ] [
        div [ "columns"; "is-mobile"; "is-vcentered" ] [
            div [ "column" ] [
                Html.p [
                    prop.style [ if todo.Completed then style.textDecoration.lineThrough ]
                    prop.className "subtitle"
                    prop.text todo.Description
                ]
            ]
        

            div [ "column"; "is-narrow" ] [
                div [ "buttons"] [
                    Html.button [
                        prop.classes [ "button"; if todo.Completed then "is-success"]
                        prop.onClick (fun _ -> dispatch (ToggleCompleted todo.Id))
                        prop.children [
                            Html.i [ prop.classes [ "fa"; "fa-check" ] ]
                        ]
                    ]

                    Html.button [
                        prop.classes [ "button"; ]
                        prop.onClick (fun _ -> dispatch (StartEditingTodo todo.Id))
                        prop.children [
                            Html.i [ prop.classes [ "fa"; "fa-pencil" ]]
                        ]
                    ]

                    Html.button [
                        prop.classes [ "button"; "is-danger" ]
                        prop.onClick (fun _ -> dispatch (DeleteTodo todo.Id))
                        prop.children [
                            Html.i [ prop.classes [ "fa"; "fa-trash-can" ] ]
                        ]
                    ]
                ] 
            ]
        ]
    ]

let todoList (state: State) (dispatch: Msg -> unit) = 
    Html.ul [
        prop.children [
            let todos = 
                state.TodoList
                |> List.filter (fun todo -> 
                    match state.Filter with 
                        | Completed -> todo.Completed = true 
                        | NotCompleted -> todo.Completed <> true 
                        | All -> true 
                )
            for todo in todos ->
                    match state.TodoBeingEdited with 
                    | Some todoBeingEdited when todo.Id = todoBeingEdited.Id -> renderTodoEdit todoBeingEdited dispatch
                    | _ -> renderTodo todo dispatch
        ]
    ]

let filterTabs (state: State) (dispatch: Msg -> unit) =
    div ["tabs"; "is-toggle"; "is-fullwidth"] [
        Html.ul [
            Html.li [
                prop.classes [(match state.Filter with | All -> "is-active" | _ -> "")]
                // prop.classes [if highlight = "All" then "is-active"]
                prop.onClick (fun _ -> dispatch ShowAll)
                prop.children [
                    Html.a [
                        prop.text "All"
                    ]
                ]
            ]
            Html.li [
                prop.classes [(match state.Filter with | Completed -> "is-active" | _ -> "")]
                // prop.classes [if state.Filter = Completed then "is-active"]
                prop.onClick (fun _ -> dispatch ShowCompleted)
                prop.children [
                    Html.a [
                        prop.text "Completed"
                    ]
                ]
            ]
            Html.li [
                prop.classes [(match state.Filter with | NotCompleted -> "is-active" | _ -> "")]
                // prop.classes [if state.Filter = NotCompleted then "is-active"]
                prop.onClick (fun _ -> dispatch ShowNotCompleted)
                prop.children [
                    Html.a [
                        prop.text "Not Completed!"
                    ]
                ]
            ]
        ]
    ]

let render (state: State) (dispatch: Msg -> unit) =
    Html.div [
        prop.style [ style.padding 20 ]
        prop.children [
            appTitle
            inputField state dispatch
            filterTabs state dispatch
            todoList state dispatch
        ]
    ]

Program.mkSimple init update render
|> Program.withReactSynchronous "elmish-app"
|> Program.run

Expected and actual results

Using if statements with HMR the is-active class is not reapplied:
image

Using match with HMR the is-active class is reapplied:
image

Related information

  • elmish version: 4.0.2
  • fable-compiler version: 4.1.4
  • fable-core version: 4.0
  • Operating system: MacOS 13.4.1
  • Vite: 4.4.4

HMR crash app

Description

Please provide a succinct description of your issue.

Repro code

Please provide the F# code to reproduce the problem.
Ideally, it should be possibe to easily turn this code into a unit test.

Expected and actual results

Please provide the expected and actual results.

Related information

  • elmish version:
  • fable-compiler version:
  • fable-core version:
  • Operating system:

HMR breaks the whole app after dispatching any message

Description

On the initial load, HMR works properly and I am able to make changes on the fly:

hmr-working

but after dispatching any message, the whole dispatch loop is frozen and the application
stops working

hmr-not-working

Repro code

To reproduce the bug, I made a repo elmish-hmr-bug, follow the steps:

  • git clone https://github.com/Zaid-Ajaj/elmish-hmr-bug.git
  • cd elmish-hmr-bug
  • npm install
  • npm start
  • navigate to localhost:8080
  • Verify that HMR works at first before dispatching any message
  • Dispatch a message using the "+" or "-" buttons
  • Make changes to source code
  • Verify that nothing changes and that you cannot dispatch any more messages

Expected and actual results

Expected HMR to work after dispatching a message.

Related information

  <ItemGroup>
    <PackageReference Include="Fable.Elmish.HMR" Version="4.0.0" />
    <PackageReference Include="Fable.Elmish.React" Version="3.0.1" />
  </ItemGroup>
  • elmish version: 3.0 stable
  • fable-compiler version: 2.3.0
  • fable-core version: 3.0 stable
  • Operating system: Windows 10

Recent updates do not work with SAFE Template

How to fix if you come accross this error

If you're using the SAFE template, upgrade it to Webpack 5.

Alternatively, if you prefer to stack with Webpack 4 at the moment, you can pin the version of Fable.Elmish.Hmr in your paket.dependencies file:

Fable.Elmish.Hmr == 4.1

Then paket install

dotnet paket install

Description

Using version 4.2 or above of Fable.Elmish.HMR leads to an error during webpack build.

Repro code

With safe template v3.1.1

dotnet new safe
dotnet tool restore
dotnet paket update Fable.Elmish.HMR
dotnet run

There is also a repo linked in SAFE-Stack/SAFE-template#481

client: ERROR in ./output/App.js 113:14
client: Module parse failed: Unexpected token (113:14)
client: File was processed with these loaders:
client:  * ../../node_modules/source-map-loader/dist/cjs.js
client: You may need an additional loader to handle the result of these loaders.
client: |     }
client: |     const hmrState = new FSharpRef(null);
client: >     if (import.meta.hot) {
client: |         window.Elmish_HMR_Count = ((window.Elmish_HMR_Count == null) ? 0 : (window.Elmish_HMR_Count + 1));
client: |         import.meta.hot.accept();
client: Child html-webpack-plugin for "index.html":
client:      1 asset
client:     Entrypoint undefined = index.html
client:     [../../node_modules/html-webpack-plugin/lib/loader.js!./index.html] /home/oliver/repos/safenew/node_modules/html-webpack-plugin/lib/loader.js!./index.html 703 bytes {0} [built]
client:     [../../node_modules/lodash/lodash.js] /home/oliver/repos/safenew/node_modules/lodash/lodash.js 531 KiB {0} [built]
client:     [../../node_modules/webpack/buildin/global.js] (webpack)/buildin/global.js 472 bytes {0} [built]
client:     [../../node_modules/webpack/buildin/module.js] (webpack)/buildin/module.js 497 bytes {0} [built]

Related information

  • elmish version: 3.1
  • fable-compiler version: 3.2.11
  • fable-core version: 3.6
  • Operating system: manjaro

Missing `runWith` in v3.0.2

Description

opening Fable.Elmish.HMR shadows Program.run but not Program.runWith because there's no such function in HMR

Repro code

Program.mkProgram init update view
#if DEBUG
|> Program.withConsoleTrace
#endif
|> Program.withReact "elmish-app"
#if DEBUG
|> Program.withDebugger
#endif
|> Program.runWith "argument"

Expected and actual results

Full page reload occurs when modifying source file, while hot replace should be performed

Related information

  • elmish version: 3.0.2
  • fable-compiler version: 2.1.8
  • fable-core version: 2.0.3
  • Operating system: mac 10.14

Fable 2

Could you please update dependencies to Fable.Core/Fable.PowerPack 2 (prerelease) and publish a prerelease version?

App locks with HMR > 3.0, but works with < 3.0

Description

I have a problem where if I use version 3 of the HMR nuget, the app locks after the first HMR update after I have made state changes, whereas with version 2, it works fine.

Repro code

Repro solution: fulma-demo.zip

(Not minimal, it's a slightly modified version of https://github.com/MangelMaxime/fulma-demo where I've replaced the app contents with a TodoMVC sample. Contains a lot of dead code from the fulma demo; only the code in src/App.fs is relevant.)

  1. Run fake build -t Watch
  2. Open localhost:8080
  3. Make any Elmish model change (e.g. write in the text field)
  4. Make a change in src/App.fs that should be visible with HMR (e.g. replace "TodoMVC" near the bottom with another string)
  5. Observe HMR works
  6. Now open paket.dependencies and remove < 3 from nuget Fable.Elmish.HMR < 3
  7. Run paket update
  8. Remove |> Program.withHMR from src/App.fs
  9. Repeat 1–5, notice how that the app is locked and won't respond to input.
  • elmish version: 2.0.3
  • fable-compiler version: 2.0.10 (output of dotnet fable --version, don't know if that's the right thing)
  • fable-core version: 2.0.1
  • Operating system: Win 10

HMR reloads page

Description

Instead of replacing the modified code, the whole page gets reloaded

Repro code

  • Follow all instructions from the docs
  • Instead of serving everything from webdevserver, link to the bundled script file and serve everything else from a second server (a CMS in my case)

Expected results

On an App update, it should just reload the new js module, and the state should remain.

Actual results

However, the page including the new code is reloaded, but the state is gone.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.