Fable: fable-splitter only uses last file in project

Created on 26 Sep 2017  路  16Comments  路  Source: fable-compiler/Fable

Description

I'm trying to create multiple js files from a fsproj using fable-splitter.
My fsproj:

Repro code

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>netstandard2.0</TargetFramework>
  </PropertyGroup>
  <ItemGroup>
    <Compile Include="App.fs" />    
    <Compile Include="Helper.fs" />
  </ItemGroup>
  <Import Project="..\.paket\Paket.Restore.targets" />
</Project>

App.fs

module FableSplit

open Fable.Core
open Fable.Core.JsInterop
open Fable.Import

let init() =
    let canvas = Browser.document.getElementsByTagName_canvas().[0]
    canvas.width <- 1000.
    canvas.height <- 800.
    let ctx = canvas.getContext_2d()
    // The (!^) operator checks and casts a value to an Erased Union type
    // See http://fable.io/docs/interacting.html#Erase-attribute
    ctx.fillStyle <- !^"rgb(200,0,0)"
    ctx.fillRect (10., 10., 55., 50.)
    ctx.fillStyle <- !^"rgba(0, 0, 200, 0.5)"
    ctx.fillRect (30., 30., 55., 50.)

init()

Helper.fs

module Helper

open Fable.Import.Browser

let private toList (nodeList:NodeListOf<Element>) =
    let length = nodeList.length - 1.0
    [0.0 .. length]
    |> List.map (fun i -> nodeList.item i  :?> HTMLElement)

let dollar selector (element:HTMLElement) =
    element.querySelectorAll selector
    |> toList

splitter.config.js

const path = require("path");
const fableUtils = require("fable-utils");

function resolve(relativePath) {
    return path.join(__dirname, relativePath);
}

module.exports = {
  entry: resolve("src/FableSplit.fsproj"),
  outDir: resolve("splitted"),
  babel: fableUtils.resolveBabelOptions({
    presets: [["es2015", { modules: false }]],
    sourceMaps: true,
  }),
  fable: {
    define: ["DEBUG"]
  }
}

Expected and actual results

Expected

Two files (App.js and Helper.js) inside the splitted folder.

Actual

Only the last item in the fsproj is being compiled.

Related information

  • Fable version (dotnet fable --version): 1.2.3
  • Operating system: Windows 7

Most helpful comment

Ah, ok. Nobody uses that module so the error only surfaces if you use the allFiles option :wink: I released Fable.PowerPack 1.3.3, should fix that.

All 16 comments

In general Fable clients (Webpack loader, Rollup plugin, fable-splitter) start compiling the last file in the project and only request other files if they're being referenced. This is consistent with how JS projects work where there's an _entry file_ that acts as the public interface for the project/package.

However, I also want to add the option to fable-splitter to compile all files in the project (or at least all in the base directory) for special cases (like tests projects). Until this is ready there's a little hack to make sure all projects will get compiled which is using an empty import (actually named importSideEffects). Please see how it's done in Fable unit tests.

I've published fable-splitter 0.1.19 which accepts the following config to force compilation of all project files even if they're not referenced, could you please give it a try? (You also need to upload Fable to 1.2.4)

module.exports = {
  ...
  fable: {
    ...
    extra: { allFiles: true }
  }
};

Thanks Alfonso, it worked!

I did kinda wish paket update also did the dotnet restore of my project. A bit confusing as I updated all dependencies and it was still loading stuff from 1.2.3. Only after the dotnet restore I got the multiple files.

As a last remark for anyone trying to do the same the extra configuration is not underneath fable.
For ex.

const path = require("path");
const fableUtils = require("fable-utils");

function resolve(relativePath) {
    return path.join(__dirname, relativePath);
}

module.exports = {
  entry: resolve("src/FableSplit.fsproj"),
  outDir: resolve("splitted"),
  babel: fableUtils.resolveBabelOptions({
    presets: [["es2015", { modules: false }]],
    sourceMaps: true,
  }),
  fable: {
    define: ["DEBUG"]
  },
  extra: { allFiles: true }
}

Ups, thanks for pointing that out @nojaf! Actually that's my mistake I think it should go into fable because extra can also be used to pass some values to Fable daemon. I'll fix that!

Sorry for so many changes but I realized allFiles is an exclusive option of fable-splitter so I moved it to the options root as other splitter-only options like entry or outDir. Now with fable-splitter 0.1.20 you do:

module.exports = {
  entry: ...,
  outDir: ...,
  babel: ...,
  fable: ...,
  allFiles: true
}

Tested the 0.1.20, works. Thanks!

I was attempting to do the same as this issue but i'm only getting one file out.

my splitter config

const path = require("path");
const fableUtils = require("fable-utils");

function resolve(relativePath) {
    return path.join(__dirname, relativePath);
}

module.exports = {
    entry: resolve("src/FableTestSplitter.fsproj"),
    outDir: resolve("out"),
    fable: {
        define: ["DEBUG"]
    },
    babel: fableUtils.resolveBabelOptions({
        presets: [
            ["es2015", {
                modules: false
            }]
        ],
        sourceMaps: true,
    }),
    allFiles: true
}
$ dotnet fable --version
1.3.2
$ dotnet --info
.NET Command Line Tools (2.1.3)

Product Information:
 Version:            2.1.3
 Commit SHA-1 hash:  a0ca411ca5

Runtime Environment:
 OS Name:     Mac OS X
 OS Version:  10.12
 OS Platform: Darwin
 RID:         osx.10.12-x64
 Base Path:   /usr/local/share/dotnet/sdk/2.1.3/

Microsoft .NET Core Shared Framework Host

  Version  : 2.0.4
  Build    : 7f262f453d8c8479b9af91d34c013b3aa05bc1ff
$ yarn --version
1.3.2

Am I overlooking something obvious?

@TheAngryByrd Latest Fable is 1.3.7 AFAIK but you seem to have 1.3.2 maybe update to latest?

@Zaid-Ajaj just did a paket update cleared bin and obj and then dotnet restore and still same results

You're right, it's not working :confused: Latest Fable is not returning the list of files for the .fsproj. I must have broken something, sorry! 馃槄 I'll check...

Hmm, apparently I removed that to fix #1241. Let's see if we can find a solution that solves both problems...

This should be fixed now, please update Fable to 1.3.8 and fable-splitter to 0.1.21 and tell me if you have any problem 馃憤

I've tested this and it worked. I do think that the Fable.Elmish.React and Fable.PowerPack are not yet compatible with the latest Fable.

@nojaf Thanks for checking! I think Fable.Elmish.React stable has to update the dependency to Fable.React 2. What problem do you have for Fable.PowerPack?

Awesome!

@alfonsogarciacaro

Powerpack error I'm getting from the same project above (without using a Main.fs file)

/Users/username/.nuget/packages/fable.powerpack/1.3.2/fable/src/IndexedDB.fs(71,37): (71,41) error FSHARP: The type '(Browser.Event -> 'a)' does not have 'null' as a proper value
fable: Compilation failed at 9:18:42 AM (22.265 s)

Ah, ok. Nobody uses that module so the error only surfaces if you use the allFiles option :wink: I released Fable.PowerPack 1.3.3, should fix that.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

alfonsogarciacaro picture alfonsogarciacaro  路  3Comments

MangelMaxime picture MangelMaxime  路  3Comments

krauthaufen picture krauthaufen  路  3Comments

nozzlegear picture nozzlegear  路  3Comments

jwosty picture jwosty  路  3Comments