shakapacker 9.7.0 → 10.0.0.rc.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/.claude/commands/address-review.md +45 -17
  3. data/.claude/commands/verify.md +12 -0
  4. data/.claude/rules/coding-style.md +7 -0
  5. data/.claude/rules/git-workflow.md +6 -0
  6. data/.claude/rules/open-source.md +7 -0
  7. data/.claude/rules/testing.md +9 -0
  8. data/.github/workflows/dummy.yml +1 -2
  9. data/.github/workflows/node.yml +2 -1
  10. data/.github/workflows/trigger-docs-site.yml +24 -0
  11. data/.gitignore +3 -0
  12. data/CHANGELOG.md +23 -1
  13. data/CLAUDE.md +13 -2
  14. data/CONTRIBUTING.md +5 -4
  15. data/README.md +52 -32
  16. data/docs/api-reference.md +33 -55
  17. data/docs/cdn_setup.md +3 -3
  18. data/docs/common-upgrades.md +4 -4
  19. data/docs/css-modules-export-mode.md +3 -44
  20. data/docs/deployment.md +1 -1
  21. data/docs/early_hints.md +1 -1
  22. data/docs/optional-peer-dependencies.md +8 -6
  23. data/docs/peer-dependencies.md +47 -41
  24. data/docs/precompile_hook.md +5 -4
  25. data/docs/react.md +36 -225
  26. data/docs/releasing.md +8 -3
  27. data/docs/rspack.md +1 -1
  28. data/docs/rspack_migration_guide.md +11 -27
  29. data/docs/transpiler-migration.md +21 -21
  30. data/docs/troubleshooting.md +13 -4
  31. data/docs/typescript-migration.md +2 -2
  32. data/docs/using_esbuild_loader.md +1 -1
  33. data/docs/using_swc_loader.md +2 -2
  34. data/docs/v9_upgrade.md +8 -6
  35. data/lib/install/bin/shakapacker-watch +77 -0
  36. data/lib/install/package.json +4 -4
  37. data/lib/install/template.rb +12 -10
  38. data/lib/shakapacker/doctor.rb +4 -3
  39. data/lib/shakapacker/version.rb +1 -1
  40. data/package/types/README.md +3 -3
  41. data/package/webpackDevServerConfig.ts +25 -4
  42. data/package.json +8 -8
  43. data/test/package/bundlerUtils.rspack.test.js +13 -9
  44. data/test/package/webpackDevServerConfig.test.js +55 -0
  45. data/yarn.lock +128 -153
  46. metadata +11 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 518eb8673a021c5e18507ebc14ba593128288ddb9f735390581bd998d1f33715
4
- data.tar.gz: 3c2c532321d8c79e4374fbbe0854319d6ebd89df33557e21a4ce6e4ec322cc7c
3
+ metadata.gz: 88f81e8b1935f9898330405c06f7e71366d53b5c43a9223931055a741697e76a
4
+ data.tar.gz: f4358d5be4114b34aa01668c07b2ed5d0e032dfac18174c4e052afdd39885091
5
5
  SHA512:
6
- metadata.gz: 26414fbf14fe2d835262ee5a6d2b46a9e50c76eee0391a0d859b60ee60f8899a87fa0e8c9d39aa651a8eadecb37639cd9684e775dd2004a55f83bb1f8aa4647e
7
- data.tar.gz: 13f248afecdaa3ef579a20f7abf7ed592db788c2e5aa6b119a4940429b1e3c6f0bae263b985abe78e6ed0217116c6eeb9483c252f3a38bddd33e1c6e4533cc2c
6
+ metadata.gz: e774c9cce94707f55922d2bb65d3ce9aa1f773937a315373cde05e6c01ad4531e1815e2a1b276dc80c07ff670604db0de58e5cf14b67b7130cf27ac3135cb619
7
+ data.tar.gz: 3cf440898e5ef0a949835aead30e370c4bbd5d648e57233b763bc8a768edfca7572fbcbf954d1823c80321e1220e8d086114400296d3b345c59fd48cf2092245
@@ -16,7 +16,9 @@ If this command fails, ensure `gh` CLI is installed and authenticated (`gh auth
16
16
 
17
17
  ## Step 2: Parse User Input
18
18
 
19
- Extract the PR number and optional review/comment ID from the user's message:
19
+ The user's input is: $ARGUMENTS
20
+
21
+ Extract the PR number and optional review/comment ID from the input above:
20
22
 
21
23
  **Supported formats:**
22
24
 
@@ -42,21 +44,40 @@ gh api repos/${REPO}/issues/comments/{COMMENT_ID} | jq '{body: .body, user: .use
42
44
  **If a specific review ID is provided (`#pullrequestreview-...`):**
43
45
 
44
46
  ```bash
45
- gh api repos/${REPO}/pulls/{PR_NUMBER}/reviews/{REVIEW_ID}/comments | jq '[.[] | {id: .id, path: .path, body: .body, line: .line, start_line: .start_line, user: .user.login}]'
47
+ # Review body (often contains summary feedback)
48
+ gh api repos/${REPO}/pulls/{PR_NUMBER}/reviews/{REVIEW_ID} | jq '{id: .id, body: .body, state: .state, user: .user.login, html_url: .html_url}'
49
+
50
+ # Inline comments for this review
51
+ gh api --paginate repos/${REPO}/pulls/{PR_NUMBER}/reviews/{REVIEW_ID}/comments | jq -s '[.[].[] | {id: .id, node_id: .node_id, path: .path, body: .body, line: .line, start_line: .start_line, user: .user.login, in_reply_to_id: .in_reply_to_id}]'
46
52
  ```
47
53
 
48
- **If only PR number is provided (fetch all PR review comments):**
54
+ Include the review body as a general comment when it contains actionable feedback. When the review body contains actionable feedback, note that it cannot be replied to via the `/replies` endpoint — responses to review summary bodies must be posted as general PR comments (see Step 7).
55
+
56
+ **If only PR number is provided (fetch all PR comments):**
49
57
 
50
58
  ```bash
51
- gh api repos/${REPO}/pulls/{PR_NUMBER}/comments | jq '[.[] | {id: .id, path: .path, body: .body, line: .line, start_line: .start_line, user: .user.login, in_reply_to_id: .in_reply_to_id}]'
59
+ # Inline code review comments
60
+ gh api --paginate repos/${REPO}/pulls/{PR_NUMBER}/comments | jq -s '[.[].[] | {id: .id, node_id: .node_id, type: "review", path: .path, body: .body, line: .line, start_line: .start_line, user: .user.login, in_reply_to_id: .in_reply_to_id}]'
61
+
62
+ # General PR discussion comments (not tied to specific lines)
63
+ gh api --paginate repos/${REPO}/issues/{PR_NUMBER}/comments | jq -s '[.[].[] | {id: .id, node_id: .node_id, type: "issue", body: .body, user: .user.login, html_url: .html_url}]'
64
+ ```
65
+
66
+ **For all paths that fetch review comments (both specific review and full PR), fetch review thread metadata and attach `thread_id` by matching each review comment's `node_id`:**
67
+
68
+ ```bash
69
+ OWNER=${REPO%/*}
70
+ NAME=${REPO#*/}
71
+ gh api graphql --paginate -f owner="${OWNER}" -f name="${NAME}" -F pr={PR_NUMBER} -f query='query($owner:String!, $name:String!, $pr:Int!, $endCursor:String) { repository(owner:$owner, name:$name) { pullRequest(number:$pr) { reviewThreads(first:100, after:$endCursor) { nodes { id isResolved comments(first:100) { nodes { id databaseId } } } pageInfo { hasNextPage endCursor } } } } }' | jq -s '[.[].data.repository.pullRequest.reviewThreads.nodes[] | {thread_id: .id, is_resolved: .isResolved, comments: [.comments.nodes[] | {node_id: .id, id: .databaseId}]}]'
52
72
  ```
53
73
 
54
74
  **Filtering comments:**
55
75
 
76
+ - Skip comments belonging to already-resolved threads (match via `thread_id` and `is_resolved` from the GraphQL response)
56
77
  - Skip comments where `in_reply_to_id` is set (these are replies, not top-level comments)
57
78
  - Do not skip bot-generated comments by default. Many actionable review comments in this repository come from bots.
58
79
  - Deduplicate repeated bot comments and skip bot status posts, summaries, and acknowledgments that do not require a code or documentation change
59
- - Treat as actionable by default only: correctness bugs, regressions, missing tests, and clear inconsistencies with adjacent code
80
+ - Treat as actionable by default only: correctness bugs, regressions, security issues, missing tests, and clear inconsistencies with adjacent code
60
81
  - Treat as non-actionable by default: style nits, speculative suggestions, changelog wording, duplicate bot comments, and "could consider" feedback unless the user explicitly asks for polish work
61
82
  - Focus on actionable feedback, not acknowledgments or thank-you messages
62
83
 
@@ -83,31 +104,33 @@ Triage rules:
83
104
 
84
105
  ## Step 5: Create Todo List
85
106
 
86
- Create a todo list with TodoWrite containing **only the `MUST-FIX` items**:
107
+ Create a task list with TodoWrite containing **only the `MUST-FIX` items**:
87
108
 
88
- - One todo per must-fix comment or deduplicated issue
89
- - For file-specific comments: `"{file}:{line} - {comment_summary} (@{username})"` (content)
90
- - For general comments: Parse the comment body and extract the must-fix action
91
- - Format activeForm: `"Addressing {brief description}"`
92
- - All todos should start with status: `"pending"`
109
+ - One task per must-fix comment or deduplicated issue
110
+ - Subject: `"{file}:{line} - {comment_summary} (@{username})"`
111
+ - For general comments: Parse the comment body and extract the must-fix action as the subject
112
+ - Description: Include the full review comment text and any relevant context
113
+ - All tasks should start with status: `"pending"`
93
114
 
94
115
  ## Step 6: Present Triage to User
95
116
 
96
117
  Present the triage to the user - **DO NOT automatically start addressing items**:
97
118
 
119
+ - Use a single sequential numbering across all categories (1, 2, 3, ...) so every item has a unique number the user can reference. Do not restart numbering at 1 for each category.
98
120
  - `MUST-FIX ({count})`: list the todos created
99
121
  - `DISCUSS ({count})`: list items needing user choice, with a short reason
100
122
  - `SKIPPED ({count})`: list skipped comments with a short reason, including duplicates and factually incorrect suggestions
101
123
  - Wait for the user to tell you which items to address
102
124
  - Always offer an explicit optional follow-up to post rationale replies on selected `SKIPPED` or declined `DISCUSS` items
103
125
  - Never post those rationale replies unless the user explicitly selects which items to reply to
104
- - Ask two things when relevant:
126
+ - Ask two things when there are `SKIPPED` or declined `DISCUSS` items:
105
127
  - Which items to address in code/tests/docs
106
128
  - Which skipped/declined items (if any) should receive a rationale reply
107
129
 
108
130
  ## Step 7: Address Items, Reply, and Resolve
109
131
 
110
- When addressing items, after completing each selected todo item, reply to the original review comment explaining how it was addressed.
132
+ When addressing items, after completing each selected item (whether `MUST-FIX` or `DISCUSS`), reply to the original review comment explaining how it was addressed.
133
+ If the user selects `DISCUSS` items to address, treat them the same as `MUST-FIX`: make the code change, reply, and resolve the thread.
111
134
  If the user selects skipped/declined items for rationale replies, post those replies too.
112
135
 
113
136
  **For issue comments (general PR comments):**
@@ -122,14 +145,16 @@ gh api repos/${REPO}/issues/{PR_NUMBER}/comments -X POST -f body="<response>"
122
145
  gh api repos/${REPO}/pulls/{PR_NUMBER}/comments/{COMMENT_ID}/replies -X POST -f body="<response>"
123
146
  ```
124
147
 
125
- **For standalone review comments (not in a thread):**
148
+ Use the `/replies` endpoint for all existing review comments, including standalone top-level comments.
149
+
150
+ **For review summary bodies (from `/pulls/{PR_NUMBER}/reviews/{REVIEW_ID}`):**
151
+
152
+ Review summary bodies do not have a `comment_id` and cannot be replied to via the `/replies` endpoint. Instead, post a general PR comment referencing the review:
126
153
 
127
154
  ```bash
128
- gh api repos/${REPO}/pulls/{PR_NUMBER}/comments -X POST -f body="<response>" -f commit_id="<COMMIT_SHA>" -f path="<FILE_PATH>" -f line=<LINE_NUMBER> -f side="RIGHT"
155
+ gh api repos/${REPO}/issues/{PR_NUMBER}/comments -X POST -f body="<response>"
129
156
  ```
130
157
 
131
- Note: `side` is required when using `line`. Use `"RIGHT"` for the PR commit side (most common) or `"LEFT"` for the base commit side.
132
-
133
158
  The response should briefly explain:
134
159
 
135
160
  - What was changed
@@ -184,6 +209,8 @@ Which items would you like me to address? (e.g., "1", "1,2", or "all must-fix")
184
209
  Optional: I can also post rationale replies for skipped/declined items (e.g., "reply 3,5" or "reply all skipped").
185
210
  ```
186
211
 
212
+ Note: Only show the "Optional: rationale replies" line when there are `SKIPPED` or declined `DISCUSS` items. Omit it when every item is `MUST-FIX`.
213
+
187
214
  # Important Notes
188
215
 
189
216
  - Automatically detect the repository using `gh repo view` for the current working directory
@@ -204,3 +231,4 @@ Optional: I can also post rationale replies for skipped/declined items (e.g., "r
204
231
 
205
232
  - Rate limiting: GitHub API has rate limits; if you hit them, wait a few minutes
206
233
  - Private repos: Requires appropriate `gh` authentication scope
234
+ - GraphQL inner pagination: The `comments(first:100)` inside each review thread is hardcoded. Threads with >100 comments (rare) will have older comments truncated. The outer `reviewThreads` pagination is handled by `--paginate`.
@@ -0,0 +1,12 @@
1
+ ---
2
+ description: Run the standard project verification loop before pushing.
3
+ ---
4
+
5
+ Run the following checks in order and stop on first failure:
6
+
7
+ 1. `bundle exec rubocop`
8
+ 2. `yarn lint`
9
+ 3. `bundle exec rspec`
10
+ 4. `yarn test --runInBand` (serial mode for reliable pre-push verification)
11
+
12
+ If all checks pass, summarize command outcomes and total runtime.
@@ -0,0 +1,7 @@
1
+ # Coding Style Rules
2
+
3
+ 1. Always end files with a trailing newline.
4
+ 2. Always use `bundle exec` when running Ruby commands.
5
+ 3. Follow existing code conventions in the file you are editing.
6
+ 4. Keep changes focused and minimal; avoid unrelated diffs.
7
+ 5. Do not add unnecessary comments unless requested.
@@ -0,0 +1,6 @@
1
+ # Git Workflow Rules
2
+
3
+ 1. Create feature branches for all changes.
4
+ 2. Never push directly to `main`.
5
+ 3. Keep PRs small and focused.
6
+ 4. Open a PR immediately after pushing branch changes.
@@ -0,0 +1,7 @@
1
+ # Open Source Maintainability Rules
2
+
3
+ 1. Prefer removing complexity over adding new configuration.
4
+ 2. Treat every new option as long-term maintenance surface.
5
+ 3. Favor secure defaults over convenience defaults.
6
+ 4. Keep feature PRs focused; do not refactor adjacent code in the same PR.
7
+ 5. For niche needs, prefer existing extension points over new global options.
@@ -0,0 +1,9 @@
1
+ # Testing Rules
2
+
3
+ 1. Run corresponding specs/tests when changing source files.
4
+ 2. Run `bundle exec rubocop` before committing Ruby changes.
5
+ 3. Run `yarn lint` before committing JavaScript changes.
6
+ 4. Prefer explicit RSpec spy assertions (`have_received`) over indirect counters.
7
+ 5. Validate both webpack and rspack paths when changing core Shakapacker behavior.
8
+ 6. Run `bundle exec rspec` (full suite) before pushing.
9
+ 7. Run `yarn test --runInBand` (JS tests) before pushing.
@@ -30,7 +30,7 @@ jobs:
30
30
  persist-credentials: false
31
31
  - uses: actions/setup-node@v4
32
32
  with:
33
- node-version: "20"
33
+ node-version: "20.x"
34
34
  - uses: ruby/setup-ruby@v1
35
35
  with:
36
36
  ruby-version: "3.2"
@@ -40,7 +40,6 @@ jobs:
40
40
  bundle install
41
41
  yarn install --frozen-lockfile --production=false
42
42
  npm install -g yalc
43
- cd spec/dummy && npm install
44
43
 
45
44
  - name: Build TypeScript
46
45
  run: yarn build
@@ -139,7 +139,8 @@ jobs:
139
139
  cd /tmp/test-types
140
140
  npx tsc --noEmit \
141
141
  --skipLibCheck \
142
- --moduleResolution node \
142
+ --moduleResolution bundler \
143
+ --types node \
143
144
  *.d.ts
144
145
  test:
145
146
  name: Testing
@@ -0,0 +1,24 @@
1
+ name: Trigger docs site rebuild
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ paths: ["docs/**"]
7
+
8
+ jobs:
9
+ notify-docs-site:
10
+ runs-on: ubuntu-latest
11
+ steps:
12
+ - uses: actions/create-github-app-token@v1
13
+ id: app-token
14
+ with:
15
+ app-id: ${{ secrets.DOCS_DISPATCH_APP_ID }}
16
+ private-key: ${{ secrets.DOCS_DISPATCH_APP_KEY }}
17
+ owner: shakacode
18
+ repositories: shakapacker.com
19
+
20
+ - uses: peter-evans/repository-dispatch@v3
21
+ with:
22
+ token: ${{ steps.app-token.outputs.token }}
23
+ repository: shakacode/shakapacker.com
24
+ event-type: docs-updated
data/.gitignore CHANGED
@@ -26,6 +26,9 @@ yalc.lock
26
26
  # Config exporter output directory
27
27
  shakapacker-config-exports/
28
28
 
29
+ # Webpack build output
30
+ public/packs/
31
+
29
32
  # TypeScript generated files
30
33
  package/**/*.d.ts
31
34
  package/**/*.d.ts.map
data/CHANGELOG.md CHANGED
@@ -9,6 +9,27 @@
9
9
 
10
10
  ## [Unreleased]
11
11
 
12
+ ## [v10.0.0-rc.0] - April 1, 2026
13
+
14
+ ### Added
15
+
16
+ - **Added `bin/shakapacker-watch` binstub for clean Ctrl-C shutdown in Procfile-based workflows**. [PR #1026](https://github.com/shakacode/shakapacker/pull/1026) by [justin808](https://github.com/justin808). The new wrapper script traps INT/TERM signals and forwards TERM to the underlying `bin/shakapacker --watch` process, preventing Ruby interrupt backtraces when stopping `bin/dev`. Use `bin/shakapacker-watch --watch` in Procfiles instead of `bin/shakapacker --watch`.
17
+ - **Allowed `webpack-cli` v7 (`^7.0.0`) in peer dependencies**. [PR #1021](https://github.com/shakacode/shakapacker/pull/1021) by [justin808](https://github.com/justin808). Fixes [#1020](https://github.com/shakacode/shakapacker/issues/1020). Note: `webpack-cli` v7 requires Node.js >= 20.9.0.
18
+
19
+ ### ⚠️ Breaking Changes
20
+
21
+ - **Breaking: bumped the minimum `webpack` version to `^5.101.0`**. [PR #1021](https://github.com/shakacode/shakapacker/pull/1021) by [justin808](https://github.com/justin808). The previous minimum was `^5.76.0`.
22
+ - **Breaking: required `webpack-dev-server` `^5.2.2` and dropped support for v4**. [PR #1021](https://github.com/shakacode/shakapacker/pull/1021) by [justin808](https://github.com/justin808). The removed v4 range was `^4.15.2`.
23
+
24
+ ### Changed
25
+
26
+ - **Changed `shakapacker:install` to default `webpack-cli` installs to the latest v6 range**. [PR #1021](https://github.com/shakacode/shakapacker/pull/1021) by [justin808](https://github.com/justin808). This keeps installs compatible with Node.js `20.0-20.8`; v7 remains supported via peer dependencies for Node.js >= 20.9.0.
27
+ - **Changed dev server config handling to warn on deprecated middleware hooks and ignore them for webpack-dev-server v5**. [PR #1021](https://github.com/shakacode/shakapacker/pull/1021) by [justin808](https://github.com/justin808). Use `setup_middlewares` instead of `on_before_setup_middleware` and `on_after_setup_middleware`.
28
+
29
+ ### Fixed
30
+
31
+ - **Ensured `shakapacker:install` installs the latest `compression-webpack-plugin`**. [PR #1035](https://github.com/shakacode/shakapacker/pull/1035) by [G-Rath](https://github.com/G-Rath).
32
+
12
33
  ## [v9.7.0] - March 15, 2026
13
34
 
14
35
  ### Added
@@ -887,7 +908,8 @@ Note: [Rubygem is 6.3.0.pre.rc.1](https://rubygems.org/gems/shakapacker/versions
887
908
 
888
909
  See [CHANGELOG.md in rails/webpacker (up to v5.4.3)](https://github.com/rails/webpacker/blob/master/CHANGELOG.md)
889
910
 
890
- [Unreleased]: https://github.com/shakacode/shakapacker/compare/v9.7.0...main
911
+ [Unreleased]: https://github.com/shakacode/shakapacker/compare/v10.0.0-rc.0...main
912
+ [v10.0.0-rc.0]: https://github.com/shakacode/shakapacker/compare/v9.7.0...v10.0.0-rc.0
891
913
  [v9.7.0]: https://github.com/shakacode/shakapacker/compare/v9.6.1...v9.7.0
892
914
  [v9.6.1]: https://github.com/shakacode/shakapacker/compare/v9.6.0...v9.6.1
893
915
  [v9.6.0]: https://github.com/shakacode/shakapacker/compare/v9.5.0...v9.6.0
data/CLAUDE.md CHANGED
@@ -1,5 +1,16 @@
1
1
  # Shakapacker Project Guidelines
2
2
 
3
+ ## Rules Directory
4
+
5
+ Concise always-on reminders live in `.claude/rules/`:
6
+
7
+ - `.claude/rules/coding-style.md`
8
+ - `.claude/rules/testing.md`
9
+ - `.claude/rules/git-workflow.md`
10
+ - `.claude/rules/open-source.md`
11
+
12
+ See the sections below for full detail and examples.
13
+
3
14
  ## Critical Requirements
4
15
 
5
16
  - **ALWAYS end all files with a trailing newline character.** This is required by the project's linting rules.
@@ -11,7 +22,7 @@
11
22
 
12
23
  - Run corresponding RSpec tests when changing source files
13
24
  - For example, when changing `lib/shakapacker/foo.rb`, run `spec/shakapacker/foo_spec.rb`
14
- - Run the full test suite with `bundle exec rspec` before pushing
25
+ - Run the full test suite with `bundle exec rake test` before pushing
15
26
  - **Use explicit RSpec spy assertions** - prefer `have_received`/`not_to have_received` over indirect counter patterns
16
27
  - Good: `expect(Open3).to have_received(:capture3).with(anything, hook_command, anything)`
17
28
  - Good: `expect(Open3).not_to have_received(:capture3).with(anything, hook_command, anything)`
@@ -37,7 +48,7 @@
37
48
  - **Do NOT add entries for**: linting, formatting, refactoring, tests, or documentation fixes
38
49
  - **Format**: `[PR #123](https://github.com/shakacode/shakapacker/pull/123) by [username](https://github.com/username)` (Shakapacker uses `#` in PR links)
39
50
  - **Use `/update-changelog` command** for guided changelog updates with automatic formatting
40
- - **Version management**: Run `bundle exec rake update_changelog` after releases to update version headers
51
+ - **Version management**: Use the `/update-changelog` command to stamp version headers during release prep
41
52
  - **Examples**: Run `grep -A 3 "^### " CHANGELOG.md | head -30` to see real formatting examples
42
53
 
43
54
  ## Open Source Maintainability
data/CONTRIBUTING.md CHANGED
@@ -8,7 +8,7 @@ Thank you for your interest in contributing to Shakapacker! We welcome all contr
8
8
  - [Submitting Pull Requests](#submitting-pull-requests)
9
9
  - [Setting Up a Development Environment](#setting-up-a-development-environment)
10
10
  - [Making sure your changes pass all tests](#making-sure-your-changes-pass-all-tests)
11
- - [Testing the generator](#testing-the-generator)
11
+ - [Testing the installer](#46-testing-the-installer)
12
12
 
13
13
  ## Reporting Issues
14
14
 
@@ -44,8 +44,8 @@ This project includes configuration for git hooks via `husky` and `lint-staged`,
44
44
  To enable pre-commit hooks locally:
45
45
 
46
46
  ```bash
47
- npx husky install
48
- npx husky add .husky/pre-commit "npx lint-staged"
47
+ yarn install
48
+ npx husky
49
49
  ```
50
50
 
51
51
  ---
@@ -178,7 +178,8 @@ yarn lint --cache
178
178
  ```
179
179
  bundle install
180
180
  yarn install
181
- yarn prepare:husky # Set up pre-commit hooks for linting
181
+ # Optional: enable local pre-commit hooks
182
+ npx husky
182
183
  ```
183
184
 
184
185
  ## Understanding Optional Peer Dependencies
data/README.md CHANGED
@@ -4,6 +4,8 @@
4
4
 
5
5
  _🚀 Shakapacker 9 supports [Rspack](https://rspack.rs/)! 10x faster than webpack!_
6
6
 
7
+ _📖 **Full documentation at [shakapacker.com](https://shakapacker.com)**_
8
+
7
9
  ---
8
10
 
9
11
  _Official, actively maintained successor to [rails/webpacker](https://github.com/rails/webpacker). ShakaCode stands behind the long-term maintenance and development of this project for the Rails community._
@@ -19,7 +21,7 @@ _Official, actively maintained successor to [rails/webpacker](https://github.com
19
21
  [![Rubocop](https://github.com/shakacode/shakapacker/workflows/Rubocop/badge.svg)](https://github.com/shakacode/shakapacker/actions)
20
22
  [![JS lint](https://github.com/shakacode/shakapacker/workflows/JS%20lint/badge.svg)](https://github.com/shakacode/shakapacker/actions)
21
23
 
22
- [![node.js](https://img.shields.io/badge/node-%3E%3D%2012.0.0-brightgreen.svg)](https://www.npmjs.com/package/shakapacker)
24
+ [![node.js](https://img.shields.io/badge/node-%3E%3D%2020-brightgreen.svg)](https://www.npmjs.com/package/shakapacker)
23
25
  [![Gem](https://img.shields.io/gem/v/shakapacker.svg)](https://rubygems.org/gems/shakapacker)
24
26
  [![npm version](https://badge.fury.io/js/shakapacker.svg)](https://badge.fury.io/js/shakapacker)
25
27
 
@@ -57,6 +59,20 @@ Here's a testimonial of how ShakaCode can help from [Florian Gößler](https://g
57
59
 
58
60
  Read the [full review here](https://clutch.co/profile/shakacode#reviews?sort_by=date_DESC#review-2118154).
59
61
 
62
+ Here's a testimonial from Jon Rajavuori of [Academia.edu](https://www.academia.edu/) about migrating frontend builds from Webpack to [rspack](https://rspack.rs/) with ShakaCode's help, shared in March 2026:
63
+
64
+ > We've been running [rspack](https://rspack.rs/) most of the week now for frontend builds! It's a performance-focused drop-in replacement for Webpack that apparently works as advertised. The impact has been between a **2-4x build speed increase** depending on the environment and conditions.
65
+ >
66
+ > The typical case of first startup with a warm cache has gone from roughly 1m with Webpack down to about **20s** — close to the amount of time other dev components take to startup.
67
+ >
68
+ > As for production **incremental** builds, they now take around 10s when only a few lines in one bundle have changed!
69
+ >
70
+ > Additional stats from follow-up conversation with Jon:
71
+ >
72
+ > - Cold-cache startup: **4m30s → 3m30s** (~22% faster; 2-4x gains apply to warm-cache and incremental builds)
73
+ > - Production incremental builds: **~10 seconds**
74
+ > - HMR rebuild time: unchanged at ~8s (bottleneck is orchestration, not compilation)
75
+
60
76
  ---
61
77
 
62
78
  <!-- START doctoc generated TOC please keep comment here to allow auto update -->
@@ -78,7 +94,7 @@ Read the [full review here](https://clutch.co/profile/shakacode#reviews?sort_by=
78
94
  - [View Helper: `image_pack_tag`](#view-helper-image_pack_tag)
79
95
  - [View Helper: `favicon_pack_tag`](#view-helper-favicon_pack_tag)
80
96
  - [View Helper: `preload_pack_asset`](#view-helper-preload_pack_asset)
81
- - [View Helper: `send_pack_early_hints`](#view-helper-send_pack_early_hints)
97
+ - [HTTP 103 Early Hints](#http-103-early-hints)
82
98
  - [Images in Stylesheets](#images-in-stylesheets)
83
99
  - [Server-Side Rendering (SSR)](#server-side-rendering-ssr)
84
100
  - [Development](#development)
@@ -117,7 +133,7 @@ Read the [full review here](https://clutch.co/profile/shakacode#reviews?sort_by=
117
133
 
118
134
  - Ruby 2.7+
119
135
  - Rails 5.2+
120
- - Node.js 14+
136
+ - Node.js 20+
121
137
 
122
138
  ## Features
123
139
 
@@ -191,24 +207,16 @@ If you wish to use [Yarn PnP](https://yarnpkg.com/features/pnp) you will need to
191
207
  > a particular package manager requires a very different command; otherwise it should be safe to just replace `npm` with the name of your
192
208
  > preferred package manager when running the command
193
209
 
194
- Note, in v6+, most JS packages are peer dependencies. Thus, the installer will add the packages:
195
-
196
- - `@babel/core`
197
- - `@babel/plugin-transform-runtime`
198
- - `@babel/preset-env`
199
- - `@babel/runtime`
200
- - `babel-loader`
201
- - `compression-webpack-plugin`
202
- - `terser-webpack-plugin`
203
- - `webpack`
204
- - `webpack-assets-manifest`
205
- - `webpack-cli`
206
- - `webpack-merge`
207
- - `webpack-sources`
208
- - `webpack-dev-server`
209
-
210
- Previously, these "webpack" and "babel" packages were direct dependencies for `shakapacker`. By
211
- making these peer dependencies, you have control over the versions used in your webpack and babel configs.
210
+ Note, in v6+, most JS packages are peer dependencies. During `shakapacker:install`, Shakapacker
211
+ adds the subset required for your chosen bundler/transpiler setup rather than forcing every
212
+ supported package into every app.
213
+
214
+ See:
215
+
216
+ - [Optional Peer Dependencies](./docs/optional-peer-dependencies.md) for how optional peers work
217
+ - [Shakapacker's Peer Dependencies](./docs/peer-dependencies.md) for the current supported version ranges
218
+
219
+ This keeps installation flexible while still making the supported dependency ranges explicit.
212
220
 
213
221
  ### Optional Peer Dependencies
214
222
 
@@ -238,14 +246,16 @@ Depending on your setup, you'll need different subsets of the optional peer depe
238
246
  "babel-loader": "^8.2.4",
239
247
  "compression-webpack-plugin": "^9.0.0",
240
248
  "terser-webpack-plugin": "^5.3.1",
241
- "webpack": "^5.76.0",
249
+ "webpack": "^5.101.0",
242
250
  "webpack-assets-manifest": "^5.0.6",
243
- "webpack-cli": "^5.0.0",
244
- "webpack-dev-server": "^5.0.0"
251
+ "webpack-cli": "^6.0.0",
252
+ "webpack-dev-server": "^5.2.2"
245
253
  }
246
254
  }
247
255
  ```
248
256
 
257
+ > **Note:** `webpack-cli` v7 is also supported but requires Node.js >= 20.9.0. If you're on Node >= 20.9.0, you can use `"webpack-cli": "^7.0.0"` instead. See [peer-dependencies.md](./docs/peer-dependencies.md) for the full supported range.
258
+
249
259
  **For Webpack + SWC (faster alternative):**
250
260
 
251
261
  ```json
@@ -256,10 +266,10 @@ Depending on your setup, you'll need different subsets of the optional peer depe
256
266
  "swc-loader": "^0.2.0",
257
267
  "compression-webpack-plugin": "^9.0.0",
258
268
  "terser-webpack-plugin": "^5.3.1",
259
- "webpack": "^5.76.0",
269
+ "webpack": "^5.101.0",
260
270
  "webpack-assets-manifest": "^5.0.6",
261
- "webpack-cli": "^5.0.0",
262
- "webpack-dev-server": "^5.0.0"
271
+ "webpack-cli": "^6.0.0",
272
+ "webpack-dev-server": "^5.2.2"
263
273
  }
264
274
  }
265
275
  ```
@@ -607,7 +617,7 @@ Note, if you are using server-side rendering of JavaScript with dynamic code-spl
607
617
 
608
618
  ### Development
609
619
 
610
- Shakapacker ships with two binstubs: `./bin/shakapacker` and `./bin/shakapacker-dev-server`. Both are thin wrappers around the standard `webpack.js` and `webpack-dev-server.js` executables to ensure that the right configuration files and environmental variables are loaded based on your environment.
620
+ Shakapacker ships with three binstubs: `./bin/shakapacker`, `./bin/shakapacker-dev-server`, and `./bin/shakapacker-watch`. The first two are thin wrappers around the standard `webpack.js` and `webpack-dev-server.js` executables to ensure that the right configuration files and environmental variables are loaded based on your environment. `./bin/shakapacker-watch` is a shell wrapper around `./bin/shakapacker` that traps INT/TERM signals for clean shutdown — use it in Procfile-based workflows (e.g., `foreman`, `bin/dev`) to avoid Ruby interrupt backtraces when pressing Ctrl-C.
611
621
 
612
622
  _Note: older Shakapacker installations had set a missing NODE_ENV in the binstubs. Please remove this for versions 6.5.2 and newer._
613
623
 
@@ -642,7 +652,10 @@ If you want to use live code reloading, or you have enough JavaScript that on-de
642
652
  # webpack dev server
643
653
  ./bin/shakapacker-dev-server
644
654
 
645
- # watcher
655
+ # watcher (use in Procfiles for clean Ctrl-C shutdown)
656
+ ./bin/shakapacker-watch --watch --progress
657
+
658
+ # watcher (standalone, without signal handling)
646
659
  ./bin/shakapacker --watch --progress
647
660
 
648
661
  # standalone build
@@ -962,15 +975,22 @@ See also [Customizing Babel Config](./docs/customizing_babel_config.md) for an e
962
975
  **📚 TypeScript Support:** See the **[TypeScript Documentation](./docs/typescript.md)** for type-safe configuration.
963
976
 
964
977
  ```bash
965
- npm install typescript @babel/preset-typescript
978
+ npm install --save-dev typescript
979
+
980
+ # If you explicitly use `javascript_transpiler: babel`
981
+ npm install --save-dev @babel/preset-typescript
966
982
  ```
967
983
 
968
- Babel won't perform any type-checking on TypeScript code. To optionally use type-checking run:
984
+ Shakapacker does not type-check TypeScript during builds. For webpack projects, you can optionally
985
+ add type-checking during builds with:
969
986
 
970
987
  ```bash
971
- npm install fork-ts-checker-webpack-plugin
988
+ npm install --save-dev fork-ts-checker-webpack-plugin
972
989
  ```
973
990
 
991
+ You can also run `tsc --noEmit` separately in CI or local development if you prefer not to wire
992
+ type-checking into the bundler.
993
+
974
994
  Add tsconfig.json
975
995
 
976
996
  ```json