Today’s article will look at combining Fable and Cordova to make a mobile application. For those not familar with these projects, a little context may be helpful. Fable compiles F# to Javascript and Cordova facilitates mobile app development using HTML and Javascript. Throw in some Elmish, and its a party. Joining these technologies provides some unique possibilities. Specifically this is an interesting way to leverage F# for mobile development.
The goal will be to make a very simple hello world mobile app. There are a couple steps to get there, none of which are too complicated. To follow along, you will need the following prerequisites. Make sure you have .NET Core and NodeJs installed. Next, Cordova must be installed: npm install -g cordova
. Now that the building blocks are installed, it is time to get started.
First, the Cordova project will be created and initialized with the supported platforms. browser
is useful for the development process, while android
is the real target. If you’re of an iOS leaning, it can be the mobile target instead, or as an addition.
1 | cordova create HelloWorld |
Second, the Fable part of the project needs created. From inside the main project, create a new F# app and add the basic Fable requirements. The requirements come in two parts: dotnet and javascript. For this sample app this will be all that is needed, although a fuller functional app may have more dependencies.
1 | dotnet new console -lang F# -n App |
In the main project directory add the javascript dependencies.
1 | npm install fable-compiler --save |
Third, it is time to wire the projects together, which is where webpack enters the picture. The Fable sample project already uses webpack, the config just needs some adjustments in order to publish the results to cordova (instead of a website).
1 | npm install webpack --save |
In the main project directory, webpack needs a config file webpack.config.js
file with the following contents. This tells webpack to process the newly create F# app project, and use the fable-loader to process files. The destination bundle file generated is placed in Cordova’s www/js
directory.
1 | var path = require("path"); |
The project directory should look something like this:
1 | HelloWorld |
Now that the main project structures have been put into place, it is time to put the code together. The Cordova project needs to be able to consume the generated Fable bundle created by webpack. This is done by editing the Cordova index page www/index.html
. The contents can be reduced to below. The key points here are the elmish-app
div and the bundle.js
include.
1 |
|
Cordova is set to accept some Fable code, now it is time to get to the F#. The contents of App/Program.fs
are below. Since this is about wiring Fable to Cordova I don’t want to spend too much time on the specific F# code. But the code takes a person’s name as input and replies with a Hello message. To add a bit of mobile flavor, it also tracks current acceleration of the device using the devicemotion
event, and publishes that to the screen as well.
1 | module App |
All that is left now is to build and run the app. There are a couple things to keep track of: building the Fable app with webpack, running the app in the browser for development, and building. The commands below touch the surface of development and building, but they at least get you started.
1 | # Run webpack on the fable app |
A running app looks like this:
Being able to build is great, but development can be cumbersome without the ability to watch and auto-build file changes. Taking the next step, let’s add some convenience to the process. Add the following to package.json
.
1 | "scripts": { |
The above command is just the interface, it needs some modifications to webpack.config.js
to perform the desired actions. The below changes wire into the afterEmit
hook to refresh the cordova browser (and start the local service if not already started). The watchOptions
aren’t strictly needed for this, but it helps to stop rebuild spamming, and lower file watch needs. These values can be tuned more for specific needs.
1 | const exec = require("child_process").exec; |
Now, a simple npm run watch
will start the Cordova browser, watch for application updates, and auto-build as files are edited. The development process just got way easier. As a reminder, this is just a sample; more goes into properly building everything out. With that said, this provides a good starting point to getting F# running on mobile using Cordova. I hope you found this useful and/or interesting. Until next time…