

Getting Started with Fable. Routing
source link: https://antongorbikov.com/2020/02/10/getting-started-with-fable-routing/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Photo by Diego Jimenez on Unsplash
Welcome back! This article is the part of “Getting started with Fable” series, so if you missed the previous articles please visit:
The idea of these series is to create a template which can be used as a starting point for enterprise application of any complexity. So as I’d love to see a functional application with routing, state management, unit tests, end-to-end tests, all possible linting tools, code style checkers, environment dependant configuration, build scripts (I hope I didn’t forget anything important).
The main topic of today’s post is application’s routing. I wanted to integrate React Router to the Fable-based application and as far as you are reading this post I’ve succeeded. And yes, I know that there is a Elmish Router which can be used in Fable applications. But there are couple of reasons why I’m not using it:
- It’s an out-of-the-box solution. So it’s just working. It’s too simple, no challenge;
- Most of the front-end engineers are not aware about Elm architecture for front-end applications. The most important part of my “investigation” is whether it’s possible to build application which is readable/maintainable by both .NET and front-end developers and at the same time taking advantage of functional programming as a main paradigm;
- Integrating a third-party React component is in general very important exercise. Nowadays, it’s mostly impossible to develop big enterprise applications without consuming a components library or several independent components (like grid, drag-and-drop lists, etc.).
So yes, I’m aware about Elm architecture but for this series I’ll avoid it.
CI
There are couple of changes in the solution since the last post. And the first thing is integration with GitHub actions. Now Yarn
is available as a part of the default image, hence you must remove a couple of lines from the configuration file as in the screenshot below. Otherwise you’ll experience build failures with messages saying that “yarn is already installed”:

Just a small quality of life change from the GitHub Actions side. I’m not sure about the current state of NPM
but a year ago when I was responsible for configuring the CI environment for my Angular project I faced couple a of issues with NPM
which where resolved by migrating to Yarn
. That’s why on all new projects I’m starting I prefer using Yarn
instead of NPM
.
One last word regarding Yarn
. To keep all your dependencies up to date you can use an interactive console, which is very handy. Just type:
yarn upgrade-interactive --latest
and Yarn
will provide you a way to easily select the packages you want to upgrade ( --latest
parameter can be omitted in case you want to upgrade packages using version patterns provided in packages.json
):

yarn upgrade-interactive
interface
DevServer
Before start with the main dish let’s make one more improvement to our solution. It’s really hard to imagine a web development project without a development server. So let’s get one set up:
yarn add webpack-dev-server --dev
After installing the dependency you need to add a new script to the package.json
file like on the screenshot below (in this and further articles I’ll post some minor code changes as screenshots to emphasize change itself):

The next step is to configure this package:
There are three properties we want to configure right now. The first one is contentBase
. It’s responsible for configuring the output directory which will be used as a root for the web server. The second one, open
, is not required and can be omitted. This is just a small automation script, which will open our application in the specified browser (in my case – Google Chrome). Please, take into account that it’s not recommended to commit this property, because it’s OS dependant (technical limitation), so if you have a team members which are using different OS (MacOS, Linux, Windows) it’s very likely that some of them will have issues with it. And the last but not least is historyApiFallback
. This one is mandatory for client-side routing in Single Page Applications. So in case when you have only one index.html
page and all other routes make sense only on the client ( /users
, /admin/sessions
, etc.) you want the server to always return that single page. That’s where this property comes into play.
Now all you need is to run command:
yarn start
and application will be opened in the browser of choice (by default application will be served at http://localhost:8080/
).
Routing
Here we come. Now when we are finished with all the preparations we can start developing the application itself (finally). Most of the modern applications are Single Page Application, it mean that we need a routing to display different pages on the client side without actual navigation.
At first, we need to install the React Router (it’s the most popular routing module for the React applications, I see no reason to use something else):
yarn add react-router-dom --dev
And now it’s the place where thing getting more interesting. I need to warn you that I’m not an expert in F#
(not even close), I’m just a person who is trying to learn by doing (making mistakes is included). So, what I did:
- There is a manual in the Fable React repository ( link ). I used it as a starting point.
- For the initial showcase I needed a couple of components from the React Router: BrowserRouter, Link, Switch, Route. I’ve created a file for each of the classes. As for me, the process looks similar to writing a type definition for libraries in
TypeScript
(that’s not a surprise, because actually it was a sort of type definition but forF#
. - Then I’ve declared discriminated unions for each set of attributes (parameters) and functions for each component.
Most of the code doesn’t look like rocket science, but there is an interesting code related to JavaScript
interop. It’s not a secret that in JavaScript
functions often receive one parameter which can be of different types (e.g. navigation URL can be simple string or an object with base URL and query parameters as fields). In the F#
there is no way to define such type that’s why Fable
provides a generic type U* (U2, U3, etc.) to make it work. You can see the usage of this type in the link.fs
file.
And now the only thing left is to actually use these definitions. For this purpose let’s modify the App component to create two stub pages with different welcome messages:
The thing I like about this code is that it looks so much similar to the JSX. Seriously, I have an impression that most of the JavaScript/React developers can read this code without significant issues. Each function in this syntax accepts two parameters – two arrays. The first array describes the element attributes, the second – its children.
The only thing I’d like to mention is the !^
operator – it’s the Fable’s type casting operator, it’s required to work with U* generic type. This operator is a sort of syntax sugar for the alternative version which is not so convenient to use: U3.Case*. Case1 means first type from the generic type declaration.
Now you can start the application and see that it’s working!

conclusion
That’s basically it for today. In the next posts I’ll cover even more development topics, so please stay tuned. If you have any questions or faced any issues during following this manual don’t hesitate to write in the comments below.
Thanks a lot for reading! I hope you enjoyed. If you find this material useful, don’t forget to subscribe and share with your colleagues and friends! Thanks!
Recommend
-
13
Key Takeaways This tutorial demonstrates how to install and use the Istio service mesh in a Kubernetes cluster, and discusses how to best leverage Istio’s routing capabilities. Explo...
-
37
Fable entered its fourth year with a new major version that greatly improves its performance, code-generation, and stability. It took more than six months to go from the
-
5
Fable.React.WebComponent 0.0.1 Provides a compile-time transformation to generate web components from react compone...
-
8
Fable BlogFable December 04, 2020Today is the day, Fable 3 Nagareyama is officially released! Does this mean the latest version is bug-free? Probably not, but at least the install com...
-
9
Fable 3.0.4 F# to JS compiler
-
16
SkillsCast Nagareyama: a new Fable, faster, more powerful and easier to use: Bonus Q&A Session
-
15
[Release News] Fable 3.0.0-nagareyama-rc-010 released!Welcome to Devtalk - the brand new platform for developers! If you’ve been looking for...
-
7
Fable.OidcClient 1.0.2 Fable binding for oidc-client javascript library...
-
4
Getting Started with Fable. Fable 3 and deployment Photo by Kelvin Ang on
-
13
Google Voice is getting some long-overdue rules for routing incoming calls By Haroun Adamu Published 3 hours ago Ca...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK