Axxes IT Consultancy

Compiling F# scripts with Fable 2.2

Introduction

With the release of Fable 2.2 it is now (back) possible to compile .fsx files. There are some subtle differences in this approach and in this blog post, I’d like to illustrate how your workflow could be.

Initial setup

Using a script file in Fable 2.2 is actually not all that different from the regular Fable approach (see minimal sample). When using webpack, point your entry to your script file and make sure that the fable-loader is matching .fsx as well.

...
entry: "myScript.fsx",
module: {
        rules: [
            {
                test: /\.fs(x|proj)?$/,
                use: {
                    loader: "fable-loader"
                }
            }
        ]
    }
...

If for example, the content of the script file is merely to print something like


printfn "Works!

Fable already can compile this to the expected console.log statement.

Using dependencies

Of course logging to the console bearly proves anything. How can we import some dependencies and do something useful?

This is where Paket can really shine. Next to being a great alternative to NuGet, it can also generate a script file that contains references (#r) to all the listed dependencies.

Step by step

Paket can be installed as a dotnet cli tool.


dotnet tool install --tool-path .paket Paket --add-source <a href="https://api.nuget.org/v3/index.json" rel="nofollow">https://api.nuget.org/v3/index.json</a> --framework netcoreapp2.1

Moving forward execute

.paket/paket.exe init

to generate an empty

paket.dependencies

.

There we can list whatever packages we need.

F.ex.

storage: none
source https://www.nuget.org/api/v2
framework: netstandard2.0

nuget Fable.Browser.Dom 1.0.0-alpha-004 alpha
nuget Fable.React 5.0.0-alpha-005 alpha

After 

.paket/paket.exe

install, we can generate a load script via

.paket/paket.exe generate-load-scripts -f netstandard2.0 -t fsx

. This creates the following script file:

namespace PaketLoadScripts

#r "C:\\Users\\nojaf\\.nuget\\packages\\fable.core\\2.1.0-alpha-002\\lib\\netstandard2.0\\Fable.Core.dll" 
#r "C:\\Users\\nojaf\\.nuget\\packages\\fable.browser.blob\\1.0.0-alpha-001\\lib\\netstandard2.0\\Browser.Blob.dll" 
#r "C:\\Users\\nojaf\\.nuget\\packages\\fable.browser.event\\1.0.0-alpha-001\\lib\\netstandard2.0\\Browser.Event.dll" 
#r "C:\\Users\\nojaf\\.nuget\\packages\\fable.browser.webstorage\\1.0.0-alpha-001\\lib\\netstandard2.0\\Browser.WebStorage.dll" 
#r "C:\\Users\\nojaf\\.nuget\\packages\\fable.browser.dom\\1.0.0-alpha-004\\lib\\netstandard2.0\\Browser.Dom.dll" 
#r "C:\\Users\\nojaf\\.nuget\\packages\\fable.react\\5.0.0-alpha-005\\lib\\netstandard2.0\\Fable.React.dll" 

Note that storage:none, will reference everything from my global NuGet cache.

Loading the generated script

With a simple #load directive, we can import the generated script.

#load "../.paket/load/netstandard2.0/main.group.fsx"

And from now on we can use our dependencies.

Extra

Depending on what editor you are using, you might want to add

#if INTERACTIVE
#r "netstandard"
#endif

below the #load, as netstandard and fsi will only be fully supported in .NETCore 3.0.

Motivation

So when does this approach make sense?

  • If you are already using Paket.
  • When you only have a single file and you feel like a fsproj file is a bit of an overkill.
  • Or when you want to start out small and switch to a fsproj when the need arises.

Sample

Check out https://github.com/nojaf/fable-fsx-sample for a larger sample.

Final words

I hope you enjoyed this blogpost and it all makes sense. If you have any suggestions or questions please leave a comment. Want to read more about F#? Take a look at Watching files with FAKE 5

Cheers,

Florian

About the author

Florian Verdonck

Florian Verdonck

.NET Consultant

Share this article

GET TO KNOW US BETTER

Get to know Axxes and our corporate culture!

LOOKING FOR EXPERTISE OR A NEW OPPORTUNITY?

Let's get in touch!

Keep up with news and updates in the sector