Add Precompile Hook Support with Environment-Based Skip Flag
Summary
Add support for precompile_hook configuration in shakapacker.yml that runs before webpack compilation, with an environment variable flag to skip the hook when needed (e.g., when called from bin/dev which runs the hook once before launching all processes).
Problem
Currently, there's no standardized way to run pre-build tasks (like ReScript compilation, locale generation, or other build prerequisites) before webpack starts. Projects resort to:
-
Sleep delays in Procfiles - Fragile timing-based workarounds:
wp-client: sleep 15 && bin/shakapacker-dev-server
wp-server: sleep 15 && bundle exec rake react_on_rails:locale && bin/shakapacker --watch
-
Manual task execution - Duplicating tasks in multiple places (Procfiles, rake tasks, CI scripts)
-
No coordination - When bin/dev or development servers start, there's no single place to run prerequisites
Proposed Solution
1. Add precompile_hook to shakapacker.yml
default: &default
# Command or script to run before webpack compilation
# Can be a shell command or path to executable script
precompile_hook: "yarn res:build && bundle exec rake react_on_rails:locale"
# Or point to a script file
precompile_hook: "./bin/precompile-hook"
2. Run hook automatically in bin/shakapacker and bin/shakapacker-dev-server
Unless SHAKAPACKER_SKIP_PRECOMPILE_HOOK=true is set:
# In Shakapacker::Runner.run or Shakapacker::DevServerRunner.run
unless ENV['SHAKAPACKER_SKIP_PRECOMPILE_HOOK'] == 'true'
if (hook_command = Shakapacker.config.precompile_hook)
puts "Running precompile hook: #{hook_command}"
system(hook_command) or raise "Precompile hook failed"
end
end
3. bin/dev integration pattern
The recommended pattern for bin/dev:
# bin/dev runs the hook ONCE before launching Procfile processes
if (hook_command = Shakapacker.config.precompile_hook)
system(hook_command) or exit(1)
end
# Then launch Procfile with skip flag set
ENV['SHAKAPACKER_SKIP_PRECOMPILE_HOOK'] = 'true'
# ... launch foreman/overmind with Procfile.dev
This ensures:
- Hook runs once when starting development
- Individual webpack processes (client/server bundles) don't re-run it
- Production deploys run it once during asset compilation
- Can be skipped explicitly when needed
Benefits
- Eliminates sleep hacks - No more fragile timing delays
- Single source of truth - Precompile logic in one place (shakapacker.yml)
- Flexible control - Environment variable allows fine-grained control
- Framework integration - React on Rails, Vite Ruby, etc. can coordinate with this
- CI/CD friendly - Works consistently across development and production
Example Use Cases
ReScript + React on Rails
precompile_hook: "yarn res:build && bundle exec rake react_on_rails:locale"
TypeScript with custom codegen
precompile_hook: "./bin/generate-graphql-types"
Multi-step build
precompile_hook: "./bin/precompile-hook"
Where bin/precompile-hook:
#!/bin/bash
set -e
yarn res:build
bundle exec rake react_on_rails:locale
yarn run generate:icons
Implementation Checklist
Related Issues
This coordinates with React on Rails issue about moving react_on_rails:locale from Procfiles into the precompile hook.
Version
Shakapacker: 9.3.3
Context: Working with React on Rails 16.2.0.beta.12, Rails 8.1.1
Add Precompile Hook Support with Environment-Based Skip Flag
Summary
Add support for
precompile_hookconfiguration in shakapacker.yml that runs before webpack compilation, with an environment variable flag to skip the hook when needed (e.g., when called frombin/devwhich runs the hook once before launching all processes).Problem
Currently, there's no standardized way to run pre-build tasks (like ReScript compilation, locale generation, or other build prerequisites) before webpack starts. Projects resort to:
Sleep delays in Procfiles - Fragile timing-based workarounds:
Manual task execution - Duplicating tasks in multiple places (Procfiles, rake tasks, CI scripts)
No coordination - When
bin/devor development servers start, there's no single place to run prerequisitesProposed Solution
1. Add
precompile_hookto shakapacker.yml2. Run hook automatically in bin/shakapacker and bin/shakapacker-dev-server
Unless
SHAKAPACKER_SKIP_PRECOMPILE_HOOK=trueis set:3. bin/dev integration pattern
The recommended pattern for
bin/dev:This ensures:
Benefits
Example Use Cases
ReScript + React on Rails
TypeScript with custom codegen
Multi-step build
Where
bin/precompile-hook:Implementation Checklist
precompile_hookconfig option to shakapacker.ymlShakapacker::Configuration#precompile_hookmethodShakapacker::Runnerto run hook before webpack (unless skip flag set)Shakapacker::DevServerRunnerto run hook before dev server (unless skip flag set)SHAKAPACKER_SKIP_PRECOMPILE_HOOKenvironment variable checkRelated Issues
This coordinates with React on Rails issue about moving
react_on_rails:localefrom Procfiles into the precompile hook.Version
Shakapacker: 9.3.3
Context: Working with React on Rails 16.2.0.beta.12, Rails 8.1.1