With all of the recent news about F# Data Providers available on .NET Core as well as progress with getting F# tooling also working without Mono I figured it might be time for me to get some hands on time with the SAFE stack. As I’m just diving in for my first time this post is about getting my prerequisites in order for developing a SAFE app.
Preparing my machine
Hunting around the recently updated documentation for SAFE stack I was eventually able to find the Quick Start guide which lists a few prerequisites.
.NET Core SDK 2.x
Since I’ve already playing around with .NET Core on my machine I went ahead and checked the version I have installed by running the following command.
> dotnet --version 2.1.2
Running this returned the value 2.1.2 which fits the 2.x requirement as specified in the the Quick Start guide however whether this value is truly the .NET Core SDK version or some other version I’m unsure. I’ve given up on making sense out of the versioning strategy with .NET Core a while back so unless I run into problems later I’ll assume I have this step covered.
Yarn package manager
I’ve used yarn before but apparently not on this machine as running
yarn --version returned the typical command not found error message. My initial gut reaction was to install Yarn using chocholatey however half way through I noticed that it was installing Node.js 10 as a dependency which is not what I want since I manage my Node and npm versions using the Nodist. To address this I had to manually uninstall the version of Node 10 that came along for the ride and then re-added it through Nodist using the command
nodist + 10 since the next prerequisite in the list was Node 8.x anyway.
For now, and at least without installing pre-released versions of tools, I believe Ionide and perhaps other tools used by SAFE stack will require mono on Mac/Linux or the full .NET Framework on Windows. Since I’m setting this up on Windows 10 and should have a somewhat recent version of a full .NET Framework (> 4.0) installed I’ll assumed I’ll be covered here as well.
VSCode + Ionide
I already had VSCode installed and updated just recently so I made a quick check to ensure I have the latest version of the Ionide extension installed as well. According to VSCode Extension Marketplace feature it looks like I had this extension installed already and that there are no pending updates with the version 3.19.4 listed as the latest version available at the time of this exercise.
Creating my first SAFE app
To start off I created a new directory named
word-search-safe and ran
git init . to initialize a new git repository as I normally do to start off any project. Next I ran the following commands.
dotnet new -i SAFE.Template
This appeared to run succesfully and listed what looked like all of the project templates I have installed and available locally including one called SAFE-Stack Web App v0.14.0.
dotnet new SAFE -lang F#
Before I make any more changes or run any commands that may alter the state of these files I made sure to snapshot them as my first commit in my local git repository.
> git add . > git commit -m "Add initial project from SAFE template"
Next to build the default project I ran the following build command which reported a slew of different dependencies as they were resolved including ones for FAKE, Fable, Giraffe, as well as many others.
> ./build run
Along with the output I noticed a few indications that there may have been problems with the build.
Could not detect any platforms from ‘UAP10.0.16299’ in X.Y.Z, please tell the package authors
As far as I can tell this message appears to be a warning suggesting that some of the dependencies are not properly built for .NET Standard are instead targeting a specific version of .NET Core. Most of the explanations I could find around this error seem to revolve around UWP apps oddly enough so I’m not sure whether this is a concern or not at the moment. Perhaps a more enlightened reader can fill us less knowledable on the subject in on what this means.
error email@example.com: The engine “node” is incompatible with this module. Expected version “>=4 <=9”.
This error was more straightforward and and it indicated to me that my gamble on relying on node 10 may have not been well placed as it appears that some module (upath perhaps) requires a version of node specifically between 4 and 9. See the full related section of the error output below.
error firstname.lastname@example.org: The engine "node" is incompatible with this module. Expected version ">=4 <=9". error Found incompatible module info Visit https://yarnpkg.com/en/docs/cli/install for documentation about this command. Running build failed. Error: System.Exception: 'C:\Program Files (x86)\Yarn\bin\yarn.cmd install --frozen-lockfile' failed at Microsoft.FSharp.Core.PrintfModule.PrintFormatToStringThenFail@1379.Invoke(String message) at FSI_0005.Build.run(String cmd, String args, String workingDir) in C:\work\jpierson\word-search-safe\build.fsx:line 29 at FSI_0005.Build.clo@39-3.Invoke(Unit _arg3) in C:\work\jpierson\word-search-safe\build.fsx:line 42 at Fake.TargetHelper.runSingleTarget(TargetTemplate`1 target) in D:\code\fake\src\app\FakeLib\TargetHelper.fs:line 626
To resolve this build issue I tried the simplest thing first and added Node 9 to my local environment using the Nodist command
nodist + 9 and then told Nodist to use Node 9 locally with
nodist local 9. After this I checked to ensure that the expected version of Node was reported locally by running
node --version which returned v9.11.1 which fit my expectations.
Next step was to again run
./build run and see if I would have any better luck with node 9 but unfortunately I was still running into the same error. My guess at this point was that the version of node being used by yarn or FAKE was not picking up on the version exposed in the local folder by Nodist. I’ve seen similar issues with npm scripts in the past requiring running
npm start with the
--scripts-prepend-node-path=true option in order to run with the expected version of node.
Seeing that I only have Node installed through Nodist I figured I’d give it the best chance for success by instead defaulting Nodist to node 9 globally by using the command
nodist 9 and then rerunning the build. Satisfyingly this seemed to do the trick as the node related version issue no longer appeared, the build succeeded and page launched in the browser showing the default counter app served up at http://localhost:8080/.
While actively documenting my progress this process took me a little over two hours which puts me at a good stopping point for now. In my next post I’ll try to dig into the source code to get familiar with the code from the template, the architecture, and tooling while making some small tweaks to exercise the development process while using this stack. My background in recent front end development is mainly with React, Elm, and AngularJS so expect to see see some comparisons with those approaches as a dig in further.