Skip to content

WebSharper 8.0

Compare
Choose a tag to compare
@Jand42 Jand42 released this 26 Mar 13:42
· 90 commits to master since this release

This is a major release of WebSharper. NuGet version 8.0.0.540.

Templates for .NET Core SDK: dotnet new install WebSharper.Templates::8.0.0.541

WebSharper version 8 is running on .NET 8, the current LTS .NET framework. A WebSharper 9 upgrade is soon in the pipeline. The WebSharper 7 version haven't reached maturity, so it is skipped as a production-ready release. The below change summaries reflect changes since WebSharper 6.

Changes to JavaScript translation

WebSharper 8 writes modern module-based JavaScript code. This is a break from previous versions which still had EcmaScript 5 compatible output that could be directly interpreted by browsers. With WebSharper 8, usually some bundling tool is required if you use code that would import any npm packages or if you want to optimize your site for production. Many WebSharper bindings have been updated to use npm imports.

For an overview of WebSharper's JavaScript translation with F# examples (but everything is also valid for C#), see the WebSharper 8 translation document.

Changes to Sitelets (web projects)

Along with the JavaScript change, using dynamic code lookup has been eliminated, initializing web pages always use explicit import statements. A production-ready mode has been added to serve optimized bundled code.

Please read the WebSharper 8 update guide on how to update your older projects or create a new WebSharper 8 project from a template using dotnet new install WebSharper.Templates.

  • #1359 Web.Controls now use a ws-id attribute on elements to mark where to insert dynamic content.
  • #1361 By default, output follows one class per file rule, and there is an additional root.js for web projects that re-exports everything needed by the site. This file can be used as an entrypoint for a bundler like esbuild.
  • #1372 If you specify "prebundle": true in wsconfig.json, then the WebSharper compiler will create readable npm-based prebundles, and Sitelets runtime will expect fully bundled code export their contents through a global variable called wsbundle. Configure a bundler like esbuild to create a final bundle.
    See new templates for an example.
  • #1438 Prebundling is also supported for offline sitelets. Use a bundler to generate fully offline-compatible JavaScript.
  • #1408 Added a UseWebSharperScriptRedirect helper for Asp.NET Core, which starts up a vite server on the url setting "DebugScriptRedirectUrl" in appconfig.json's "websharper" section.
  • #1403 Added Content.PageFromFile, which serves a html file from application root, while inserting an initializer scripts where exact placeholder <script ws-replace="scripts"></script> is found.

Changes to Remoting and JSON serialization

  • #1343 Remoting now uses a symmetric JSON serialization, requests and responses have use the same serializers. In JavaScript code, a function is created for every RPC function, that wraps this deserialization and handles the asynchronicity.
  • #1346 Web.Control initialization now takes place in a script block, instead of grabbing data from a meta element.
  • #1336 RPC endpoints are exposed by default at yourURL/TypeName/MethodName, and do not expect any custom headers any more, but behave like a standard API.
  • #1424 The above default path can be overridden with the Remote attribute, example: Remote("alternatePath").
  • #1339 Record types can now be used for instance-based remoting. Example:
    type RecordRemote =
        {
            [<Remote>]
            R1 : string -> Async<string>
        }
    let recordRemoteImpl =
        {
            R1 = fun x -> 
                async {
                    return (x + "_fromRecordRemote")
                }
        }
    do AddRpcHandler typeof<RecordRemote> recordRemoteImpl
  • #1047 Interfaces can now be used for instance-based remoting, similar to classes and records.

New features

  • #1299 Added the Import attribute, sample usage:
    [<Import("sayHi.js")>] // imports the default export, applies to all Inlines/Stubs within class
    type SayHi [<Inline "new $imported()">] () =
        
        // FooInst is an instance member, we don't have to refer to an import directly, so its effect is ignored
        [<Inline "$this.FooInst()">]
        member this.FooInst() = X<string>
    
        // Foo is a static member of SayHi class, this inherits the Import attr from the type
        [<Inline "$imported.Foo()">]
        static member Foo() = X<string>
     
        // Bar is a separate named export, we redefine the Import attr which hides the one inherited from the type
        [<Import("Bar", "sayHi.js"); Inline "$imported()">]
        static member Bar() = X<string>
  • #1391 Added WebSharper.JavaScript.ImportFile function which adds a side-effecting import, that can be used for css and other non-code resources.
  • #1347 Added ImportFile helper to WebSharper.InterfaceGenerator, example usage: "default" => T<unit> ^-> T<unit> |> ImportFile (sprintf "highlight.js/styles/default.css" name).
  • #1333 Added JS.Verbatim which takes a string and exact JS code will be printed in the code output. Supports string interpolation to include values. Also JS.jsx for supporting jsx HTML fragments.
  • #1325 You can use "JsOutput": "path" to make the compiler output all generated code from library projects too.
  • #1350 Added support of SPAEntryPoint attribute for library projects. Combined with the "JsOutput" setting, this allows library projects to be used for producing .js files for external use. An $EntryPoint.js file will contain the call for the annotated function.
  • #1337 You can add static members EncodeJson/DecodeJson on a type to enable WebSharper's client-side JSON serialization on them.
  • #1340 Query parameters can be included in Endpoint attribute values: | [<EndPoint "/FindBook?isbn={isbn}&ty={ty}">] FindBook of isbn:string * ty:string option
  • #1388 Added proxy for System.StringBuilder
  • #1389 Added proxy for System.Convert
  • #775 Added proxy for stderr/System.Console.Error
  • #1355 Added the !... operator for F# use, which translates directly to the JavaScript spread operator ...
  • #1383 Metaprogramming: macros defined on the type level is now invoked before the macro on a member. The type level one can return a MacroFallback value to let use the default translation for a member.
  • #1368 Stub attribute is valid for interfaces, with the equivalent effect of Name(""), translating member names without prepended type name.
  • #1373 Metaprogramming: generators now get the expression of the member they are used on, so they can act as decorators, dynamically adjusting the code of the member.
  • #1377 Metaprogramming: you can define your own attribute, put Macro or Generator attribute on them, and your attribute will work as an alias.
  • #1386 You can use "StubInterfaces": true in wsconfig.json to automatically treat all interfaces in your project as a Stub (interface for JavaScript interop).
  • #1395 Stub attribute now accomodates for overloads, keeping the JavaScript name always as is in .NET.
  • #1397 F# option arguments in Stub types translate to plain arguments.
  • #1404 wsconfig.json files can define Debug and Release sections.
  • #1405 Added missing Style property for HTMLElement.

Fixes

  • #1387 Implicit quotations in client-side code are not pre-compiled as a separate member.
  • #1412 Fix dead code elimination around interface methods.
  • #1351 Fix WIG created dlls to have file information when looked at by Windows file properties dialog.

Language features

  • The compilers now run on .NET 8.
  • #1366 F# 8.0 new features: syntax sugar (property shorthand, nested record field copy, etc.), static interface members, try/with within collection expressions
  • #1294 C# 11.0 new feature: list patterns
  • #1367 C# 12.0 new features: primary constructors for non-record classes, collection expressions and the .. operator

Cleanup and optimizations

  • #1445 All standard proxies are now merged into a single WebSharper.StdLib.dll
  • #1362 removed the requestAnimationFrame polyfill.
  • #1364 removed the JSON polyfill.
  • #1431 printf functions now generate cleaner code when a string is used in a %s hole.
  • #1443 Removed UseStdlibCdn and other WebSharper CDN-related settings.
  • #1444 Removed UseMinifiedScripts setting. WebSharper now outputs readable code, to be processed by external JavaScript tooling for production purposes.

Breaking changes

  • The serialization/url changes around remoting can break code if you depended on unspecified internal mechanisms of RPC calls. The goal of the remoting changes is to provide reliable API shapes now.
  • Removed two fields from Resources.Context type: DebuggingEnabled and GetAssemblyRendering, these had a very low chance to be needed from any user code directly.
  • #1351 was achieved by WIG building atop the definitions library. In WIG, make sure you don't have namespace conflicts between your definitions and the defining code, and ideally hide the definitions by making them internal.