Note our sample project is a library consisting of a single method to print key-value pairs in padded format (because padding is one of the most demanded features in npm packages).
It is recommended that a Fable package has a structure similar to the following.
Folder containing the F# source code and the
.fsproj file. The convention is the project file
has the same name as the npm package, even though the former uses Pascal case with periods between
the words (
Fable.Helpers.Sample.fsproj) while the latter uses snake case (
Used both to manage our dependencies and to publish our package to npm.
There're dependencies that will be used only during development (like
fable-extra) and others that will be necessary during runtime too (like
However, for Fable packages it's recommended to use only
devDevependencies and indicate in
the README the dependencies that must be downloaded by the consumer of the library. If several
packages specify different versions of
fable-core for example, npm may try to install them all,
creating conflicts during Fable runtime.
peerDependenciesare supposed to fix this problem as they require dependencies to be installed in the same level. However, the way they're handled by npm can be confusing and thus they're not recommended at the moment.
Note the version number in this file is
0.0.0. This is because the version will be automatically
updated by the build script.
Description of our project that will appear both in our public repository (like Github) and the npm web site.
This is optional, but it's recommended to easily track changes between different releases.
You can check the file in this sample project to see the format. Usually we will just include
the messages of the commits between versions. Furthermore, the build script can use this file
to automatically update the version number in
Simple node.js script to build the project, inspired by FAKE. Check the file contents to learn more, you can also know more details about the build process in the following section.
The build script does all the work of building the project, which in this case is just calling Fable
package). The script is inspired by FAKE and it can contain different
build targets that can be easily chained. The script contains multiple comments so please check it for
more details. A couple of important notes though:
fableconfig.jsonfile and just call
fable.compile()(with no options) instead.
dllflag, which is use to generate a .NET assembly with the only purpose to store the F# type metadata so it can be referenced by other projects.
The convention is that all Fable packages use ES2015 modules by default, because Fable takes advantage of this module system to reduce the app size when using bundlers like Rollup (embedded in Fable) or Webpack 2.
Please note that libraries shouldn't be bundled. Only final apps must be bundled.
However, some users may not want to bundle their apps but rather load each file separately in a node app
or with require.js in the browser. For these cases, the convention is to also include
the JS files compiled with the
umd module target and put them in a subdirectory also named
umd. If you
follow this convention, when the consumer of your library selects a UMD-compatible module target (commonjs, amd),
Fable will automatically detect if a
umd folder is present in your package in order to reference the JS files
within it instead of the default ones.
As you can see in the build script, compiling with
umd modules just involves creating a
in the fableconfig and then calling it after the first compilation.
This is automatically done in the
publish target of the build script, so you only need to type:
node build publish
This is equivalent to building the project and then running
npm publish in the build directory.
The machine must be authorized to publish npm packages, see npm documentation for details.
To use your library, a Fable developer only needs to download it from npm, together with others packages your library may rely on (say, fable-powerpack).
npm install --save fable-helpers-sample
Then the user must add a reference to the
.dll within the package from the F# code. For example,
in the case of an
#r "../node_modules/fable-helpers-sample/Fable.Helpers.Sample.dll"open Fable.Helpers.Sample
If it's an
.fsproj file, add the following:
Nothing else needs to be done. When compiling the app, Fable will automatically detect the
to a Fable package and (thanks to
.fablemap file) it will correctly replace the references to the types in
the assembly with references to the compiled JS files.