-
-
Notifications
You must be signed in to change notification settings - Fork 632
Description
Summary
The react-webpack-rails-tutorial migration to v16 revealed a more flexible and cleaner approach to handling precompile tasks than the default precompile_hook mechanism. This approach better supports projects with custom build requirements (e.g., ReScript, TypeScript compilation, custom locale generation).
Current Default Approach
React on Rails uses Shakapacker's precompile_hook in shakapacker.yml:
precompile_hook: 'bin/shakapacker-precompile-hook'This hook:
- Runs before webpack compilation
- Calls
ReactOnRails::PacksGenerator.instance.generate_packs_if_stale - Is designed primarily for auto-bundled component packs generation
Limitations:
- Projects with additional precompile needs (ReScript, custom locale handling) must either:
- Modify the hook script (mixing concerns)
- Add precompile tasks to Procfile commands (duplicated, error-prone)
- The hook mechanism adds indirection and complexity
- Embedded precompile tasks in Procfiles are harder to maintain
Proposed Alternative: Extensible bin/dev with Explicit Precompile
The react-webpack-rails-tutorial branch uses this cleaner pattern:
1. Custom precompile in bin/dev (NOT in precompile_hook)
# bin/dev
def run_precompile_tasks
require_relative "../config/environment"
puts "📦 Running precompile tasks..."
# Project-specific: Build ReScript files
print " ReScript build... "
system("yarn res:build") or exit(1)
puts "✅"
# Locale generation via direct Ruby API (faster, no shell issues)
print " Locale generation... "
ReactOnRails::Locales.compile
puts "✅"
end
# Only run precompile for server start commands
unless ARGV.include?("kill") || ARGV.include?("-h")
run_precompile_tasks
end
ReactOnRails::Dev::ServerManager.run_from_command_line(ARGV)2. Disable precompile_hook in shakapacker.yml
default: &default
shakapacker_precompile: false
# Note: precompile_hook is not used here because:
# - In development: bin/dev runs precompile tasks before starting processes
# - In production: build_production_command includes all build steps3. Clean Procfiles (no embedded precompile logic)
# Procfile.dev - Clean and simple
rescript: yarn res:watch
rails: bundle exec thrust bin/rails server -p 3000
wp-client: RAILS_ENV=development bin/shakapacker-dev-server
wp-server: SERVER_BUNDLE_ONLY=yes bin/shakapacker --watch
Compare to the old approach with embedded precompile:
# Old approach - duplicated precompile in Procfile
webpack: sh -c 'bundle exec rake react_on_rails:locale && rm -rf public/packs/* || true && bin/shakapacker -w'
4. Build commands handle production
# config/initializers/react_on_rails.rb
config.build_test_command = "yarn res:build && RAILS_ENV=test bin/shakapacker"
config.build_production_command = "yarn res:build && RAILS_ENV=production NODE_ENV=production bin/shakapacker"Benefits of This Approach
| Aspect | Default (precompile_hook) | Proposed (bin/dev) |
|---|---|---|
| Custom build steps | Modify hook script (mixing concerns) | Add to run_precompile_tasks method |
| Procfile clarity | Embedded shell commands | Clean, single-purpose processes |
| Locale generation | Via rake task (slow, shell issues) | Direct ReactOnRails::Locales.compile (fast) |
| Version manager compatibility | Rake task may use wrong Ruby | Direct Ruby call uses correct version |
| Debugging | Multiple indirection layers | Clear sequential execution |
| When precompile runs | Before each webpack compile | Once at dev server startup |
Specific Improvements
1. Direct Ruby API for Locale Generation
Instead of:
bundle exec rake react_on_rails:localeUse:
ReactOnRails::Locales.compileThis avoids:
- Shell spawning overhead
- Version manager PATH issues (mise, asdf, rbenv)
- Duplicate Rails environment loading
2. Extensible Precompile Pattern
Provide a hook point in bin/dev or a new configuration option:
# Option A: Configuration-based
ReactOnRails.configure do |config|
config.precompile_tasks = [
-> { system("yarn res:build") },
-> { ReactOnRails::Locales.compile },
]
end
# Option B: Documented bin/dev pattern
# bin/dev template includes clear extension point
def run_precompile_tasks
# Add your custom precompile tasks here
# Example: system("yarn res:build")
ReactOnRails::Locales.compile if ReactOnRails.configuration.i18n_dir.present?
end3. Document the "No precompile_hook" Pattern
For projects that don't use auto-bundling or have custom build requirements, document:
# shakapacker.yml - Alternative: explicit precompile in bin/dev
default: &default
shakapacker_precompile: false
# precompile_hook: not configured - handled by bin/devProposal
-
Add extensible precompile support to bin/dev template: Include a
run_precompile_tasksmethod with clear extension points -
Expose
ReactOnRails::Locales.compileas public API: Document its use for custom bin/dev scripts -
Document the "no precompile_hook" pattern: For projects with custom build requirements
-
Add configuration option for precompile tasks: Allow registering custom tasks via configuration
-
Update Procfile templates: Remove embedded precompile logic when bin/dev handles it
Reference Implementation
- Branch:
justin808/shakapacker-early-hintsin react-webpack-rails-tutorial - Key files:
bin/dev,config/shakapacker.yml,Procfile.dev - Related issues: Conductor multi-version-manager support (Doc Changes for links on gitbook #692)