Skip to content

Commit 447f537

Browse files
justin808claude
andcommitted
Improve precompile hook documentation and add changelog entry
- Document that SHAKAPACKER_SKIP_PRECOMPILE_HOOK requires exact string "true" - Replace risky .env file modification with safer alternatives - Replace eval usage with Ruby system() calls for better security - Reorder examples to recommend Procfile env prefix approach first - Add comprehensive CHANGELOG entry with migration tips 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
1 parent 62f2f02 commit 447f537

2 files changed

Lines changed: 50 additions & 47 deletions

File tree

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@
1111

1212
Changes since the last non-beta release.
1313

14+
### Added
15+
16+
- **Added `SHAKAPACKER_SKIP_PRECOMPILE_HOOK` environment variable to skip precompile hook**. [PR #XXX](https://github.com/shakacode/shakapacker/pull/XXX) by [justin808](https://github.com/justin808). Set `SHAKAPACKER_SKIP_PRECOMPILE_HOOK=true` to skip the precompile hook during compilation. This is useful when using process managers like Foreman or Overmind to run the hook once before starting multiple webpack processes, preventing duplicate hook execution. **Migration tip:** If you have a custom `bin/dev` script that starts multiple webpack processes, you can now run the precompile hook once in the script and set this environment variable to prevent each webpack process from running the hook again. See the [precompile hook documentation](./docs/precompile_hook.md#skipping-the-hook) for implementation examples.
17+
1418
## [v9.3.4-beta.0] - November 17, 2025
1519

1620
### Fixed

docs/precompile_hook.md

Lines changed: 46 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,8 @@ You can skip the precompile hook using the `SHAKAPACKER_SKIP_PRECOMPILE_HOOK` en
292292
SHAKAPACKER_SKIP_PRECOMPILE_HOOK=true bin/shakapacker
293293
```
294294

295+
**Important:** The environment variable must be set to the exact string `"true"` to skip the hook. Any other value (including `"false"`, `"1"`, or empty string) will run the hook normally.
296+
295297
This is useful when:
296298

297299
- Using `bin/dev` or Foreman to run the hook once before starting multiple webpack processes
@@ -300,82 +302,79 @@ This is useful when:
300302

301303
**Note:** The examples below show how to implement this in your custom `bin/dev` script. If you're using React on Rails, the generated `bin/dev` script already implements this pattern automatically - it runs the precompile hook once before launching processes, then sets `SHAKAPACKER_SKIP_PRECOMPILE_HOOK=true` to prevent duplicate execution.
302304

303-
**Example with Foreman:**
305+
**Recommended: Use Procfile env prefix**
306+
307+
The cleanest approach is to set the environment variable per-process in your Procfile:
308+
309+
```procfile
310+
# Procfile.dev
311+
web: env SHAKAPACKER_SKIP_PRECOMPILE_HOOK=true bin/rails server
312+
webpack-client: env SHAKAPACKER_SKIP_PRECOMPILE_HOOK=true bin/shakapacker --watch
313+
webpack-server: env SHAKAPACKER_SKIP_PRECOMPILE_HOOK=true bin/shakapacker --watch --config-name server
314+
```
304315

305-
Foreman reads environment variables from `.env` files. Add the skip flag to your `.env` file:
316+
Then your `bin/dev` can run the hook once and launch the process manager:
306317

307318
```bash
308319
#!/usr/bin/env bash
309320
# bin/dev
310321

311322
# Run the hook once before launching all processes
312-
if [ -f "config/shakapacker.yml" ]; then
313-
# Extract and run the precompile_hook if configured
314-
HOOK=$(ruby -ryaml -e "puts YAML.load_file('config/shakapacker.yml')['development']['precompile_hook'] rescue nil")
315-
if [ -n "$HOOK" ]; then
316-
echo "Running precompile hook: $HOOK"
317-
eval $HOOK || exit 1
318-
fi
319-
fi
320-
321-
# Add skip flag to .env file for foreman subprocesses
322-
echo "SHAKAPACKER_SKIP_PRECOMPILE_HOOK=true" > .env.tmp
323-
cat .env >> .env.tmp 2>/dev/null || true
324-
mv .env.tmp .env
323+
bundle exec ruby -r ./config/boot -e "
324+
hook = Shakapacker.config.precompile_hook
325+
if hook
326+
puts \"Running precompile hook: #{hook}\"
327+
system(hook) or exit(1)
328+
end
329+
"
325330

326-
# Launch Procfile
327331
exec foreman start -f Procfile.dev
332+
# or: exec overmind start -f Procfile.dev
328333
```
329334

330-
**Example with Overmind:**
335+
**Alternative: Export environment variable**
331336

332-
Overmind reads environment variables from `.env` or `.overmind.env` files:
337+
You can export the environment variable before starting your process manager:
333338

334339
```bash
335340
#!/usr/bin/env bash
336341
# bin/dev
337342

338343
# Run the hook once before launching all processes
339-
if [ -f "config/shakapacker.yml" ]; then
340-
HOOK=$(ruby -ryaml -e "puts YAML.load_file('config/shakapacker.yml')['development']['precompile_hook'] rescue nil")
341-
if [ -n "$HOOK" ]; then
342-
echo "Running precompile hook: $HOOK"
343-
eval $HOOK || exit 1
344-
fi
345-
fi
344+
bundle exec ruby -r ./config/boot -e "
345+
hook = Shakapacker.config.precompile_hook
346+
if hook
347+
puts \"Running precompile hook: #{hook}\"
348+
system(hook) or exit(1)
349+
end
350+
"
346351

347-
# Add skip flag to .overmind.env file for overmind subprocesses
348-
echo "SHAKAPACKER_SKIP_PRECOMPILE_HOOK=true" > .overmind.env
352+
# Export skip flag for all subprocesses
353+
export SHAKAPACKER_SKIP_PRECOMPILE_HOOK=true
349354

350-
# Launch Procfile
351-
exec overmind start -f Procfile.dev
355+
exec foreman start -f Procfile.dev
356+
# or: exec overmind start -f Procfile.dev
352357
```
353358

354-
**Alternative: Use Procfile env prefix**
355-
356-
You can also set the environment variable per-process in your Procfile:
357-
358-
```procfile
359-
# Procfile.dev
360-
web: env SHAKAPACKER_SKIP_PRECOMPILE_HOOK=true bin/rails server
361-
webpack-client: env SHAKAPACKER_SKIP_PRECOMPILE_HOOK=true bin/shakapacker --watch
362-
webpack-server: env SHAKAPACKER_SKIP_PRECOMPILE_HOOK=true bin/shakapacker --watch --config-name server
363-
```
359+
**Alternative: Use .env.local (not tracked by git)**
364360

365-
Then your `bin/dev` can simply run the hook and launch the process manager:
361+
For Foreman or Overmind, you can create a `.env.local` file (typically gitignored):
366362

367363
```bash
368364
#!/usr/bin/env bash
369365
# bin/dev
370366

371367
# Run the hook once before launching all processes
372-
if [ -f "config/shakapacker.yml" ]; then
373-
HOOK=$(ruby -ryaml -e "puts YAML.load_file('config/shakapacker.yml')['development']['precompile_hook'] rescue nil")
374-
if [ -n "$HOOK" ]; then
375-
echo "Running precompile hook: $HOOK"
376-
eval $HOOK || exit 1
377-
fi
378-
fi
368+
bundle exec ruby -r ./config/boot -e "
369+
hook = Shakapacker.config.precompile_hook
370+
if hook
371+
puts \"Running precompile hook: #{hook}\"
372+
system(hook) or exit(1)
373+
end
374+
"
375+
376+
# Create .env.local for process manager subprocesses
377+
echo "SHAKAPACKER_SKIP_PRECOMPILE_HOOK=true" > .env.local
379378

380379
exec foreman start -f Procfile.dev
381380
# or: exec overmind start -f Procfile.dev

0 commit comments

Comments
 (0)