or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

index.mddocs/

Fable Loader

Fable Loader is a Webpack loader that enables seamless integration of F# code compilation through the Fable compiler into JavaScript build pipelines. It serves as a bridge between Webpack's module loading system and the Fable F#-to-JavaScript compiler, allowing developers to include F# source files (.fs, .fsx, .fsproj) in their Webpack builds.

Package Information

  • Package Name: fable-loader
  • Package Type: npm
  • Language: JavaScript
  • Installation: npm install fable-loader fable-compiler @babel/core

Core Imports

The loader is configured through Webpack configuration rather than direct imports:

// webpack.config.js
module.exports = {
  module: {
    rules: [{
      test: /\.fs(x|proj)?$/,
      use: "fable-loader"
    }]
  }
};

Basic Usage

Create a webpack.config.js file to configure the loader:

var path = require("path");

module.exports = {
  mode: "production",
  entry: "./src/App.fsproj",
  output: {
    path: path.join(__dirname, "./public"),
    filename: "bundle.js",
  },
  devServer: {
    contentBase: "./public",
    port: 8080,
  },
  module: {
    rules: [{
      test: /\.fs(x|proj)?$/,
      use: "fable-loader"
    }]
  }
};

With loader options:

module.exports = {
  module: {
    rules: [{
      test: /\.fs(x|proj)?$/,
      use: {
        loader: "fable-loader",
        options: {
          babel: {
            presets: ["@babel/preset-env"]
          },
          define: ["PRODUCTION"],
          typedArrays: true,
          clampByteArrays: false
        }
      }
    }]
  }
};

Architecture

Fable Loader operates as a standard Webpack loader with the following key components:

  • Loader Function: Main entry point that processes F# files using Webpack's loader API
  • Compiler Management: Caches and manages Fable compiler instances for performance
  • Babel Integration: Applies Babel transformations to compiled JavaScript output
  • Dependency Tracking: Automatically tracks F# file dependencies for Webpack
  • Error Handling: Propagates compilation errors and warnings through Webpack

Capabilities

Loader Function

The main loader function that processes F# files and returns compiled JavaScript.

/**
 * Main webpack loader function for processing F# files
 * @param {Buffer} buffer - File content as buffer (raw loader)
 * @returns {void} - Result passed via async callback
 */
function Loader(buffer) {
  // Implementation handles compilation and returns via this.async() callback
}

// Loader configuration
Loader.raw = true; // Indicates binary input handling

Configuration Options

Options passed through Webpack loader configuration:

interface LoaderOptions {
  /** Babel transformation options applied to compiled F# code */
  babel?: BabelOptions;
  
  /** Compilation constants passed to F# compiler */
  define?: string[];
  
  /** Translate numeric arrays as JS Typed Arrays (default: true) */
  typedArrays?: boolean;
  
  /** Translate byte arrays as Uint8ClampedArray (default: false) */
  clampByteArrays?: boolean;
  
  /** Additional options passed to compiler */
  extra?: Record<string, any>;
  
  /** CLI options for fable-compiler */
  cli?: CliOptions;
}

interface BabelOptions {
  /** Babel presets to apply */
  presets?: string[];
  
  /** Babel plugins to apply (merged with built-in plugins) */
  plugins?: any[];
  
  /** Source map configuration */
  sourceMaps?: boolean;
  
  /** Source file name for source maps */
  sourceFileName?: string;
}

interface CliOptions {
  /** Additional CLI arguments for fable-compiler */
  [key: string]: any;
}

Usage Examples:

// Basic configuration
{
  test: /\.fs(x|proj)?$/,
  use: "fable-loader"
}

// With options
{
  test: /\.fs(x|proj)?$/,
  use: {
    loader: "fable-loader",
    options: {
      babel: {
        presets: ["@babel/preset-env"],
        plugins: ["@babel/plugin-proposal-class-properties"]
      },
      define: ["DEBUG", "BROWSER"],
      typedArrays: true,
      clampByteArrays: false,
      extra: {
        optimizeFSharpAst: true
      }
    }
  }
}

File Support

Supported F# file extensions:

/** Supported file extensions pattern */
const SUPPORTED_EXTENSIONS = /\.fs(x|proj)?$/;

/** File types processed by the loader */
type SupportedFileTypes = 
  | ".fs"    // F# source files
  | ".fsx"   // F# script files  
  | ".fsproj" // F# project files

Compilation Process

The loader processes files through the following pipeline:

interface CompilationMessage {
  /** Source file path */
  path: string;
  
  /** Project root directory */
  rootDir: string;
  
  /** Compilation constants */
  define: string[];
  
  /** Enable typed arrays translation */
  typedArrays: boolean;
  
  /** Enable clamped byte arrays */
  clampByteArrays: boolean;
  
  /** Additional compilation options */
  extra: Record<string, any>;
}

interface CompilationResult {
  /** Compiled JavaScript AST or error message */
  error?: string;
  
  /** File dependencies for Webpack tracking */
  dependencies?: string[];
  
  /** Compilation logs by severity */
  logs?: {
    error?: string[];
    warning?: string[];
    info?: string[];
  };
  
  /** Source file name for source maps */
  fileName?: string;
}

Error Handling

The loader handles various error conditions:

/** Error types handled by the loader */
type LoaderError = 
  | "FABLE_SERVER_PORT_ERROR"  // Incompatible with dotnet-fable CLI
  | "COMPILATION_ERROR"        // F# compilation failed
  | "BABEL_TRANSFORM_ERROR"    // Babel transformation failed
  | "DEPENDENCY_ERROR"         // File dependency resolution failed

/** Error reporting through Webpack */
interface ErrorReporting {
  /** Emit compilation error */
  emitError(error: Error): void;
  
  /** Emit compilation warning */
  emitWarning(error: Error): void;
  
  /** Enable/disable caching based on error state */
  cacheable(cacheable: boolean): void;
}

Built-in Babel Plugins

The loader automatically applies Fable-specific Babel plugins:

/** Built-in Babel plugins for Fable transformations */
const CUSTOM_PLUGINS = [
  "fable-babel-plugins/getRemoveUnneededNulls",
  "fable-babel-plugins/getTransformMacroExpressions"
];

Dependencies

Runtime Dependencies

  • fable-babel-plugins: ~2.1.0 - Babel plugins for Fable transformations

Peer Dependencies

  • @babel/core: ^7.1.6 - Babel compiler core
  • fable-compiler: ~2.1.0 - F# to JavaScript compiler
  • webpack: >=4.23.0 - Module bundler

Development Environment

The loader automatically detects development mode and adds the "DEBUG" compilation constant when webpack.mode === "development".

Source Map Support

Source maps are generated when enabled in Webpack configuration:

// Enable source maps in webpack config
module.exports = {
  devtool: 'source-map', // or other source map options
  // ... other config
};

The loader handles source map generation by:

  • Setting sourceMaps: true in Babel options when enabled
  • Normalizing file paths for cross-platform compatibility
  • Passing original F# source content to Babel for accurate mappings

Webpack Integration

The loader integrates with Webpack through:

  • Dependency Tracking: Automatically calls this.addDependency() for F# file dependencies
  • Watch Mode Detection: Manages compiler lifecycle based on Webpack watch mode
  • Error/Warning Emission: Uses Webpack's error reporting system
  • Caching: Enables Webpack caching for successful compilations
  • Hook Integration: Registers cleanup hooks for compiler shutdown