f# in web development: websharper - cornerstone in web development: websharper ... which depends on...

27
#devsum15 F# in web development: WebSharper Michał Śliwoń @mihcall [email protected]

Upload: truongquynh

Post on 22-May-2018

214 views

Category:

Documents


1 download

TRANSCRIPT

Page 1: F# in web development: WebSharper - Cornerstone in web development: WebSharper ... which depends on the username. Content.PageContent < ... • Babylon.js • ... Deployment options

#devsum15

F# in web development: WebSharper

Michał Śliwoń

@mihcall [email protected]

Page 2: F# in web development: WebSharper - Cornerstone in web development: WebSharper ... which depends on the username. Content.PageContent < ... • Babylon.js • ... Deployment options

What is WebSharper?

• F# Web Development Framework• Abstractions, abstractions everywhere

• Ecosystem (~50 extensions)• Full-stack F#, not only F#->Javascript compiler• Developed by IntelliFactory (~270 projects, all in F#), eating

their dog food• Apache license

Page 3: F# in web development: WebSharper - Cornerstone in web development: WebSharper ... which depends on the username. Content.PageContent < ... • Babylon.js • ... Deployment options

Features

• Client-Server apps• Type system across client and server

• Plumbing for client-server apps• Idiomatic abstractions

• Pagelets• Sitelets• Formlets• Flowlets• Piglets

• Typed wrappers for Javascript libraries

Page 4: F# in web development: WebSharper - Cornerstone in web development: WebSharper ... which depends on the username. Content.PageContent < ... • Babylon.js • ... Deployment options

When to use WebSharper?

• You love F#• You’re probably NOT in love with Javascript

Page 5: F# in web development: WebSharper - Cornerstone in web development: WebSharper ... which depends on the username. Content.PageContent < ... • Babylon.js • ... Deployment options

When it’s „probabaly” not advised to use WebSharper?• You love Javascript• You just want something to spit some nice Javascript code• You can’t figure out what’s this Functional Programming buzz

all about

Page 6: F# in web development: WebSharper - Cornerstone in web development: WebSharper ... which depends on the username. Content.PageContent < ... • Babylon.js • ... Deployment options

Starting with WebSharper

• Visual Studio• Nuget• vsix installer (with Visual Studio Templates)

• Xamarin Studio• Add-in

• CloudSharper• Web IDE, collaboration platform (Cloud)• Executed on local machine

Page 7: F# in web development: WebSharper - Cornerstone in web development: WebSharper ... which depends on the username. Content.PageContent < ... • Babylon.js • ... Deployment options

WebSharper Code Sample

• Client-server

Page 8: F# in web development: WebSharper - Cornerstone in web development: WebSharper ... which depends on the username. Content.PageContent < ... • Babylon.js • ... Deployment options

ASP.NET Integration

• Client-side controls• ... with Remoting

• In ASPX Pages• In Razor Pages• or as Sitelet

Page 9: F# in web development: WebSharper - Cornerstone in web development: WebSharper ... which depends on the username. Content.PageContent < ... • Babylon.js • ... Deployment options

OWIN Integration

• WebSharper.Owin.RemotingMiddleware• WebSharper.Owin.SiteletMiddleware

Page 10: F# in web development: WebSharper - Cornerstone in web development: WebSharper ... which depends on the username. Content.PageContent < ... • Babylon.js • ... Deployment options

Sitelets

• primary way to create server-side content• Route requests• Generate HTML or JSON responses

• Sitelets routing• Mapping from URLs to actions• Mapping from actions to URLs• Mapping from actions to content

• Custom Attributes to Sitelet.Infer

Page 11: F# in web development: WebSharper - Cornerstone in web development: WebSharper ... which depends on the username. Content.PageContent < ... • Babylon.js • ... Deployment options

open WebSharper.Sitelets

type Action =| Index| Stats of username: string| BlogArticle of id: int * slug: string

type MyWebsite() =interface IWebsite<Action> with

member this.Sitelet =Sitelet.Infer <| function

| Index ->// Content of the index pageContent.PageContent <| fun ctx ->

{ Page.Default withTitle = Some "Welcome!"Body = [H1 [Text "Index page"]] }

| Stats username ->// Content of the stats page, which depends on the usernameContent.PageContent <| fun ctx ->

{ Page.Default withBody = [Text ("Stats for " + username)] }

| BlogArticle (id, slug) ->// Content of the article page, which depends on id and slugContent.PageContent <| fun ctx ->

{ Page.Default withBody = [Text (sprintf "Article id %i, slug %s" id slug)] }

member this.Actions = []

[<assembly: WebsiteAttribute(typeof<MyWebsite>)>]do ()

Page 12: F# in web development: WebSharper - Cornerstone in web development: WebSharper ... which depends on the username. Content.PageContent < ... • Babylon.js • ... Deployment options

Sitelet.Infer Custom Attributes

• [<Method("GET", "POST", ...)>]• [<CompiledName "string">]• [<Query("arg1", "arg2", ...)>]• [<Json "arg">]• [<FormData("arg1", "arg2", ...)>]• [<DateTimeFormat(string)>]• [<Wildcard>]

Page 13: F# in web development: WebSharper - Cornerstone in web development: WebSharper ... which depends on the username. Content.PageContent < ... • Babylon.js • ... Deployment options

module Content =open Http

val PageContent : (Context<'Action> -> Page) -> Content<'Action>val PageContentAsync : (Context<'Action> -> Async<Page>) -> Content<'Action>

val WithTemplate : Template<'T> -> (Context<'Action> -> 'T) -> Content<'Action>val WithTemplateAsync : Template<'T> -> (Context<'Action> -> Async<'T>) -> Content<'Action>

val JsonContent : (Context<'Action> -> 'T) -> Content<'Action>val JsonContentAsync : (Context<'Action> -> Async<'T>) -> Content<'Action>

val CustomContent : (Context<'Action> -> Response) -> Content<'Action>val CustomContentAsync : (Context<'Action> -> Async<Response>) -> Content<'Action>

module Content =/// Permanently redirect to an action. (HTTP status code 301)val Redirect : 'Action -> Content<'Action>

/// Permanently redirect to a URL. (HTTP status code 301)val RedirectToUrl : string -> Content<'Action>

/// Temporarily redirect to an action. (HTTP status code 307)val RedirectTemporary : 'Action -> Content<'Action>

/// Temporarily redirect to a URL. (HTTP status code 307)val RedirectTemporaryToUrl : string -> Content<'Action>

Page 14: F# in web development: WebSharper - Cornerstone in web development: WebSharper ... which depends on the username. Content.PageContent < ... • Babylon.js • ... Deployment options

HTML Combinators

• Server-sidelet myDiv = Div []// HTML: <div></div>

let myRule = HR []// HTML: <hr/>

let mySection = Section [HR []]// HTML: <section><hr/></section>

let myP = P [Class "paragraph"] -< [Text "This is a paragraph."]// HTML: <p class="paragraph">This is a paragraph.</p>

• Client-side

Page 15: F# in web development: WebSharper - Cornerstone in web development: WebSharper ... which depends on the username. Content.PageContent < ... • Babylon.js • ... Deployment options

HTML Templates

• ${NameOfHole}• data-replace="NameOfHole"• data-hole="NameOfHole"

Page 16: F# in web development: WebSharper - Cornerstone in web development: WebSharper ... which depends on the username. Content.PageContent < ... • Babylon.js • ... Deployment options

UI.Next

• Reactive Web Development

open WebSharper.UI.Nextopen WebSharper.UI.Next.Html

let basicExample() =

let rvContent = Var.Create ""let vUpperContent =

rvContent.View|> View.Map (fun t -> t.ToUpper())

Div [] [Doc.Input [] rvContentLabel [] [Doc.TextView vUpperContent]

]

Page 17: F# in web development: WebSharper - Cornerstone in web development: WebSharper ... which depends on the username. Content.PageContent < ... • Babylon.js • ... Deployment options

Formletstype Person = {

Name: stringEmail: string

}

[<JavaScript>]let PersonFormlet : Formlet<Person> =

let nameF = Controls.Input "" |> Validator.IsNotEmpty "Empty name not allowed" |> Enhance.WithValidationIcon|> Enhance.WithTextLabel "Name"

let emailF = Controls.Input ""|> Validator.IsEmail "Please enter valid email address" |> Enhance.WithValidationIcon|> Enhance.WithTextLabel "Email"

Formlet.Yield (fun name email -> {Name = name; Email = email})<*> nameF<*> emailF|> Enhance.WithSubmitAndResetButtons|> Enhance.WithLegend "Add a New Person"|> Enhance.WithFormContainer

[<JavaScript>]let Main () =

Div [PersonFormlet]

Page 18: F# in web development: WebSharper - Cornerstone in web development: WebSharper ... which depends on the username. Content.PageContent < ... • Babylon.js • ... Deployment options

Piglets

• Yes...

• Similar to Formlets but gives you control over HTML generation

Page 19: F# in web development: WebSharper - Cornerstone in web development: WebSharper ... which depends on the username. Content.PageContent < ... • Babylon.js • ... Deployment options

Extensions

• Sencha Architect• jQuery• Kendo UI• Google Visualization• Google Maps• D3, Raphael, Dojo• Babylon.js• ...

Page 20: F# in web development: WebSharper - Cornerstone in web development: WebSharper ... which depends on the username. Content.PageContent < ... • Babylon.js • ... Deployment options

Deployment options

• OWIN Containers• IIS

• Azure Websites

Page 21: F# in web development: WebSharper - Cornerstone in web development: WebSharper ... which depends on the username. Content.PageContent < ... • Babylon.js • ... Deployment options

namespace Samples

open WebSharper

open WebSharper.Html.Client

open WebSharper.Google.Maps

[<JavaScript>]

module GoogleMaps =

open WebSharper.JavaScript

let Sample buildMap =

Div [Attr.Style "padding-bottom:20px; width:500px; height:300px;"]

|>! OnAfterRender (fun mapElement ->

let center = new LatLng(37.4419, -122.1419)

let options = new MapOptions(center, 8)

let map = new Google.Maps.Map(mapElement.Body, options)

buildMap map)

Page 22: F# in web development: WebSharper - Cornerstone in web development: WebSharper ... which depends on the username. Content.PageContent < ... • Babylon.js • ... Deployment options

let SimpleMap() =

Sample <| fun (map: Map) ->

let latLng = new LatLng(37.4419, -122.1419)

let options = new MapOptions(latLng, 8)

map.SetOptions options

Page 23: F# in web development: WebSharper - Cornerstone in web development: WebSharper ... which depends on the username. Content.PageContent < ... • Babylon.js • ... Deployment options

let SimpleDirections() =

Sample <| fun map ->

let directionsService = new DirectionsService()

let directionsDisplay = new DirectionsRenderer();

map.SetCenter(new LatLng(41.850033, -87.6500523))

map.SetZoom 7

map.SetMapTypeId MapTypeId.ROADMAP

let a = DirectionsRendererOptions()

directionsDisplay.SetMap(map)

let mapDiv = map.GetDiv()

let dirPanel = Div [ Attr.Name "directionsDiv"]

let j = WebSharper.JQuery.JQuery.Of(mapDiv)

j.After(dirPanel.Dom).Ignore

directionsDisplay.SetPanel dirPanel.Body

let calcRoute () =

let start = "chicago, il"

let destination = "st louis, mo"

let request = new DirectionsRequest(start, destination, TravelMode.DRIVING)

directionsService.Route(request, fun (result, status) ->

if status = DirectionsStatus.OK then

directionsDisplay.SetDirections result)

calcRoute ()

Page 24: F# in web development: WebSharper - Cornerstone in web development: WebSharper ... which depends on the username. Content.PageContent < ... • Babylon.js • ... Deployment options

Other web development options in F#

• Suave.io (simple web development F# library)• Pure F# ASP.NET MVC• FunScript (F# to javascript converter)• Freya (functional-first web stack)• Frank (combinators for composing web applications)• ServiceStack• NancyFx• Canopy (web testing framework)

Page 25: F# in web development: WebSharper - Cornerstone in web development: WebSharper ... which depends on the username. Content.PageContent < ... • Babylon.js • ... Deployment options

How much does it cost?

• Free – $ 0• Mobile - $ 25 / month• Insider Basic (individual) - $ 299 / year• Insider Pro (company) - $ 899 / year

+ Support/Consulting/Training options

Page 26: F# in web development: WebSharper - Cornerstone in web development: WebSharper ... which depends on the username. Content.PageContent < ... • Babylon.js • ... Deployment options

Resources

• http://websharper.com/docs• „Expert F# 3.0” Don Syme, Adam Granicz, Antonio Cisternino

Page 27: F# in web development: WebSharper - Cornerstone in web development: WebSharper ... which depends on the username. Content.PageContent < ... • Babylon.js • ... Deployment options

#devsum15

Thank you DevSum 2015!@mihcall

@mihcall [email protected]