Skip to content

Commit 8bce7fa

Browse files
justin808claude
andcommitted
Add Shakapacker precompile hook support for auto pack generation
This change leverages Shakapacker's new precompile_hook feature to automatically generate packs before webpack compilation, replacing the need to manually modify assets:precompile tasks or bin/dev scripts. Changes: - Add bin/shakapacker-precompile-hook script to templates and spec/dummy - Update shakapacker.yml to configure precompile_hook - Add PackerUtils.shakapacker_precompile_hook_configured? method - Skip generate_packs in configuration and PackGenerator when hook configured - Update generator to copy hook script and make it executable The precompile hook runs before webpack compilation and is properly validated by Shakapacker to ensure it points to a file within the project root. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
1 parent d527ddf commit 8bce7fa

File tree

8 files changed

+79
-2
lines changed

8 files changed

+79
-2
lines changed

lib/generators/react_on_rails/base_generator.rb

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,16 @@ def copy_base_files
3737
app/views/layouts/hello_world.html.erb
3838
Procfile.dev
3939
Procfile.dev-static-assets
40-
Procfile.dev-prod-assets]
40+
Procfile.dev-prod-assets
41+
bin/shakapacker-precompile-hook]
4142
base_templates = %w[config/initializers/react_on_rails.rb]
4243
base_files.each { |file| copy_file("#{base_path}#{file}", file) }
4344
base_templates.each do |file|
4445
template("#{base_path}/#{file}.tt", file)
4546
end
47+
48+
# Make the hook script executable
49+
File.chmod(0o755, "bin/shakapacker-precompile-hook") if File.exist?("bin/shakapacker-precompile-hook")
4650
end
4751

4852
def copy_js_bundle_files
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#!/usr/bin/env ruby
2+
# frozen_string_literal: true
3+
4+
# Shakapacker precompile hook for React on Rails
5+
#
6+
# This script runs before webpack compilation to generate pack files
7+
# for auto-bundled components. It's called automatically by Shakapacker
8+
# when configured in config/shakapacker.yml:
9+
# precompile_hook: 'bin/shakapacker-precompile-hook'
10+
11+
require_relative "../config/environment"
12+
13+
begin
14+
puts Rainbow("🔄 Running React on Rails precompile hook...").cyan
15+
ReactOnRails::PacksGenerator.instance.generate_packs_if_stale
16+
rescue StandardError => e
17+
warn Rainbow("❌ Error in precompile hook: #{e.message}").red
18+
warn e.backtrace.first(5).join("\n")
19+
exit 1
20+
end

lib/generators/react_on_rails/templates/base/base/config/shakapacker.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,11 @@ default: &default
4242
# Raises an error if there is a mismatch in the shakapacker gem and npm package being used
4343
ensure_consistent_versioning: true
4444

45+
# Hook to run before webpack compilation (e.g., for generating dynamic entry points)
46+
# SECURITY: Only reference trusted scripts within your project. The hook command will be
47+
# validated to ensure it points to a file within the project root.
48+
precompile_hook: 'bin/shakapacker-precompile-hook'
49+
4550
# Select whether the compiler will use SHA digest ('digest' option) or most recent modified timestamp ('mtime') to determine freshness
4651
compiler_strategy: digest
4752

lib/react_on_rails/configuration.rb

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,11 @@ def adjust_precompile_task
238238
raise(ReactOnRails::Error, compile_command_conflict_message) if ReactOnRails::PackerUtils.precompile?
239239

240240
precompile_tasks = lambda {
241-
Rake::Task["react_on_rails:generate_packs"].invoke
241+
# Skip generate_packs if shakapacker has a precompile hook configured
242+
unless ReactOnRails::PackerUtils.shakapacker_precompile_hook_configured?
243+
Rake::Task["react_on_rails:generate_packs"].invoke
244+
end
245+
242246
Rake::Task["react_on_rails:assets:webpack"].invoke
243247

244248
# VERSIONS is per the shakacode/shakapacker clean method definition.

lib/react_on_rails/dev/pack_generator.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@ module Dev
77
class PackGenerator
88
class << self
99
def generate(verbose: false)
10+
# Skip if shakapacker has a precompile hook configured
11+
if ReactOnRails::PackerUtils.shakapacker_precompile_hook_configured?
12+
puts "⏭️ Skipping pack generation (handled by shakapacker precompile hook)" if verbose
13+
return
14+
end
15+
1016
if verbose
1117
puts "📦 Generating React on Rails packs..."
1218
success = system "bundle exec rake react_on_rails:generate_packs"

lib/react_on_rails/packer_utils.rb

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,5 +166,18 @@ def self.raise_shakapacker_version_incompatible_for_basic_pack_generation
166166

167167
raise ReactOnRails::Error, msg
168168
end
169+
170+
# Check if shakapacker.yml has a precompile_hook configured
171+
# This prevents react_on_rails from running generate_packs redundantly
172+
def self.shakapacker_precompile_hook_configured?
173+
return false unless defined?(::Shakapacker)
174+
175+
config_data = ::Shakapacker.config.send(:data)
176+
hook = config_data[:precompile_hook]
177+
178+
hook.present?
179+
rescue StandardError
180+
false
181+
end
169182
end
170183
end
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#!/usr/bin/env ruby
2+
# frozen_string_literal: true
3+
4+
# Shakapacker precompile hook for React on Rails
5+
#
6+
# This script runs before webpack compilation to generate pack files
7+
# for auto-bundled components. It's called automatically by Shakapacker
8+
# when configured in config/shakapacker.yml:
9+
# precompile_hook: 'bin/shakapacker-precompile-hook'
10+
11+
require_relative "../config/environment"
12+
13+
begin
14+
puts Rainbow("🔄 Running React on Rails precompile hook...").cyan
15+
ReactOnRails::PacksGenerator.instance.generate_packs_if_stale
16+
rescue StandardError => e
17+
warn Rainbow("❌ Error in precompile hook: #{e.message}").red
18+
warn e.backtrace.first(5).join("\n")
19+
exit 1
20+
end

spec/dummy/config/shakapacker.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ default: &default
1717
cache_manifest: false
1818
nested_entries: true
1919

20+
# Hook to run before webpack compilation (e.g., for generating dynamic entry points)
21+
# SECURITY: Only reference trusted scripts within your project. The hook command will be
22+
# validated to ensure it points to a file within the project root.
23+
precompile_hook: 'bin/shakapacker-precompile-hook'
24+
2025
development:
2126
<<: *default
2227
# Turn this to true if you want to use the rails/shakapacker check that the test

0 commit comments

Comments
 (0)