-
Notifications
You must be signed in to change notification settings - Fork 6
Technology Introduction
This project serves as an example of how to use Monaco with F#, FABLE and electron desktop app development. This page serves as an introductory guide to using electron and web technology to write desktop applications.
Node is a now ubiquitous package library and runtime for Javascript. It can be used in two distinct ways: running on a web server (server-side) or running in a browser (client-side). Think of Node as being like the Java standard libraries for Javascript. Node comes as standard with a package manager npm
which automatically downloads and links Node-compatible Javascript packages. Yarn is a plug-in replacement package manager that can be used instead of npm
.
Electron is based on the Chrome browser engine - cut down to make a local desktop HTML server and Javascript compiler. It can run client-side web pages (HTML, Javascript, CSS) almost identically to a browser, but because it is local it has extensions that allow access to machine resources. Electron is very sophisticated and the resulting apps can be single-click published for multiple platforms, and have a look and feel that is modern and native.
Electron has gained popularity as a simple and standard way of writing GUI-based cross-platform applications. Because code written is essentially identical to web code it is easy to move apps between native and web, and the technology used is common reducing what needs to be learnt.
This project uses the FABLE F# to JS transpiler, so that 95% of code can be written type-safe in F#. The development environment uses Node technology to watch for changed files and then automatically hot-reload the running application. This is invaluable especially for GUI tuning where it is important to see instantly what the effect of some code change is.
The technology to manage hot-reloading consists of:
- electron-reload - makes the electron app hot reload
- electron-fs.watch - monitors host files and runs code when they change
- fable-compiler - transpiles F# to Javascript and itself monitors changed F# source files and recompiles to Javascript.
- electron-packager - generates the application as a directory containing all necessary files and an electron executable for a given platform
All this technology is available packaged in Node, and works cross-platform, so this is a development environment that will work on any platform and cross-compile to any platform.
The amount of boilerplate needed to make all this work is relatively small, and documented in comments and separate pages on this wiki.
HTML is the web HyperText Markup Language which describes in text form a GUI as a tree of components: windows, controls, etc. HTML is read by browsers and converted to a graphical representation in memory of the DOM which can then be directly manipulated by Javascript code. HTML is typically used for the static elements of a web page or in this case, using electron, a native application.
CSS (Cascading Style Sheets) is the language used to style DOM elements, for example to set sizes, colors, fonts.
This project uses some HTML for GUI construction. Much of the GUI is created dynamically by F# functions and this generally is the preferred method since it allows functional abstraction. However CSS, to style GUI elements, is used and preferred to F#. This makes a fairly clean split between styling (in CSS) and functionality (in F# / HTML). CSS is used with the powerful CSS custom variables. Best practice writing CSS is that a given styling parameter (color, size, etc) is written just once in a CSS file as a value assigned to a variable, which can then be used multiple times. This also makes the F# interface to CSS clean - style changes can be implemented as single variable updates, and separated from knowledge of where they are used.
Since F# can dynamically change the value of these variables, and CSS can itself contain arbitrary arithmetic expressions that include variables, this allows dynamic styling - for example setting the width of a panel based on arbitrary conditions. F# is also used extensively to set and change the CSS classes attached to DOM (document object model, AKA GUI) elements. Thus the F# interaction with the GUI consists of:
- Create/change DOM elements
- Change values of CSS variables
- Add CSS classes to DOM elements
Although it is possible for F# code to manipulate DOM element styles directly this is bad practice. The intent is that as much as possible of the GUI style tweaking and documentation is done in CSS.
Neither HTML nor CSS has great syntax, and a number of non-standard preprocessors have been developed that generate complex HTML or CSS from simpler template files. For this project preprocessors will not be used. CSS with custom variables is quite adequate, and for both CSS and HTML complex functionality can be written in F#. Still, the choice not to use a CSS preprocessor such as LESS is marginal and given a larger GUI this would maybe be worthwhile because it would help to maintain a split between styling and functionality. Adding LESS to the project technology chain would be easy - it is available as a node package.
Since all compilation and build is done automatically based on file changes an IDE is needed to provide intelligent editing with compiler error messages before building. Both Visual Studio and Visual Studio Code do an excellent job here, and both are now cross-platform. Visual Studio has slightly nicer syntax highlighting (because it is fully semantically aware) whereas Visual Studio Code is lighter weight and has some other nice features. Use whichever you prefer, and try both to see.
The Monaco programmer's editor component is one of the (many) Javascript programmer's editors. It is probably the most sophisticated with best feature set. Monaco is not that well documented, with self-generated API documentation from the code and not much else. However it comes with web-based interactive try-it example playground that can easily be modified so once you have got started it is pretty efficient. Also it is both stable and very well maintained. This project uses quite a bit of Monaco functionality and explains what it uses.