使用 WebSharper 在服务器端呈现 SVG

Using WebSharper to render SVGs server-side

我正在尝试在服务器端生成 SVG,然后使用 WebSharper 的 RPC 机制将它们传递给客户端。我基于 websharper-web 模板,使用 dotnet 核心。

为了完整起见,我这样渲染模板:

// Site.fs
    let Draw ctx =
        Templating.Main ctx EndPoint.Home "Home" [
            h1 [] [text "Say Hi to the server!"]
            div [] [client <@ Artery.Main() @>]
        ]

我定义了一个 RPC 方法,return我的 SVG:

module Server =
    [<Rpc>]
    let FetchDrawing () =
        let center = {Svg.Point.X=50; Svg.Point.Y=50}
        let r = 25
        let circle = Svg.Shape.Circle(center=center, radius=r)
        async {
            return circle |> Svg.render
        }
    // Returns an SvgElement.circle with cx, cy, and r set

到目前为止一切正常,但我无法弄清楚如何在客户端中正确加载它。我得到的最接近的是:

[<JavaScript>]
module Artery =
    let Main() =
        let circle = Server.FetchDrawing()
        div [] [
            SvgElements.svg [SvgAttributes.height "100"
                             SvgAttributes.width "100"] [
                Doc.Async circle
                ]
            ]

这个:

  1. 类型检查和编译
  2. 运行
  3. 运行时抛出 JavaScript 错误

具体来说,我得到 TypeError: x is not a function。 SourceMaps link 错误深入到一个名为 Snap.fs 的 WebSharper 库中,它揭示了......相对较少的光。

这是 WebSharper 中的错误吗? 这应该有效吗?在这样的客户端文档中包含 Async<Doc> 的正确方法是什么?如果可能的话,我 更喜欢 不要使用 jQuery ——我宁愿 return JS 在 SVG 中异步加载,而不是 jQuery 稍后插入 - 但如果这是这里的最佳做法,我愿意接受 JQuery 的回答。

快速回答是否定的,不幸的是,这不会按原样工作,并且很抱歉当我早些时候在 F# Slack 频道上给你指导时没有想得更清楚。一方面,它是 WebSharper 编译器 限制 不发出不能将 Doc 值从 RPC 传递到客户端的警告。 WebSharper documentation page for remoting 列出了可以参与此类交换的类型的要求,不幸的是 Doc 不符合条件。

另一方面,有人提议使 RPC 调用更符合序列化,例如 dotnet-websharper/core#930,为使更多类型在 RPC 中工作铺平道路,或者可以直接支持Doc RPC 中的值直接启用您的场景,仅仅是因为它们 应该 工作。这确实是少数需要涵盖的极端案例之一。

您现在可以做的是将您的 RPC 更改为 return 适合您需要的自定义 SVG 表示(例如一些形状的 AST),并使用它来转换为 Doc 在客户端。