Wednesday, July 13, 2022
HomeWordPress DevelopmentConcentrating on Node, Bun and Deno With F#

Concentrating on Node, Bun and Deno With F#


Hi there people, right here we’re as soon as once more with extra F#, this time we’ll be speaking about how can we use the fable compiler to focus on bun.sh and deno.land.

As chances are you’ll (or not) know by now if in case you have learn a few of my older posts fable permits you to compile your F# code into fashionable net requirements JavaScript this has loads of benefits for contemporary runtimes like bun/deno which settle for ES modules by default meaning you need not additional course of your compiled JS code if not required it ought to simply work!



What’s node, deno, and bun?

Over the previous decade the JavaScript ecosystem grew exponentially and innovated in lots of areas that had been lacking for JavaScript, it allowed the language to modernize and to allow tooling for net purposes in addition to servers, individuals discovered that generally it is sensible to have the ability to share the code that runs within the browser with the one which runs on the server, node, deno and bun exactly let you try this, they’re JavaScript runtimes constructed on prime of net browser engines like V8 (chromium) and WebKit (safari) though the server code is completely different from the consumer, there may be all the time logic that may be shared between each events be it validation, workflow execution and different cool stuff.



nodejs

Till immediately… it’s nonetheless essentially the most used runtime to deploy server or desktop JavaScript it builds itself on prime of chromium’s V8 engine to energy JavaScript code in a runtime comparable but completely different to the browser.

When node was getting began the JavaScript panorama was vastly completely different however node offered some niceties over browser JavaScript on the time, most notably for me the notion of modules, the format known as commonjs caught the eye of many individuals who needed to show how purposes had been constructed there have been different module techniques on the time, amd, umd, system, and many others however nobody had a definitive answer, browserify was then constructed, webpack got here to the scene, and loads of tooling after (together with Typescript, Babel, ES2015, and different niceties) right here we’re immediately, the node ecosystem is a beast by itself and with the help to ESModules the ecosystem is lastly within the transition to a extra net requirements code which might permit higher supply code sharing among the many browser and node itself.



deno.land

As per the phrases taken from deno’s touchdown web page:

Deno is a straightforward, fashionable and safe runtime for JavaScript, TypeScript, and WebAssembly that makes use of V8 and is in-built Rust.

  • Supplies net platform performance and adopts net platform requirements.
  • Safe by default. No file, community, or surroundings entry, except explicitly enabled.
  • Helps TypeScript out of the field.
  • Ships solely a single executable file.
  • Has built-in improvement tooling like a dependency inspector (deno data) and a code formatter (deno fmt).
  • Has a set of reviewed (audited) normal modules which are assured to work with Deno: deno.land/std.

Deno (which is constructed by the identical one who initially constructed node) is principally one other take to node however with completely different philosophies in some areas, among the most notable and already talked about are typescript help out of the field, it additionally makes use of V8 and is constructed with rust. In contrast to node, deno does not have bundle supervisor, quite than that deno leverages net requirements the place it could possibly and on this case it makes use of URL imports in ESModules to import recordsdata and import maps to maintain naked modules intact, this pairs properly with CDNs like jspm, jsdelivr, skypack and deno’s cdn as properly.



Bun.sh

Bun is the brand new participant within the recreation and oh boi… what a participant it’s!

Bun is a quick all-in-one JavaScript runtime
Bundle, transpile, set up and run JavaScript & TypeScript initiatives — all in Bun.

  • Bun is a brand new JavaScript runtime with a local bundler, transpiler, activity runner and npm consumer built-in.

Bun goals to be appropriate with node the place it could possibly, in addition to being net requirements pushed (like deno) nevertheless it additionally takes classes from the JavaScript ecosystem and tries to supply performant and environment friendly tooling it is like in the event you mixed rollup/esbuild/npm/pnpm/yarn multi function.

One necessary bit is that Bun implements the node decision algorithm which helps rather a lot bringing the present node ecosystem into bun principally virtually out of the field, in reality one in all its promoting options is you could run Subsequent.js initiatives inside bun and not using a problem.

Additionally in contrast to deno and node, Bun most popular to make use of WebKit as an alternative of V8 which appears to be quicker in bun’s benchmarks and properly it’s a very fascinating prospect when you’ll be able to inform people “Hey! do tou wish to make your node quicker? Simply run it in bun!



Will node utilization decline?

Now the creation of bun, and deno does not imply that node goes to die anytime quickly, the concept alone is laughable. Whereas these initiatives purpose to unravel comparable issues, It relies upon how every venture’s developer viewers makes use of them, that may make these initiatives favor extra, much less or completely different use circumstances.

Give it some thought for the second, simply assume what number of frameworks are on the market but most of then co-exist naturally and assist one another out to enhance, fortunately making a JS runtime is not as simple as writing one more framework 🤣.

For us Builders although it provides extra selections on the desk, and that is good competitors drives innovation. Given how every runtime depends extra on net requirements these improvements might find yourself within the requirements and profit everybody on the similar time.

It additionally opens the likelihood that code you write could also be as agnostic as attainable and run with out modifications in numerous runtimes.



Getting again to fsharp

Now what does this imply for the F# people?

Relying on how you utilize F# it may not imply something in any respect or it would imply leveraging the sort security and the ability of F# to put in writing protected code that may carry out properly in a mess of runtimes be it lambda capabilities, net employees like cloudflare’s, or just leverage the superb F# tooling to enhance your codebase and benefit from the properly supported compilation JavaScript goal.

We’ll use a easy console utility for this case.

Word: take into account that you must set up node, deno, or bun relying which one you wish to goal I am going to present the three runtimes however all of them are optionally available!

dotnet new console -lang F# -o fs-sample && cd fs-sample
dotnet new tool-manifest
dotnet software set up fable

# Let's constructed the app instantly simply to check it

dotnet fable -o dist
Enter fullscreen mode

Exit fullscreen mode

These instructions ought to create and construct, and compile JavaScript from the F# console utility
contained in the dist/Program.js file you’ll find the same output to this:

import {
  printf,
  toConsole,
} from "./fable_modules/fable-library.3.7.16/String.js";

toConsole(printf("Hi there from F#"));
Enter fullscreen mode

Exit fullscreen mode

You’ll be able to run this file in the usual technique of your runtime

Word: node requires a bundle.json file with the property "kind": "module" to run with out points

So as to add that simply run npm init -y and add stated property

At this level I can let you know:

That is it, that is all it is advisable to goal JavaScript runtimes with F#

Hopefully this can be a reminder that Fable simply outputs JavaScript , you should use the plain JavaScript as is within the runtimes that help ES2015 (and some newer options) with out the necessity for additional tooling like bundlers, and transpilers or comparable tooling and as I’ve stated earlier than on different posts “Wherever Internet Requirements JavaScript runs, F# code will run as properly

There is a cool function from fable while you use an [<EntryPoint>] attribute, let’s change the Program.fs code to the next

[<EntryPoint>]
let essential argv =
    printf "%A" argv
    0
Enter fullscreen mode

Exit fullscreen mode

after working as soon as once more dotnet fable -o dist the compiled output seems like this

import {
  printf,
  toConsole,
} from "./fable_modules/fable-library.3.7.16/String.js";

(perform (argv) {
  toConsole(printf("%A"))(argv);
  return 0;
})(typeof course of === "object" ? course of.argv.slice(2) : []);
Enter fullscreen mode

Exit fullscreen mode

You’ll be able to run this file in the usual technique of your runtime

  • Node: node dist/Program.js -- -a --b=c outputs: --,-a,--b=c

  • Bun: bun dist/Program.js -- -a --b=c outputs: -a,-b=c

  • Deno: deno run dist/Program.js -- -a --b=c outputs:

Deno does not output something in any respect, and that is as a result of Deno does not use course of.argv like node and bun however quite Deno.args in order that’s one of many few variations you’ll find, additionally bun requires to flee the arguments through -- in any other case it tries to parse them as in the event that they had been bun’s cli arguments.

This entry level perform may be helpful for you relying what are you concentrating on and if you’re wanting ahead to make use of this system’s cli arguments.



Packages

For Node and Bun the bundle story is similar, simply run npm/pnpm/yarn/bun set up and as soon as packages are downloaded simply run issues with bun, though take into account that in the event you’re calling a CLI software that internally calls Node, it will not run in bun however node.

for Deno the story is barely completely different, you should use an import map like this:

{
  "imports": {
    "urlpattern-polyfill": "https://cdn.skypack.dev/pin/urlpattern-polyfill@v5.0.3-5dMKTgPBkStj8a3hiMD2/mode=imports,min/optimized/urlpattern-polyfill.js",
    "http": "https://deno.land/std@0.147.0/http/server.ts"
  }
}
Enter fullscreen mode

Exit fullscreen mode

which in flip lets you do that in deno

import "urlpattern-polyfill";
// or
import { serve } from "http";
Enter fullscreen mode

Exit fullscreen mode

whereas these aren’t “packages” just like the node/bun ones, they behave in the identical method, deno applies cache strategies to permit offline utilization as properly so you do not rely upon web to import your dependencies at runtime.

Does that import map factor really feel acquainted? properly perhaps I spoke about that just a few months in the past once I wrote a couple of venture of mine (Perla) which makes use of import maps to let you write Single Web page Functions with out node put in!



Fable.Node Fable.Bun, Fable.Deno

What about particular APIs for node, deno and bun?

Properly you are in luck if you wish to goal node as a result of Fable.Node has been out for some time and since node is the most well-liked runtime on this listing you will even discover bindings to initiatives like specific through the Glutinum venture that are top quality bindings with check suites to make sure issues do not simply break!

If you need the newer runtimes although… you will have to attend for me to launch the bindings for fable.bun and fable.deno that may let you goal Bun and Deno’s APIs

Now let’s transfer to one thing extra thrilling than only a console



Enter the Bix Experiment

With Each Bun and Deno out I actually needed to see if I might make one thing to check them out each runtimes provide HTTP servers that work with Request and Response which had been launched with the Fetch API within the browsers just a few years in the past

I’ve all the time needed to make a JavaScript framework simply to be a part of the meme and as properly to contribute again what the web has given me totally free through the years, that is the place Bix is available in

Bix is a micro-framework designed with F# in thoughts and that runs on each Deno and Bun!
In principle it additionally ought to even run in a service employee! (intercepting fetch requests) though I have not examined that but.
It gives a normal function handler that coupled with a set of route definitions it could possibly carry a Giraffe/Saturn like framework to life in JavaScript runtimes which is extremely superior! helpful? perhaps not 😅, however superior for me certainly. Let’s examine some code:

open Bix
open Bix.Varieties
open Bix.Handlers
open Bix.Router

open Bix.Bun

let checkCredentials: HttpHandler =
    enjoyable subsequent ctx ->
        let req: Request = ctx.Request
        let bearer = req.headers.get "Authorization" |> Possibility.ofObj
        // dummy handler
        match bearer with
        | None -> (setStatusCode (401) >=> sendText "Not Approved") subsequent ctx
        | Some token -> subsequent ctx

let routes =
    Router.Empty
    // helper capabilities to outline routes
    |> Router.get ("https://dev.to/", enjoyable subsequent ctx -> sendText "Hi there, World!" subsequent ctx)
    |> Router.get ("/posts/:slug", enjoyable subsequent ctx ->
        promise { // promise primarily based handlers are supported
            let slug = ctx.PathParams "slug"
            let! submit = Database.discover slug // database from someplace
            let! html = Views.renderPost submit // views from someplace
            return! sendHtml html subsequent ctx
        }
    )
    |> Router.get ("/json", enjoyable subsequent ctx ->
        let content material =  title = "Bix Server!"; Date = System.DateTime.Now 
        sendJson content material subsequent ctx
    )
    // route composition a'la suave/giraffe is supported
    |> Router.get ("/protected", (checkCredentials >=> (enjoyable subsequent ctx -> sendText "I am protected!" subsequent ctx)))

let server =
    Server.Empty
    |> Server.withRouter routes
    |> Server.withDevelopment true
    |> Server.withPort 5000
    |> Server.run

let mode =
    if server.improvement then
        "Improvement"
    else
        "Manufacturing"

printfn $"{mode} Server began at {server.hostname}"
Enter fullscreen mode

Exit fullscreen mode

For Deno it is not a lot completely different

// open the Bix.Deno module
open Bix.Deno

Server.Empty
// you should use the identical routes with out modifications!
|> Server.withRouter routes
|> Server.withDevelopment true
|> Server.withPort 5000
// the run perform returns a promise in deno due how the std HTTP server works
|> Server.run
|> Promise.begin
Enter fullscreen mode

Exit fullscreen mode

Bix gives some primary http handlers like returning json responses, set standing codes, ship html, and even ship html recordsdata.

Probably the most wonderful (at the very least for me) about that is that… 90% – 95% of micro-framework code is shared code between each runtimes, the one factor that actually modifications is the run and the inner Request handler perform which have to be completely different due to how the servers are began in each runtimes and that they’re completely different in some areas, so we have to summary a few of these particulars away in an effort to make the remainder of the framework re-usable between platforms.

If there is a Request/Response http server for node, ensure that it may be supported as properly

If this peeks your curiosity then go to the venture

A small experimental repository for bun.sh

It is a small repository that provides Fable bindings for Bun.sh and Deno

Additionally as an experimental factor It additionally exposes an F# framework known as Bix (title topic to alter) which works on each Bun and Deno

Though this isn’t one thing severe but, if you’re desirous about make this factor a actuality, be at liberty to ping me and we will work collectively to make it occur.

// For extra data see https://aka.ms/fsharp-console-apps
open Bix
open Bix.Varieties
open Bix.Handlers
open Bix.Router
open Bix.Bun

let checkCredentials: HttpHandler =
    enjoyable subsequent ctx ->
        let req: Request = ctx.Request
        let bearer = req.headers.get "Authorization" |> Possibility.ofObj
        // dummy handler
        match bearer with
        | None -> (setStatusCode (401) >=> sendText "Not Approved") subsequent ctx
        | Some token -> subsequent ctx

let routes =
    Router.Empty
    |>

…

Enter fullscreen mode

Exit fullscreen mode

There are barely extra full samples there (together with server facet rendered endpoint utilizing Feliz.ViewEngine) and provides it a go, I am going to attempt to begin releasing the primary previews over the following days/week however Suggestions is tremendous necessary right here.



Last Ideas

Fable is a really highly effective software to make F# code, type and conciseness obtainable virtually in all places through JavaScript (and shortly different languages), I am really excited to see how bun, deno and node will develop collectively and enhance to turn out to be actually good belongings within the software program developer toolbelt.

Making a framework was additionally enjoyable, I can lastly name myself a JavaScript developer now that I’ve constructed my very own framework 😅 /s if you wish to know extra about how Bix internals work and the way is the whole lot abstracted to simply work in each deno and bun, be at liberty to let me know within the feedback beneath or on twitter!

I might be glad to put in writing one other piece particularly for that function

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

- Advertisment -
Google search engine

Most Popular

Recent Comments