Skip to main content

Shakapacker Configuration Guide

This guide covers all configuration options available in config/shakapacker.yml and how to use them effectively.

Table of Contents

Quick Reference

Common configuration options with their defaults:

OptionTypeDefaultDescription
assets_bundlerstring"webpack"Bundler to use: "webpack" or "rspack"
assets_bundler_config_pathstring"config/webpack" or "config/rspack"Directory containing bundler config files
javascript_transpilerstring"swc"*Transpiler: "swc", "babel", or "esbuild"
source_pathstring"app/javascript"Root directory for JavaScript source files
source_entry_pathstring"packs"Subdirectory within source_path for entry points
nested_entriesbooleantrueDiscover entry points in subdirectories
public_output_pathstring"packs"Subdirectory within public_root_path for compiled assets
private_output_pathstringnilDirectory for private server-side bundles (e.g., SSR)
compilebooleanenv-specificCompile assets on-demand when requests are made
cache_manifestbooleanfalse (dev), true (prod)Cache manifest.json in memory
compiler_strategystring"mtime" (dev), "digest" (prod)How to determine if recompilation is needed
useContentHashbooleanfalse (dev), true (prod)Include content hashes in asset filenames
webpack_compile_outputbooleantrueShow webpack/rspack compilation output
shakapacker_precompilebooleantrueInclude in bundle exec rake assets:precompile
ensure_consistent_versioningbooleantrueEnforce gem/npm version matching
dev_server.hoststring"localhost"Development server host
dev_server.portnumber3035Development server port
dev_server.hmrbooleanfalseEnable Hot Module Replacement

For detailed explanations, examples, and additional options, see the sections below.

*Note on javascript_transpiler default: The installation template sets this to "swc" for new projects. However, at runtime, if no explicit value is configured, webpack defaults to "babel" (for backward compatibility) while rspack defaults to "swc".

Basic Configuration

assets_bundler

Type: string Default: "webpack" Options: "webpack" or "rspack"

Specifies which bundler to use for compiling assets.

# Use webpack (default)
assets_bundler: "webpack"

# Use rspack for faster builds
assets_bundler: "rspack"

See RSpack Migration Guide for details on switching bundlers.

assets_bundler_config_path

Type: string Default: "config/webpack" for webpack, "config/rspack" for rspack

Specifies the directory containing your webpack/rspack config files.

# Use default paths (config/webpack or config/rspack)
# assets_bundler_config_path: config/webpack

# Use custom directory
assets_bundler_config_path: "build_configs"

# Use project root directory
assets_bundler_config_path: "."

When to use:

  • When migrating from another build tool and want to preserve existing config locations
  • When organizing configs in a monorepo structure
  • When following custom project conventions

javascript_transpiler

Type: string Default: "swc" (new installations), "babel" (webpack runtime), "swc" (rspack runtime) Options: "swc", "babel", or "esbuild"

Specifies which transpiler to use for JavaScript/TypeScript.

# Use SWC (recommended - 20x faster than Babel, set by default in new installations)
javascript_transpiler: "swc"

# Use Babel (for maximum compatibility, webpack runtime default if not configured)
javascript_transpiler: "babel"

# Use esbuild (fastest, but may have compatibility issues)
javascript_transpiler: "esbuild"

Important default behavior:

  • New installations: The installation template explicitly sets javascript_transpiler: "swc"
  • Webpack runtime default: If not explicitly configured, defaults to "babel" for backward compatibility
  • Rspack runtime default: If not explicitly configured, defaults to "swc" as rspack is a newer bundler

See Transpiler Performance Guide for benchmarks and migration guides.

Source Configuration

source_path

Type: string Default: "app/javascript"

The root directory for your JavaScript source files.

# Default
source_path: app/javascript

# Custom location
source_path: app/frontend

source_entry_path

Type: string Default: "packs"

Subdirectory within source_path containing entry points.

# Recommended: use a subdirectory
source_entry_path: packs

# Use the entire source_path as entry directory
source_entry_path: /

Note: Cannot use / when nested_entries is true.

nested_entries

Type: boolean Default: true

Whether to automatically discover entry points in subdirectories within source_entry_path.

# Enable nested entries (recommended)
nested_entries: true

# Disable - only top-level files are entries
nested_entries: false

Example with nested entries:

app/javascript/packs/
application.js # Entry: application
admin/
dashboard.js # Entry: admin/dashboard

additional_paths

Type: array Default: []

Additional directories for webpack/rspack to search for modules.

additional_paths:
- app/assets
- vendor/assets
- node_modules/legacy-lib

Use cases:

  • Resolving modules from Rails asset directories
  • Including vendored JavaScript
  • Sharing code between engines

Output Configuration

public_root_path

Type: string Default: "public"

The public directory where assets are served from.

public_root_path: public

public_output_path

Type: string Default: "packs"

Subdirectory within public_root_path for compiled assets.

# Default - outputs to public/packs
public_output_path: packs

# Custom output directory
public_output_path: webpack-bundles

private_output_path

Type: string Default: nil

Directory for private server-side bundles (e.g., for SSR) that should not be publicly accessible.

# Enable private output for SSR bundles
private_output_path: ssr-generated

Important: Must be different from public_output_path to prevent serving private bundles.

manifest_path

Type: string Default: "{public_output_path}/manifest.json"

Location of the manifest.json file that maps entry points to compiled assets.

# Custom manifest location
manifest_path: public/assets/webpack-manifest.json

Note: Rarely needs to be changed from the default.

cache_path

Type: string Default: "tmp/shakapacker"

Directory for webpack/rspack cache files.

cache_path: tmp/shakapacker

# Use a shared cache in CI
cache_path: /mnt/shared/webpack-cache

Bundler Configuration

webpack_compile_output

Type: boolean Default: true

Whether to show webpack/rspack compilation output in the console.

# Show detailed output (helpful for debugging)
webpack_compile_output: true

# Minimal output (cleaner logs)
webpack_compile_output: false

useContentHash

Type: boolean Default: false (development), true (production - enforced)

Whether to include content hashes in asset filenames for cache busting.

# Production only (default)
useContentHash: false

# Always use content hash (not recommended for development)
useContentHash: true

Note: In production, this is always true regardless of configuration.

css_extract_ignore_order_warnings

Type: boolean Default: false

Whether to suppress mini-css-extract-plugin order warnings.

# Enable if you have consistent CSS scoping
css_extract_ignore_order_warnings: true

When to enable:

  • When using CSS modules or scoped styles
  • When following BEM or similar naming conventions
  • When order warnings are false positives

Development Server

dev_server

Configuration for bin/shakapacker-dev-server. See Dev Server Options below.

Dev Server Options

dev_server:
# Host to bind to
host: localhost

# Port to listen on
port: 3035

# Enable HTTPS
# server: https

# Hot Module Replacement
hmr: false

# Live reload (alternative to HMR)
# live_reload: true

# Inline CSS with HMR (requires style-loader)
inline_css: true

# Compression
compress: true

# Allowed hosts (security)
allowed_hosts: "auto"

# Client configuration
client:
# Show error overlay
overlay: true

# Custom WebSocket URL
# webSocketURL:
# hostname: '0.0.0.0'
# pathname: '/ws'
# port: 8080

# Custom headers for dev server responses
# Uncomment to enable CORS (e.g., when webpack-dev-server runs on a different
# port than your Rails server and the browser blocks cross-origin asset requests):
# headers:
# "Access-Control-Allow-Origin": "*"

# Static file serving
static:
watch:
ignored: "**/node_modules/**"

Key Options:

  • hmr: Hot Module Replacement updates modules without full reload. Requires additional setup.
  • inline_css: With HMR, CSS is delivered via JavaScript. Set to false to use <link> tags.
  • overlay: Shows errors/warnings in browser overlay. Helpful for development.
  • allowed_hosts: Protects against DNS rebinding attacks. Use "all" to disable (not recommended).

Compilation Options

compile

Type: boolean Environment-specific

Whether to compile assets on-demand when requests are made.

development:
compile: true # Compile on demand

production:
compile: false # Assets must be precompiled

shakapacker_precompile

Type: boolean Default: true

Whether bundle exec rake assets:precompile should compile webpack/rspack assets.

# Include in assets:precompile (recommended)
shakapacker_precompile: true

# Skip webpack compilation during assets:precompile
shakapacker_precompile: false

Override via environment variable:

SHAKAPACKER_PRECOMPILE=false bundle exec rake assets:precompile

cache_manifest

Type: boolean Default: false (development), true (production)

Whether to cache manifest.json in memory.

development:
cache_manifest: false # Reload on every request

production:
cache_manifest: true # Cache for performance

compiler_strategy

Type: string Default: "mtime" (development), "digest" (production) Options: "mtime" or "digest"

How to determine if assets need recompilation.

development:
# Fast: check file modification times
compiler_strategy: mtime

production:
# Accurate: check content hashes
compiler_strategy: digest

mtime: Faster but may miss changes if timestamps are unreliable. digest: Slower but guarantees accuracy by comparing content hashes.

Advanced Options

precompile_hook

Type: string Default: nil

Command to run before webpack/rspack compilation. Useful for generating dynamic entry points.

precompile_hook: "bin/shakapacker-precompile-hook"

Security: Only reference trusted scripts within your project. The path is validated.

See Precompile Hook Guide for examples and use cases.

ensure_consistent_versioning

Type: boolean Default: true

Raises an error if shakapacker gem and npm package versions don't match.

# Enforce version matching (recommended)
ensure_consistent_versioning: true

# Allow version mismatches (not recommended)
ensure_consistent_versioning: false

asset_host

Type: string Default: nil (uses Rails asset host)

Override Rails asset host for webpack assets specifically.

# Use custom CDN for webpack assets
asset_host: https://cdn.example.com

Environment variable override:

SHAKAPACKER_ASSET_HOST=https://cdn.example.com

See CDN Setup Guide for complete configuration.

integrity

Type: object Default: { enabled: false }

Enable Subresource Integrity (SRI) for security.

integrity:
enabled: true
hash_functions: ["sha384"] # or ["sha256"], ["sha512"]
cross_origin: "anonymous" # or "use-credentials"

See Subresource Integrity Guide for details.

early_hints

Type: object Default: { enabled: false, css: "preload", js: "preload" } Requires: Rails 5.2+, HTTP/2 server

Automatically send HTTP 103 Early Hints for faster asset loading.

early_hints:
enabled: true # Master switch (default: false)
css: "preload" # 'preload' | 'prefetch' | 'none' (default: 'preload')
js: "preload" # 'preload' | 'prefetch' | 'none' (default: 'preload')

Options:

  • enabled: Enable/disable early hints (default: false)
  • css: Hint type for CSS - 'preload', 'prefetch', or 'none' (default: 'preload')
  • js: Hint type for JS - 'preload', 'prefetch', or 'none' (default: 'preload')

⚠️ Performance note: May improve or hurt page load depending on content. Configure per-page for best results.

See the Early Hints Guide for:

  • Performance considerations and warnings
  • Per-page configuration (configure_pack_early_hints)
  • Dynamic configuration examples
  • Hero image preloading with preload_link_tag
  • Troubleshooting and testing recommendations

Environment-Specific Configuration

Shakapacker supports per-environment configuration with fallback logic:

  1. Checks for environment-specific config (e.g., development, staging)
  2. Falls back to production if not found
  3. Uses bundled defaults if neither exists
# Shared defaults
default: &default
source_path: app/javascript
assets_bundler: "webpack"

# Development
development:
<<: *default
compile: true
compiler_strategy: mtime
dev_server:
hmr: true

# Test
test:
<<: *default
compile: true
public_output_path: packs-test

# Production
production:
<<: *default
compile: false
cache_manifest: true
compiler_strategy: digest
useContentHash: true # Enforced regardless

Custom Environments

For custom environments (e.g., staging), define a section or let it fall back to production:

# Option 1: Explicit staging config
staging:
<<: *default
compile: false
# staging-specific options

# Option 2: Let staging fall back to production
# (no staging section needed)

Configuration Validation

Shakapacker validates configuration at runtime and provides helpful error messages:

  • Missing config files: Suggests creating config or checking assets_bundler_config_path
  • Transpiler mismatch: Warns if package.json dependencies don't match configured transpiler
  • Path conflicts: Prevents private_output_path from being the same as public_output_path
  • Version mismatches: Detects gem/npm version differences when ensure_consistent_versioning is enabled

Environment Variables

Some options can be overridden via environment variables:

VariableDescriptionExample
SHAKAPACKER_CONFIGPath to shakapacker.ymlconfig/webpack.yml
SHAKAPACKER_ASSETS_BUNDLEROverride assets bundlerrspack
SHAKAPACKER_PRECOMPILEOverride precompile flagfalse
SHAKAPACKER_ASSET_HOSTOverride asset hosthttps://cdn.example.com
SHAKAPACKER_PUBLIC_*Auto-exposed to client-side JS (prefix convention)SHAKAPACKER_PUBLIC_API_URL
SHAKAPACKER_ENV_VARSAdditional env vars to expose to client-side JSAPI_URL,FEATURE_FLAGS
NODE_ENVNode environmentproduction
RAILS_ENVRails environmentstaging

Exposing Environment Variables to Client-Side JavaScript

By default, only NODE_ENV, RAILS_ENV, and WEBPACK_SERVE are exposed to client-side JavaScript via webpack/rspack's EnvironmentPlugin. This is a security measure to prevent accidentally leaking secrets like DATABASE_URL, API_SECRET_KEY, etc. into your JavaScript bundles.

Any environment variable prefixed with SHAKAPACKER_PUBLIC_ is automatically exposed to client-side code. This follows the same convention used by Next.js (NEXT_PUBLIC_*) and Vite (VITE_*):

# These are automatically available in your JavaScript
export SHAKAPACKER_PUBLIC_API_URL=https://api.example.com
export SHAKAPACKER_PUBLIC_ANALYTICS_ID=UA-12345
export SHAKAPACKER_PUBLIC_FEATURE_FLAGS=dark_mode,beta_ui
// Access in your JavaScript code
console.log(process.env.SHAKAPACKER_PUBLIC_API_URL)
console.log(process.env.SHAKAPACKER_PUBLIC_ANALYTICS_ID)

The prefix makes it explicit which variables are intended for client-side use, preventing accidental exposure of secrets.

SHAKAPACKER_ENV_VARS (Legacy/Escape Hatch)

For variables without the SHAKAPACKER_PUBLIC_ prefix, you can use SHAKAPACKER_ENV_VARS to expose them:

# Expose additional variables during build
SHAKAPACKER_ENV_VARS=API_BASE_URL,FEATURE_FLAGS bundle exec rake assets:precompile

# In development
SHAKAPACKER_ENV_VARS=API_BASE_URL bin/shakapacker-dev-server
// These are available after adding to SHAKAPACKER_ENV_VARS
console.log(process.env.API_BASE_URL)
console.log(process.env.FEATURE_FLAGS)

Best Practices

  1. Use default paths unless you have a specific reason to change them
  2. Enable SWC transpiler for faster builds (20x faster than Babel)
  3. Use rspack for even faster builds if compatible with your setup
  4. Cache manifest in production for better performance
  5. Enable integrity hashes in production for security
  6. Keep development and production configs aligned except for optimization settings
  7. Use content hashes in production for proper cache busting
  8. Validate after changes by running bin/shakapacker to ensure compilation works

Common Configuration Patterns

Fast Development Setup

development:
assets_bundler: "rspack"
javascript_transpiler: "swc"
compiler_strategy: mtime
webpack_compile_output: true
dev_server:
hmr: true
inline_css: true

Production-Optimized

production:
assets_bundler: "rspack"
javascript_transpiler: "swc"
compiler_strategy: digest
cache_manifest: true
useContentHash: true
integrity:
enabled: true

Monorepo Setup

default: &default
source_path: packages/frontend/src
assets_bundler_config_path: build_configs/webpack
additional_paths:
- packages/shared
- packages/ui-components

Build Configurations (config/shakapacker-builds.yml)

Shakapacker supports defining reusable build configurations in config/shakapacker-builds.yml. This allows you to run predefined builds with a simple command, making it easy to switch between different build scenarios.

Creating a Build Configuration File

Generate config/shakapacker-builds.yml with example builds:

bin/shakapacker --init  # Creates config/shakapacker-builds.yml

This generates a file with example builds for common scenarios (HMR development, standard development, and production).

Running Builds by Name

Once you have config/shakapacker-builds.yml, you can run builds by name:

# List available builds
bin/shakapacker --list-builds

# Run a specific build
bin/shakapacker --build dev-hmr # Client bundle with HMR (automatically uses dev server)
bin/shakapacker --build prod # Client and server bundles for production
bin/shakapacker --build dev # Client bundle for development

Build Configuration Format

Example config/shakapacker-builds.yml:

builds:
dev-hmr:
description: Client bundle with HMR (React Fast Refresh)
bundler: rspack # Optional: override assets_bundler from config/shakapacker.yml
environment:
NODE_ENV: development
RAILS_ENV: development
WEBPACK_SERVE: "true" # Automatically uses bin/shakapacker-dev-server
outputs:
- client
config: config/${BUNDLER}/custom.config.js # Optional: custom config file with variable substitution

prod:
description: Production client and server bundles
environment:
NODE_ENV: production
RAILS_ENV: production
outputs:
- client # Multiple outputs - builds both client and server bundles
- server

Build Configuration Options

  • description (optional): Human-readable description of the build
  • bundler (optional): Override the default bundler from config/shakapacker.yml (webpack or rspack)
  • dev_server (optional): Boolean flag to force routing to dev server (overrides environment variable detection)
  • environment: Environment variables to set when running the build
  • outputs: Array of output types - can include client, server, or both for multiple bundles in a single build
  • config (optional): Custom config file path (supports ${BUNDLER} variable substitution)
  • bundler_env (optional): Key-value pairs passed as bundler --env flags (e.g., { analyze: true } becomes --env analyze=true)

Automatic Dev Server Detection

Shakapacker automatically uses bin/shakapacker-dev-server instead of the regular build command when:

  1. The build has dev_server: true explicitly set (preferred method - takes precedence over environment variables), OR
  2. The build has WEBPACK_SERVE=true or HMR=true in its environment variables (fallback for backward compatibility)

Example:

# These are equivalent:
bin/shakapacker --build dev-hmr
WEBPACK_SERVE=true bin/shakapacker-dev-server # (with dev-hmr environment vars)

Variable Substitution

The config field supports ${BUNDLER} substitution:

builds:
custom:
bundler: rspack
config: config/${BUNDLER}/custom.config.js # Becomes: config/rspack/custom.config.js

When to Use Build Configurations

Build configurations are useful for:

  • Multiple build scenarios: Use when you need different builds for HMR development, standard development, and production
  • CI/CD pipelines: Use when you want predefined builds that can be referenced in deployment scripts
  • Team consistency: Use to ensure all developers use the same build configurations
  • Complex setups: Use to manage different bundler configs or environment variables for different scenarios

Troubleshooting

If you encounter configuration issues:

  1. Check error messages - they often suggest the fix
  2. Validate YAML syntax - use a YAML validator to ensure proper formatting
  3. Review fallback behavior - missing environment configs fall back to production
  4. Check environment variables - they override config file settings
  5. Inspect manifest.json - verify assets are being compiled correctly

See Troubleshooting Guide for more help.