United Kingdom: +44 (0)208 088 8978

Publishing an F# React component

Akash continues his series on building React wrappers in F#, this time deploying the component to nuget!

In my last post we were able to wrap react-d3-speedometer using Feliz. The next step will be deploying this wrapper to Nuget for all to enjoy!

Setup

  • SAFE template - 3.0.0-beta004
  1. Create a folder in the root directory called fable.

  2. In the fable folder add a New Project which will be a console app that we'll call Feliz.ReactSpeedometer. Ensure when going through the wizard you create the console app in the right directory. We can remove the Program.fs that gets created.

  3. Once created right click on Feliz.ReactSpeedometer.fsproj to access Properties. Select the Package tab and complete the relevant fields:

    • Ticking Generate Nuget package on build
    • Changing the Author/Company (optional)
    • Adding Project Url (same as github repo url)
    • Adding a Repository Url

Package names must be unique when eventually publishing to nuget so check this is the case.
This step can also be done using code in the .fsproj but if it's your first time I'd recommend getting familiar with the terms

  1. Move our component Feliz.ReactSpeedometer.fs that is currently in the Client project to the Feliz.ReactSpeedometer project we just created.

Feliz.ReactSpeedometer.fsproj should look something like:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net5.0</TargetFramework>
    <GeneratePackageOnBuild>true</GeneratePackageOnBuild>
    <Version>0.0.1</Version>
    <Authors>Compositional IT</Authors>
    <Company>Compositional IT</Company>
    <PackageProjectUrl>https://github.com/XXX</PackageProjectUrl>
    <RepositoryUrl>https://github.com/XXX</RepositoryUrl>
  </PropertyGroup>

  <ItemGroup>
    <Compile Include="Feliz.ReactSpeedometer.fs" />
  </ItemGroup>

  <ItemGroup />

</Project>
  1. After that we'll need to create a paket.references so that we can get access to Fable.Core and Feliz:
Fable.Core
Feliz
  1. Ensure paket.reference is in the Feliz.ReactSpeedometer.fsproj. It should look something like:
...
<ItemGroup>
    <None Include="paket.references" />
    <Compile Include="Feliz.ReactSpeedometer.fs" />
</ItemGroup>
...
  1. With that we need to reference the Paket restore in the Feliz.ReactSpeedometer.fsproj which is the same level as an <ItemGroup>, an example of this can be found in both the Client.fsproj and the Server.fsproj:
...
</ItemGroup>
<Import Project="..\..\.paket\Paket.Restore.targets" />
...
  1. Next thing to include in the Feliz.ReactSpeedometer.fsproj, which comes from the Fable docs on authoring a library, is:
<ItemGroup>
    <Content Include="*.fsproj; **\*.fs; **\*.fsi" PackagePath="fable\" />
</ItemGroup>

The last thing for the Feliz.ReactSpeedometer.fsproj setup is to use Femto so that npm dependancies are automatically resolved for anyone using our Nuget package.

  1. Add the following to the Feliz.ReactSpeedometer.fsproj:
<PropertyGroup>
  <NpmDependencies>
      <NpmPackage Name="react-d3-speedometer" Version="gte 1.0.1 lt 2.0.0" ResolutionStrategy="Max" />
  </NpmDependencies>
</PropertyGroup>

Now we've got the setup out the way. We'll use github actions so that whenever we push the main branch it'll trigger a deploy to Nuget!

  1. Create the file path .github/workflows/publish.yml and add:
name: Nuget-Publish

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  build:

    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v2
    - name: Setup .NET
      uses: actions/setup-dotnet@v1
      with:
        dotnet-version: 5.0.100
    - name: Restore tools
      run: dotnet tool restore
    - name: Restore dependencies
      run: dotnet restore
      working-directory: ./fable/Feliz.ReactSpeedometer
    - name: Build
      run: dotnet build --configuration Release --no-restore
      working-directory: ./fable/Feliz.ReactSpeedometer
    - name: Publish
      uses: brandedoutcast/publish-nuget@v2.5.2
      with:
       PROJECT_FILE_PATH: fable/Feliz.ReactSpeedometer/Feliz.ReactSpeedometer.fsproj
       NUGET_KEY: ${{secrets.NUGET_API_KEY}}
  1. Now we need to create an API key on Nuget.

  2. Add that key to our secrets on the github repo and call it NUGET_API_KEY.

The build will be triggered on every push to main, and you can also manually start a build on github.

🎉WE'VE DONE IT!!🎉
📦You can find the package here - https://www.nuget.org/packages/Feliz.ReactSpeedometer 📦

I hope you enjoyed this series on creating a React wrapper from start to end, I've learnt a tonne along the way and hope you have too 😁