CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-fable-loader

Webpack loader for Fable compiler that enables F# code compilation into JavaScript build pipelines

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

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

docs

index.md

tile.json