2016-01-05 21 views
8

Pracuję nad Suave 1.0 + Angular 2.0 sample app i bardzo interesujące, aby uruchomić serwer Suave w trybie zegarka, więc zmiany pliku śledzenia serwera (js, css, html) w folderze głównym i podfolderach i automatycznie wysłać refresh do wszystkich otwartych kart przeglądarki z moją aplikacją, gdy jakikolwiek plik zostanie zmieniony.Suave w trybie oglądania (podczas programowania)

lite-server z Angular 2 5min Quckstark może to zrobić i jest bardzo przydatny.

Uważam, że większość zegarków można znaleźć pod numerem latest Steffen Forkmann's post, ale nie jest to zbyt jasne, jak wysłać refresh do otwartych kart przeglądarki.

Proszę podać kompletny kod podobnej implementacji z Suave.

Odpowiedz

11

Kod serwera Suave powinien wyglądać podobnie do tego

#r "packages/Suave/lib/net40/suave.dll" 
#r "packages/FAKE/tools/FakeLib.dll" 

open Fake 
open Suave 
open Suave.Operators 
open Suave.Sockets.Control 
open Suave.WebSocket 
open Suave.Utils 
open Suave.Files 
open Suave.RequestErrors 
open Suave.Filters 
open System 
open System.Net 


let port = 
    let rec findPort port = 
     let portIsTaken = 
      System.Net.NetworkInformation.IPGlobalProperties.GetIPGlobalProperties().GetActiveTcpListeners() 
      |> Seq.exists (fun x -> x.Port = int(port)) 
     if portIsTaken then findPort (port + 1us) else port 
    findPort 8083us 

let logger = Logging.Loggers.ConsoleWindowLogger Logging.LogLevel.Verbose 

let refreshEvent = new Event<_>() 

let handleWatcherEvents (events:FileChange seq) = 
    for e in events do 
     let fi = fileInfo e.FullPath 
     traceImportant <| sprintf "%s was changed." fi.Name 
    refreshEvent.Trigger() 

let socketHandler (webSocket : WebSocket) = 
    fun cx -> socket { 
    while true do 
     let! refreshed = 
     Control.Async.AwaitEvent(refreshEvent.Publish) 
     |> Suave.Sockets.SocketOp.ofAsync 
     do! webSocket.send Text (ASCII.bytes "refreshed") true 
    } 

let cfg = 
    { defaultConfig with 
     homeFolder = Some (__SOURCE_DIRECTORY__) 
     bindings = 
     [ HttpBinding.mk HTTP IPAddress.Loopback port ] 
     listenTimeout = TimeSpan.FromMilliseconds 3000. } 

let app : WebPart = 
    choose [ 
    Filters.log logger logFormat >=> never 
    Filters.path "/websocket" >=> handShake socketHandler 
    Filters.GET >=> Filters.path "/" >=> file "index.html" 
    Writers.setHeader "Cache-Control" "no-cache, no-store, must-revalidate" 
     >=> Writers.setHeader "Pragma" "no-cache" 
     >=> Writers.setHeader "Expires" "0" 
     >=> browseHome 
    NOT_FOUND "Found no handlers." 
    ] 


let watcher = 
    !! ("app/*.js") 
     ++ ("*.html") 
    |> WatchChanges handleWatcherEvents 

try 
    System.Diagnostics.Process.Start(sprintf "http://localhost:%d/index.html" port) |> ignore 
    startWebServer cfg app 
finally 
    watcher.Dispose() 

więc konfiguracja obserwatora że uchwyt zmiany js (generowane przez maszynopis) i html plików i wysłać polecenie refresh do klienta, ale w tym samym czas musimy dodać następujący kod do sekcji head z index.html obsłużyć refresh po stronie klienta

<!-- 3. Listen on refresh events from the server --> 
<script language="javascript" type="text/javascript"> 
    function init() 
    { 
     websocket = new WebSocket("ws://"+window.location.host+"/websocket"); 
     websocket.onmessage = function(evt) { location.reload(); }; 
    } 
    window.addEventListener("load", init, false); 
</script> 

Pełna aplikacja demonstracyjna, którą można znaleźć here