Class: Shakapacker::Configuration

Inherits:
Object
  • Object
show all
Defined in:
lib/shakapacker/configuration.rb

Overview

Configuration management for Shakapacker

Loads and provides access to settings from config/shakapacker.yml, including:

  • Source and output paths

  • Compilation settings

  • Dev server configuration

  • Asset bundler selection (webpack vs rspack)

  • JavaScript transpiler configuration (babel, swc, esbuild)

Configuration values can be overridden via environment variables:

  • SHAKAPACKER_CONFIG - path to config file

  • SHAKAPACKER_PRECOMPILE - whether to precompile assets

  • SHAKAPACKER_ASSETS_BUNDLER - which bundler to use

  • SHAKAPACKER_ASSET_HOST - CDN or asset host URL

Examples:

Accessing configuration

config = Shakapacker.config
config.source_path
#=> #<Pathname:/app/app/packs>
config.webpack?
#=> true

See Also:

Class Attribute Summary collapse

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(root_path:, config_path:, env:, bundler_override: nil) ⇒ Shakapacker::Configuration

Creates a new configuration instance

Parameters:

  • root_path (Pathname)

    the application root path

  • config_path (Pathname)

    the path to shakapacker.yml

  • env (ActiveSupport::StringInquirer)

    the Rails environment

  • bundler_override (String, nil) (defaults to: nil)

    optional bundler override (webpack or rspack)



62
63
64
65
66
67
# File 'lib/shakapacker/configuration.rb', line 62

def initialize(root_path:, config_path:, env:, bundler_override: nil)
  @root_path = root_path
  @env = env
  @config_path = config_path
  @bundler_override = bundler_override
end

Class Attribute Details

.installingBoolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Flag indicating whether Shakapacker is currently being installed Used to suppress certain validations during installation

Returns:

  • (Boolean)

    true if installation is in progress



35
36
37
# File 'lib/shakapacker/configuration.rb', line 35

def installing
  @installing
end

Instance Attribute Details

#bundler_overrideString? (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Override for the assets bundler (set via CLI flag)

Returns:

  • (String, nil)

    the bundler override or nil



53
54
55
# File 'lib/shakapacker/configuration.rb', line 53

def bundler_override
  @bundler_override
end

#config_pathPathname (readonly)

The path to the shakapacker.yml configuration file

Returns:

  • (Pathname)

    the config file path



44
45
46
# File 'lib/shakapacker/configuration.rb', line 44

def config_path
  @config_path
end

#envActiveSupport::StringInquirer (readonly)

The current Rails environment

Returns:

  • (ActiveSupport::StringInquirer)

    the environment



48
49
50
# File 'lib/shakapacker/configuration.rb', line 48

def env
  @env
end

#root_pathPathname (readonly)

The application root path

Returns:

  • (Pathname)

    the root path



40
41
42
# File 'lib/shakapacker/configuration.rb', line 40

def root_path
  @root_path
end

Instance Method Details

#additional_pathsArray<String>

Returns additional paths to include in compilation

These paths are added to webpack/rspack’s resolve configuration to allow importing modules from additional directories.

Returns:

  • (Array<String>)

    array of additional paths



139
140
141
# File 'lib/shakapacker/configuration.rb', line 139

def additional_paths
  fetch(:additional_paths)
end

#asset_hostString?

Returns the asset host URL for serving assets

Resolution order:

  1. SHAKAPACKER_ASSET_HOST environment variable

  2. asset_host setting in config file

  3. Rails ActionController::Base.helpers.compute_asset_host

Used to serve assets from a CDN or different domain.

Returns:

  • (String, nil)

    the asset host URL or nil



485
486
487
488
489
490
# File 'lib/shakapacker/configuration.rb', line 485

def asset_host
  ENV.fetch(
    "SHAKAPACKER_ASSET_HOST",
    fetch(:asset_host) || ActionController::Base.helpers.compute_asset_host
  )
end

#assets_bundlerString

Returns the assets bundler to use (webpack or rspack)

Resolution order:

  1. CLI –bundler flag (via bundler_override)

  2. SHAKAPACKER_ASSETS_BUNDLER environment variable

  3. assets_bundler setting in config file

  4. bundler setting in config file (deprecated)

  5. Defaults to “webpack”

Returns:

  • (String)

    “webpack” or “rspack”



257
258
259
260
261
262
263
264
265
266
# File 'lib/shakapacker/configuration.rb', line 257

def assets_bundler
  # CLI --bundler flag takes highest precedence
  return @bundler_override if @bundler_override

  # Show deprecation warning if using old 'bundler' key
  if data.has_key?(:bundler) && !data.has_key?(:assets_bundler)
    $stderr.puts "⚠️  DEPRECATION WARNING: The 'bundler' configuration option is deprecated. Please use 'assets_bundler' instead to avoid confusion with Ruby's Bundler gem manager."
  end
  ENV["SHAKAPACKER_ASSETS_BUNDLER"] || fetch(:assets_bundler) || fetch(:bundler) || "webpack"
end

#assets_bundler_config_pathString

Returns the path to the bundler configuration directory

This is where webpack.config.js or rspack.config.js should be located. Defaults to config/webpack for webpack or config/rspack for rspack.

Returns:

  • (String)

    the relative path to the bundler config directory



373
374
375
376
377
378
379
# File 'lib/shakapacker/configuration.rb', line 373

def assets_bundler_config_path
  custom_path = fetch(:assets_bundler_config_path)
  return custom_path if custom_path

  # Default paths based on bundler type
  rspack? ? "config/rspack" : "config/webpack"
end

#bundlerString

Deprecated.

Use #assets_bundler instead

Deprecated alias for #assets_bundler

Returns:

  • (String)

    the assets bundler

See Also:



273
274
275
# File 'lib/shakapacker/configuration.rb', line 273

def bundler
  assets_bundler
end

#cache_manifest?Boolean

Returns whether manifest caching is enabled

When true, the manifest.json file is cached in memory and only reloaded when it changes. This improves performance in production.

Returns:

  • (Boolean)

    true if manifest should be cached



213
214
215
# File 'lib/shakapacker/configuration.rb', line 213

def cache_manifest?
  fetch(:cache_manifest)
end

#cache_pathPathname

Returns the absolute path to the compilation cache directory

Webpack/rspack uses this directory to cache compilation results for faster subsequent builds.

Returns:

  • (Pathname)

    the absolute cache path



223
224
225
# File 'lib/shakapacker/configuration.rb', line 223

def cache_path
  root_path.join(fetch(:cache_path))
end

#compile?Boolean

Returns whether automatic compilation is enabled

When true, Shakapacker will automatically compile assets when they’re requested and are stale. This is typically enabled in development and disabled in production.

Returns:

  • (Boolean)

    true if automatic compilation is enabled



84
85
86
# File 'lib/shakapacker/configuration.rb', line 84

def compile?
  fetch(:compile)
end

#compiler_strategyString

Returns the compiler strategy for determining staleness

Options:

  • “mtime” - use file modification times (faster, less accurate)

  • “digest” - use file content digests (slower, more accurate)

Returns:

  • (String)

    the compiler strategy (“mtime” or “digest”)



243
244
245
# File 'lib/shakapacker/configuration.rb', line 243

def compiler_strategy
  fetch(:compiler_strategy)
end

#css_modules_export_modeString

Returns the CSS Modules export mode configuration

Controls how CSS Module class names are exported in JavaScript:

  • “named” (default): Use named exports with camelCase conversion (v9 behavior)

  • “default”: Use default export with both original and camelCase names (v8 behavior)

Returns:

  • (String)

    “named” or “default”

Raises:

  • (ArgumentError)

    if an invalid value is configured



350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
# File 'lib/shakapacker/configuration.rb', line 350

def css_modules_export_mode
  @css_modules_export_mode ||= begin
    mode = fetch(:css_modules_export_mode) || "named"

    # Validate the configuration value
    valid_modes = ["named", "default"]
    unless valid_modes.include?(mode)
      raise ArgumentError,
        "Invalid css_modules_export_mode: '#{mode}'. " \
        "Valid values are: #{valid_modes.map { |m| "'#{m}'" }.join(', ')}. " \
        "See https://github.com/shakacode/shakapacker/blob/main/docs/css-modules-export-mode.md"
    end

    mode
  end
end

#dataHash<Symbol, Object>

Note:

The hash is frozen to prevent mutations. Use accessor methods for safe config access.

Returns the raw configuration data hash

Returns the merged configuration from the shakapacker.yml file for the current environment. The hash has symbolized keys loaded from the config file. Individual config values can be accessed through specific accessor methods like #source_path, which apply defaults via #fetch.

The returned hash is frozen to prevent accidental mutations. To access config values, use the provided accessor methods instead of modifying this hash directly.

Examples:

config.data[:source_path]  #=> "app/javascript"
config.data[:compile]      #=> true

Returns:

  • (Hash<Symbol, Object>)

    the raw configuration data with symbolized keys (frozen)



396
397
398
# File 'lib/shakapacker/configuration.rb', line 396

def data
  @data ||= load.freeze
end

#dev_serverHash

Returns the dev server configuration hash

Contains settings like host, port, https, hmr, etc. for the webpack-dev-server.

Returns:

  • (Hash)

    the dev server configuration



74
75
76
# File 'lib/shakapacker/configuration.rb', line 74

def dev_server
  fetch(:dev_server)
end

#early_hintsBoolean

Returns whether HTTP/2 Early Hints are enabled

When true, sends Early Hints headers to start loading assets before the full response is ready.

Returns:

  • (Boolean)

    true if early hints are enabled



508
509
510
# File 'lib/shakapacker/configuration.rb', line 508

def early_hints
  fetch(:early_hints)
end

#ensure_consistent_versioning?Boolean

Returns whether consistent versioning check is enabled

When true, verifies that package.json and Gemfile versions of shakapacker match.

Returns:

  • (Boolean)

    true if version consistency checking is enabled



103
104
105
# File 'lib/shakapacker/configuration.rb', line 103

def ensure_consistent_versioning?
  fetch(:ensure_consistent_versioning)
end

#fetch(key) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Fetches a configuration value

Looks up the value in the loaded configuration data, falling back to the default configuration if not found.

Parameters:

  • key (Symbol)

    the configuration key to fetch

Returns:

  • (Object)

    the configuration value



471
472
473
# File 'lib/shakapacker/configuration.rb', line 471

def fetch(key)
  data.fetch(key, defaults[key])
end

#integrityBoolean

Returns whether subresource integrity (SRI) is enabled

When true, generates integrity hashes for script and link tags to protect against compromised CDNs or man-in-the-middle attacks.

Returns:

  • (Boolean)

    true if integrity checking is enabled



498
499
500
# File 'lib/shakapacker/configuration.rb', line 498

def integrity
  fetch(:integrity)
end

#javascript_transpilerString

Returns the JavaScript transpiler to use (babel, swc, or esbuild)

Resolution order:

  1. javascript_transpiler setting in config file

  2. webpack_loader setting in config file (deprecated)

  3. Default based on bundler (swc for rspack, babel for webpack)

Validates that the configured transpiler matches installed packages.

Returns:

  • (String)

    “babel”, “swc”, or “esbuild”



318
319
320
321
322
323
324
325
326
327
328
329
330
331
# File 'lib/shakapacker/configuration.rb', line 318

def javascript_transpiler
  # Show deprecation warning if using old 'webpack_loader' key
  if data.has_key?(:webpack_loader) && !data.has_key?(:javascript_transpiler)
    $stderr.puts "⚠️  DEPRECATION WARNING: The 'webpack_loader' configuration option is deprecated. Please use 'javascript_transpiler' instead as it better reflects its purpose of configuring JavaScript transpilation regardless of the bundler used."
  end

  # Use explicit config if set, otherwise default based on bundler
  transpiler = fetch(:javascript_transpiler) || fetch(:webpack_loader) || default_javascript_transpiler

  # Validate transpiler configuration
  validate_transpiler_configuration(transpiler) unless self.class.installing

  transpiler
end

#manifest_pathPathname

Returns the absolute path to the manifest.json file

The manifest maps source file names to their compiled output paths with digests. Defaults to manifest.json in the public output directory if not configured.

Returns:

  • (Pathname)

    the absolute manifest path



158
159
160
161
162
163
164
# File 'lib/shakapacker/configuration.rb', line 158

def manifest_path
  if data.has_key?(:manifest_path)
    root_path.join(fetch(:manifest_path))
  else
    public_output_path.join("manifest.json")
  end
end

#nested_entries?Boolean

Returns whether nested entries are enabled

When true, allows organizing entry points in subdirectories within the source entry path.

Returns:

  • (Boolean)

    true if nested entries are allowed



94
95
96
# File 'lib/shakapacker/configuration.rb', line 94

def nested_entries?
  fetch(:nested_entries)
end

#precompile_hookString?

Returns the precompile hook command to run after compilation

The hook is a shell command that runs after successful compilation, useful for post-processing tasks.

Returns:

  • (String, nil)

    the hook command or nil if not configured



297
298
299
300
301
302
303
304
305
306
# File 'lib/shakapacker/configuration.rb', line 297

def precompile_hook
  hook = fetch(:precompile_hook)
  return nil if hook.nil? || (hook.is_a?(String) && hook.strip.empty?)

  unless hook.is_a?(String)
    raise "Shakapacker configuration error: precompile_hook must be a string, got #{hook.class}"
  end

  hook.strip
end

#private_output_pathPathname?

Returns the absolute path to the private output directory

The private output path is for server-side bundles (e.g., SSR) that should not be publicly accessible. Returns nil if not configured.

Returns:

  • (Pathname, nil)

    the absolute private output path or nil



190
191
192
193
194
195
# File 'lib/shakapacker/configuration.rb', line 190

def private_output_path
  private_path = fetch(:private_output_path)
  return nil unless private_path
  validate_output_paths!
  root_path.join(private_path)
end

#public_manifest_pathPathname

Alias for #manifest_path

Returns:

  • (Pathname)

    the absolute manifest path

See Also:



170
171
172
# File 'lib/shakapacker/configuration.rb', line 170

def public_manifest_path
  manifest_path
end

#public_output_pathPathname

Returns the absolute path to the public output directory

This is where compiled assets are written for public serving (typically public/packs).

Returns:

  • (Pathname)

    the absolute public output path



203
204
205
# File 'lib/shakapacker/configuration.rb', line 203

def public_output_path
  public_path.join(fetch(:public_output_path))
end

#public_pathPathname

Returns the absolute path to the public root directory

This is typically the Rails public/ directory where compiled assets are served from.

Returns:

  • (Pathname)

    the absolute public path



180
181
182
# File 'lib/shakapacker/configuration.rb', line 180

def public_path
  root_path.join(fetch(:public_root_path))
end

#rspack?Boolean

Returns whether rspack is the configured bundler

Returns:

  • (Boolean)

    true if using rspack



280
281
282
# File 'lib/shakapacker/configuration.rb', line 280

def rspack?
  assets_bundler == "rspack"
end

#shakapacker_precompile?Boolean

Returns whether Shakapacker should precompile assets

Checks in order:

  1. SHAKAPACKER_PRECOMPILE environment variable (yes/true/y/t or no/false/n/f)

  2. shakapacker_precompile setting in config file

  3. Defaults to false if config file doesn’t exist

Returns:

  • (Boolean)

    true if assets should be precompiled



115
116
117
118
119
120
121
122
# File 'lib/shakapacker/configuration.rb', line 115

def shakapacker_precompile?
  # ENV of false takes precedence
  return false if %w(no false n f).include?(ENV["SHAKAPACKER_PRECOMPILE"])
  return true if %w(yes true y t).include?(ENV["SHAKAPACKER_PRECOMPILE"])

  return false unless config_path.exist?
  fetch(:shakapacker_precompile)
end

#source_entry_pathPathname

Returns the absolute path to the source entry directory

Entry points (application.js, etc.) are found in this directory.

Returns:

  • (Pathname)

    the absolute entry path



148
149
150
# File 'lib/shakapacker/configuration.rb', line 148

def source_entry_path
  source_path.join(relative_path(fetch(:source_entry_path)))
end

#source_pathPathname

Returns the absolute path to the source directory

This is where your JavaScript/CSS source files live (e.g., app/packs).

Returns:

  • (Pathname)

    the absolute source path



129
130
131
# File 'lib/shakapacker/configuration.rb', line 129

def source_path
  root_path.join(fetch(:source_path))
end

#webpack?Boolean

Returns whether webpack is the configured bundler

Returns:

  • (Boolean)

    true if using webpack



287
288
289
# File 'lib/shakapacker/configuration.rb', line 287

def webpack?
  assets_bundler == "webpack"
end

#webpack_compile_output?Boolean

Returns whether webpack/rspack compilation output should be shown

When true, displays webpack/rspack’s compilation progress and results.

Returns:

  • (Boolean)

    true if compilation output should be displayed



232
233
234
# File 'lib/shakapacker/configuration.rb', line 232

def webpack_compile_output?
  fetch(:webpack_compile_output)
end

#webpack_loaderString

Deprecated.

Deprecated alias for #javascript_transpiler

Returns:

  • (String)

    the JavaScript transpiler

See Also:



338
339
340
# File 'lib/shakapacker/configuration.rb', line 338

def webpack_loader
  javascript_transpiler
end