Skip to content

Source Maps in opal-vite

Source maps allow you to debug your Ruby code directly in browser DevTools, even though it's compiled to JavaScript.

⚠️ Experimental Feature: Source maps are currently experimental. There are known compatibility issues with Vite's source map chain processing when compiling files with multiple require statements. Single-file compilation works, but complex applications may encounter errors.

Overview

When source maps are enabled, opal-vite generates Source Map v3 compatible mappings that:

  1. Map JavaScript back to Ruby - Click on errors in DevTools to see the original Ruby line
  2. Include original source - The Ruby source code is embedded in the source map
  3. Support browser debugging - Set breakpoints in your Ruby files

Configuration

Vite Plugin Options

typescript
import { defineConfig } from 'vite'
import opal from 'vite-plugin-opal'

export default defineConfig({
  plugins: [
    opal({
      sourceMap: true  // Enabled by default
    })
  ],
  build: {
    sourcemap: true  // Also enable for production builds
  }
})

Ruby Configuration

ruby
# Configure via Opal::Vite
Opal::Vite.configure do |config|
  config.source_map_enabled = true  # Enabled by default
end

How It Works

  1. Compilation: When Opal compiles Ruby to JavaScript, it generates source map data
  2. Index Format: Multiple files are combined into an index source map with sections
  3. Vite Integration: The source map is passed to Vite which handles the browser delivery
  4. Browser Display: DevTools shows Ruby files in the Sources panel

Debugging in Browser

  1. Open DevTools (F12)
  2. Go to the Sources tab
  3. Find your Ruby files under the source tree
  4. Set breakpoints by clicking line numbers
  5. Variable values are shown (though with JavaScript names)

Source Map Structure

The generated source maps follow the v3 specification:

json
{
  "version": 3,
  "sections": [
    {
      "offset": { "line": 0, "column": 0 },
      "map": {
        "version": 3,
        "sources": ["app/opal/controllers/my_controller.rb"],
        "sourcesContent": ["# Original Ruby code..."],
        "names": ["method_name", "variable"],
        "mappings": "AAAA..."
      }
    }
  ]
}

Disabling Source Maps

For production builds where you don't want source maps:

typescript
// vite.config.ts
export default defineConfig({
  plugins: [
    opal({
      sourceMap: false
    })
  ],
  build: {
    sourcemap: false
  }
})

Known Limitations

Vite Source Map Chain Compatibility

When a Ruby file uses multiple require statements, Opal generates an "index source map" with multiple sections (one per file). Vite's internal _getCombinedSourcemap function has compatibility issues with this format.

Workaround: For complex applications, keep sourceMap: false until this is resolved. Single-file Ruby scripts should work fine with source maps enabled.

Multiple File Debugging

Currently, only the main entry point file appears in browser DevTools. Required files (controllers, services, etc.) may not be visible for debugging.

Troubleshooting

Source maps not appearing in DevTools

  1. Ensure sourceMap: true in plugin options
  2. Check Vite's build.sourcemap setting
  3. Verify DevTools has "Enable JavaScript source maps" checked

"Cannot read properties of undefined" error

This error occurs when Vite's source map chain processing fails. Disable source maps:

typescript
opal({
  sourceMap: false
})

Incorrect line mappings

Opal's source maps map at the expression level, not character-by-character. Some complex Ruby expressions may map to approximate JavaScript locations.

Large source map files

Source maps include original source content. For production, consider:

  • Setting build.sourcemap: 'hidden' to generate but not reference
  • Using source maps only in development

Performance

Source map generation adds minimal overhead to compilation (~5-10%). The maps are only generated once per file and cached by Vite.

Released under the MIT License.