Skip to content

Commit 2f1d3d2

Browse files
justin808claude
andcommitted
Address fourth-round PR review feedback on Phase 1 packages
Addressed review feedback from PR #1096 (rounds 4): - shakapacker-webpack peer: webpack-assets-manifest widened to ^5.0.6 || ^6.0.0 to match the core peer dep range and preserve the additive v10.1 install path for users already on webpack-assets-manifest@6. - Root shakapacker peer: webpack-cli widened to add ^7.0.0, matching the supplemental package and the RFC's "current state" description. - packages/shakapacker-rspack/index.js and packages/shakapacker-webpack/index.js now carry a brief comment explaining that the re-export targets a compiled path produced by `yarn build` (built via prepublishOnly for releases) and what to do for local monorepo development. - RFC: bumped v11 Ruby floor from 3.3.0 to 3.4.0 with rationale about Ruby 3.3 EOL (2027-03-31) leaving little headroom for a v11 release. - RFC release process: added an explicit callout that core 10.1.0 must be published before either supplemental, plus a note explaining why we use npm for publishing despite the project pinning Yarn 1 for development. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 852a136 commit 2f1d3d2

5 files changed

Lines changed: 102 additions & 78 deletions

File tree

docs/rfcs/0001-tighten-dependencies-v11.md

Lines changed: 90 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ This is rolled out in two phases:
2424
Shakapacker v10 has **23 optional peer dependencies** with extremely broad version ranges:
2525

2626
- `esbuild`: 14 separate version ranges (`^0.14.0 || ^0.15.0 || ... || ^0.27.0`)
27-
- `webpack-cli`: 3 major versions (`^4.9.2 || ^5.0.0 || ^6.0.0`)
27+
- `webpack-cli`: 4 major versions (`^4.9.2 || ^5.0.0 || ^6.0.0 || ^7.0.0`)
2828
- `sass-loader`: 4 major versions (`^13.0.0 || ^14.0.0 || ^15.0.0 || ^16.0.0`)
2929
- `babel-loader`: 3 major versions (`^8.2.4 || ^9.0.0 || ^10.0.0`)
3030

@@ -50,13 +50,14 @@ This creates:
5050

5151
### Phase 1: v10.1.0 (Non-Breaking, Additive)
5252

53-
Restructure the repo and publish the two supplemental packages. **No changes to the core `shakapacker` package's peer deps.** Existing users are unaffected.
53+
Add the two supplemental packages. **No changes to the core `shakapacker` package's peer deps.** Existing users are unaffected.
5454

5555
What ships:
56-
- Add `"workspaces": ["packages/*"]` to root `package.json`
56+
5757
- Create `packages/shakapacker-webpack/` and `packages/shakapacker-rspack/`
5858
- Core `package/` directory stays in place (NOT moved to `packages/shakapacker/`)
59-
- Publish supplemental packages at v10.1.0
59+
- Do not enable root `workspaces` yet: the root `package.json` is also the publishable `shakapacker` package, and Yarn Classic requires workspace roots to be `private: true`
60+
- Publish core `shakapacker` 10.1.0 first, then publish supplemental packages at v10.1.0 so their core peer deps resolve
6061
- Update docs and installer to recommend the new pattern for new projects
6162
- Core `shakapacker` still declares all existing peer deps (nothing removed)
6263

@@ -69,11 +70,12 @@ This gives the supplemental packages real-world usage before they become the req
6970
Remove bundler-specific peer deps from core `shakapacker`. Tighten version ranges. Drop EOL runtimes.
7071

7172
What ships:
73+
7274
- Core `shakapacker` no longer declares webpack/rspack peer deps
7375
- Users must install `shakapacker-webpack` or `shakapacker-rspack`
7476
- Drop old major versions (webpack-cli v4/v5, sass-loader v13-15, etc.)
7577
- Collapse esbuild from 14 ranges to `^0.24.0`
76-
- Ruby 3.3+, Rails 7.2+ (Ruby 3.1/3.2 are EOL; Rails 7.0/7.1 are unsupported)
78+
- Ruby 3.4+, Rails 7.2+ (Ruby 3.1/3.2 are EOL; Ruby 3.3 reaches EOL 2027-03; Rails 7.0/7.1 are unsupported)
7779

7880
### Three npm Packages
7981

@@ -92,24 +94,24 @@ The base package that all users install. Contains:
9294

9395
**Dependencies (v10.1.0 — no change from today):**
9496

95-
| Package | Version | Type |
96-
|---------|---------|------|
97-
| js-yaml | `^4.1.0` | dependency |
98-
| path-complete-extname | `^1.0.0` | dependency |
99-
| webpack-merge | `^5.8.0` | dependency |
100-
| yargs | `^17.7.2` | dependency |
97+
| Package | Version | Type |
98+
| --------------------- | ----------- | ----------------- |
99+
| js-yaml | `^4.1.0` | dependency |
100+
| path-complete-extname | `^1.0.0` | dependency |
101+
| webpack-merge | `^5.8.0` | dependency |
102+
| yargs | `^17.7.2` | dependency |
101103
| All current peer deps | (unchanged) | optional peer dep |
102104

103105
**Dependencies (v11.0.0 — stripped down):**
104106

105-
| Package | Version | Type |
106-
|---------|---------|------|
107-
| js-yaml | `^4.1.0` | dependency |
108-
| path-complete-extname | `^1.0.0` | dependency |
109-
| webpack-merge | `^5.8.0` | dependency |
110-
| yargs | `^17.7.2` | dependency |
111-
| @types/webpack | `^5.0.0` | optional peer dep |
112-
| @types/babel__core | `^7.0.0` | optional peer dep |
107+
| Package | Version | Type |
108+
| --------------------- | --------- | ----------------- |
109+
| js-yaml | `^4.1.0` | dependency |
110+
| path-complete-extname | `^1.0.0` | dependency |
111+
| webpack-merge | `^5.8.0` | dependency |
112+
| yargs | `^17.7.2` | dependency |
113+
| @types/webpack | `^5.0.0` | optional peer dep |
114+
| @types/babel\_\_core | `^7.0.0` | optional peer dep |
113115

114116
**No bundler or transpiler peer deps in v11.** This package works standalone for custom build users.
115117

@@ -121,40 +123,40 @@ Supplemental package for the standard webpack managed build experience.
121123

122124
**Peer dependencies (required):**
123125

124-
| Package | Version |
125-
|---------|---------|
126-
| shakapacker | `^10.1.0` |
127-
| webpack | `^5.76.0` |
128-
| webpack-cli | `^6.0.0` |
129-
| webpack-assets-manifest | `^5.0.6` |
126+
| Package | Version |
127+
| ----------------------- | -------------------- |
128+
| shakapacker | `^10.1.0` |
129+
| webpack | `^5.76.0` |
130+
| webpack-cli | `^6.0.0 \|\| ^7.0.0` |
131+
| webpack-assets-manifest | `^5.0.6 \|\| ^6.0.0` |
130132

131133
**Peer dependencies (optional):**
132134

133-
| Package | Version | When needed |
134-
|---------|---------|-------------|
135-
| webpack-dev-server | `^5.2.0` | Dev mode with HMR |
136-
| mini-css-extract-plugin | `^2.0.0` | CSS extraction |
137-
| terser-webpack-plugin | `^5.3.1` | Production minification |
138-
| webpack-subresource-integrity | `^5.1.0` | SRI hashes |
139-
| @pmmmwh/react-refresh-webpack-plugin | `^0.5.0` | React HMR |
135+
| Package | Version | When needed |
136+
| ------------------------------------ | -------- | ----------------------- |
137+
| webpack-dev-server | `^5.2.0` | Dev mode with HMR |
138+
| mini-css-extract-plugin | `^2.0.0` | CSS extraction |
139+
| terser-webpack-plugin | `^5.3.1` | Production minification |
140+
| webpack-subresource-integrity | `^5.1.0` | SRI hashes |
141+
| @pmmmwh/react-refresh-webpack-plugin | `^0.5.0` | React HMR |
140142

141143
**Peer dependencies (optional — transpiler, pick one):**
142144

143-
| Package | Version | When needed |
144-
|---------|---------|-------------|
145-
| @swc/core | `^1.3.0` | `javascript_transpiler: "swc"` (default) |
146-
| swc-loader | `^0.1.15 || ^0.2.0` | Paired with @swc/core |
147-
| @babel/core | `^7.17.9` | `javascript_transpiler: "babel"` |
148-
| babel-loader | `^9.0.0` | Paired with @babel/core |
149-
| esbuild | `^0.24.0` | `javascript_transpiler: "esbuild"` |
150-
| esbuild-loader | `^4.0.0` | Paired with esbuild |
145+
| Package | Version | When needed |
146+
| -------------- | --------------------- | ---------------------------------------- |
147+
| @swc/core | `^1.3.0` | `javascript_transpiler: "swc"` (default) |
148+
| swc-loader | `^0.1.15 \|\| ^0.2.0` | Paired with @swc/core |
149+
| @babel/core | `^7.17.9` | `javascript_transpiler: "babel"` |
150+
| babel-loader | `^9.0.0` | Paired with @babel/core |
151+
| esbuild | `^0.24.0` | `javascript_transpiler: "esbuild"` |
152+
| esbuild-loader | `^4.0.0` | Paired with esbuild |
151153

152154
**Peer dependencies (optional — CSS preprocessors):**
153155

154-
| Package | Version | When needed |
155-
|---------|---------|-------------|
156-
| css-loader | `^7.0.0` | CSS processing |
157-
| sass | `^1.50.0` | SCSS/Sass files |
156+
| Package | Version | When needed |
157+
| ----------- | --------- | ---------------- |
158+
| css-loader | `^7.0.0` | CSS processing |
159+
| sass | `^1.50.0` | SCSS/Sass files |
158160
| sass-loader | `^16.0.0` | Paired with sass |
159161

160162
#### `shakapacker-rspack` (managed rspack build)
@@ -163,21 +165,21 @@ Supplemental package for the rspack managed build experience.
163165

164166
**Peer dependencies (required):**
165167

166-
| Package | Version |
167-
|---------|---------|
168-
| shakapacker | `^10.1.0` |
169-
| @rspack/core | `^1.0.0 || ^2.0.0-0` |
170-
| @rspack/cli | `^1.0.0 || ^2.0.0-0` |
171-
| rspack-manifest-plugin | `^5.0.0` |
168+
| Package | Version |
169+
| ---------------------- | ---------------------- |
170+
| shakapacker | `^10.1.0` |
171+
| @rspack/core | `^1.0.0 \|\| ^2.0.0-0` |
172+
| @rspack/cli | `^1.0.0 \|\| ^2.0.0-0` |
173+
| rspack-manifest-plugin | `^5.0.0` |
172174

173175
**Peer dependencies (optional):**
174176

175-
| Package | Version | When needed |
176-
|---------|---------|-------------|
177-
| @rspack/plugin-react-refresh | `^1.0.0` | React HMR |
178-
| css-loader | `^7.0.0` | CSS processing |
179-
| sass | `^1.50.0` | SCSS/Sass files |
180-
| sass-loader | `^16.0.0` | Paired with sass |
177+
| Package | Version | When needed |
178+
| ---------------------------- | --------- | ---------------- |
179+
| @rspack/plugin-react-refresh | `^1.0.0` | React HMR |
180+
| css-loader | `^7.0.0` | CSS processing |
181+
| sass | `^1.50.0` | SCSS/Sass files |
182+
| sass-loader | `^16.0.0` | Paired with sass |
181183

182184
Note: rspack has built-in SWC transpilation, so no external transpiler deps are needed.
183185

@@ -199,8 +201,8 @@ Following [G-Rath's feedback](https://github.com/shakacode/shakapacker/issues/10
199201
"shakapacker": "^11.0.0",
200202
"shakapacker-webpack": "^11.0.0",
201203
"webpack": "^5.76.0",
202-
"webpack-cli": "^6.0.0",
203-
"webpack-assets-manifest": "^5.0.6",
204+
"webpack-cli": "^6.0.0 || ^7.0.0",
205+
"webpack-assets-manifest": "^5.0.6 || ^6.0.0",
204206
"webpack-dev-server": "^5.2.0",
205207
"@swc/core": "^1.3.0",
206208
"swc-loader": "^0.2.0",
@@ -256,7 +258,7 @@ shakapacker/
256258
├── spec/ # Ruby specs
257259
├── test/ # JS tests
258260
├── shakapacker.gemspec
259-
└── package.json # workspace root + core package
261+
└── package.json # core npm package
260262
```
261263

262264
**Phase 2 (v11.0.0) — core moves into packages/:**
@@ -304,7 +306,7 @@ All three npm packages share the same version number, always. The Ruby gem versi
304306
1. **Same version, always.** When any package is released, all three are released at the same version. If a release only changes core, the supplemental packages still get the version bump.
305307
2. **Caret peer dep on core.** `shakapacker-webpack` and `shakapacker-rspack` declare `"shakapacker": "^10.1.0"` as a peer dep. This means minor bumps don't force users to update all packages on the same day, but they stay within the same major.
306308
3. **Start at v10.1.0.** All three packages begin at the same version. No separate versioning at any point.
307-
4. **Use npm workspaces** for the monorepo. The root `package.json` declares workspaces, and a single `npm version` + publish script bumps all three.
309+
4. **Defer workspace tooling until the root can be private.** During Phase 1, the root `package.json` remains the publishable core package, so root workspaces are not enabled under Yarn Classic.
308310

309311
**Why lockstep:**
310312

@@ -313,28 +315,38 @@ All three npm packages share the same version number, always. The Ruby gem versi
313315
- Users see `"shakapacker": "^10.2.0"` and `"shakapacker-webpack": "^10.2.0"` — easy to reason about compatibility.
314316
- "Empty bumps" (a supplemental package gets a version bump with no code change) are a tiny cost compared to the coordination headache of independent versions.
315317

316-
**Release process:**
318+
**Initial v10.1.0 release process:**
319+
320+
> **Sequencing is load-bearing.** Both supplemental packages declare `"shakapacker": "^10.1.0"` as a required peer dep. Core `shakapacker` 10.1.0 must be published _before_ either supplemental, otherwise installers receive an unresolvable peer dependency error.
317321
318322
```bash
319-
# Bump all three packages to the same version (root + supplemental)
320-
npm version minor --workspaces --include-workspace-root # or patch, or major
323+
# Bump the existing root package from 10.0.0 to 10.1.0.
324+
npm version 10.1.0 --no-git-tag-version
321325

322-
# Publish all three
323-
npm publish --workspaces --include-workspace-root
326+
# Publish core first so supplemental peer deps resolve.
327+
npm publish
328+
329+
# Publish supplemental packages, already versioned 10.1.0.
330+
(cd packages/shakapacker-webpack && npm publish)
331+
(cd packages/shakapacker-rspack && npm publish)
324332

325333
# Ruby gem is released separately via existing rake task
326334
bundle exec rake release
327335
```
328336

337+
> **Why npm for publishing despite Yarn 1 for development.** The project pins `packageManager: yarn@1.22.22` and uses Yarn for all development scripts, but Yarn Classic does not have a workspace-aware publish command (and `yarn workspaces version` is not available in v1). We invoke `npm publish` per package directly until v11 picks a dedicated release tool — see Open Question #5.
338+
339+
For later Phase 1 releases, bump all three package manifests to the same version in one release commit before publishing. A dedicated workspace or release tool remains an open question for v11, when the core package can move under `packages/shakapacker/` and the repository root can become private.
340+
329341
The existing `bundle exec rake update_changelog` task should be updated to handle the monorepo structure, noting which packages were affected in each release.
330342

331343
### Ruby gemspec (v11.0.0)
332344

333-
| Dependency | Current | v11 Proposed | Reason |
334-
|------------|---------|-------------|--------|
335-
| `required_ruby_version` | `>= 2.7.0` | `>= 3.3.0` | Ruby 3.1 (EOL 2025-03-26) and 3.2 (EOL 2026-04-01) are EOL |
336-
| `activesupport` | `>= 5.2` | `>= 7.2` | Rails 7.0/7.1 are unsupported (only 7.2.x, 8.0.x, 8.1.x receive security fixes) |
337-
| `railties` | `>= 5.2` | `>= 7.2` | Match activesupport |
345+
| Dependency | Current | v11 Proposed | Reason |
346+
| ----------------------- | ---------- | ------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
347+
| `required_ruby_version` | `>= 2.7.0` | `>= 3.4.0` | Ruby 3.1 (EOL 2025-03-26) and 3.2 (EOL 2026-04-01) are EOL; Ruby 3.3 (EOL 2027-03-31) leaves little headroom for v11. Ruby 3.4 (EOL ~2027-12) gives v11 a longer active-support window. |
348+
| `activesupport` | `>= 5.2` | `>= 7.2` | Rails 7.0/7.1 are unsupported (only 7.2.x, 8.0.x, 8.1.x receive security fixes) |
349+
| `railties` | `>= 5.2` | `>= 7.2` | Match activesupport |
338350

339351
### Node.js engines
340352

@@ -356,6 +368,7 @@ The `shakapacker:install` rake task should be updated to:
356368
Existing users: nothing changes. Your current `package.json` continues to work.
357369

358370
New projects or early adopters:
371+
359372
1. Add `shakapacker-webpack` or `shakapacker-rspack` to devDependencies
360373
2. Both the old pattern (peer deps on core) and new pattern (supplemental package) work simultaneously
361374

@@ -365,7 +378,7 @@ New projects or early adopters:
365378

366379
1. Update `shakapacker` gem and npm package to v11
367380
2. Add `shakapacker-webpack` to devDependencies (if not already from v10.1)
368-
3. Update any stale dependencies to current majors (e.g., `webpack-cli` to v6)
381+
3. Update any stale dependencies to current majors (e.g., `webpack-cli` to v6 or v7)
369382
4. Remove `compression-webpack-plugin` if unused (no longer a peer dep)
370383

371384
#### For Rspack Users
@@ -385,6 +398,7 @@ New projects or early adopters:
385398
#### For Babel Users
386399

387400
Babel is no longer the default and hasn't been since v8. In v11:
401+
388402
- Babel still works, but only `babel-loader` v9+ is supported
389403
- Consider migrating to SWC (`javascript_transpiler: "swc"`) for faster builds
390404
- The transpiler migration guide already exists at `docs/transpiler-migration.md`
@@ -394,6 +408,7 @@ Babel is no longer the default and hasn't been since v8. In v11:
394408
### Single package with all optional peer deps (current approach)
395409

396410
The status quo. Rejected because:
411+
397412
- `package.json` cannot express "required if you chose webpack" — deps are either optional or required for everyone
398413
- 23 optional peer deps provide no guardrails for new users
399414
- Silenced warnings (`peerDependenciesMeta: optional`) don't help users make correct choices
@@ -405,13 +420,15 @@ Rejected because it would force webpack dependencies on rspack users and vice ve
405420
### Bundle webpack/rspack as a regular dependency (Next.js model)
406421

407422
Rejected because:
423+
408424
- Shakapacker supports **both** webpack and rspack — we can't bundle both
409425
- Users need direct access to webpack/rspack for custom config files
410426
- Vendoring would make it harder for users to apply webpack security patches independently
411427

412428
### Separate repos for supplemental packages
413429

414430
Rejected because:
431+
415432
- Core changes almost always affect both supplemental packages — separate repos mean cross-repo PRs for routine changes
416433
- Testing a core change against both supplemental packages requires coordination across repos
417434
- More CI pipelines to maintain, more places for things to drift out of sync
@@ -421,13 +438,15 @@ Rejected because:
421438
### Full monorepo split (separate gem per bundler)
422439

423440
Rejected because:
441+
424442
- The Ruby gem logic is shared across both bundlers
425443
- Would double our release/maintenance burden on the gem side
426444
- The npm-only split achieves the same dependency isolation without touching the gem
427445

428446
### Big bang v11 (no phased rollout)
429447

430448
Rejected because:
449+
431450
- v10 just shipped — bumping to v11 immediately feels rushed
432451
- Phased rollout lets supplemental packages get real-world usage before they become required
433452
- v10.1 is zero-risk for existing users

package.json

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@
118118
"terser-webpack-plugin": "^5.3.1",
119119
"webpack": "^5.76.0",
120120
"webpack-assets-manifest": "^5.0.6 || ^6.0.0",
121-
"webpack-cli": "^4.9.2 || ^5.0.0 || ^6.0.0",
121+
"webpack-cli": "^4.9.2 || ^5.0.0 || ^6.0.0 || ^7.0.0",
122122
"webpack-dev-server": "^4.15.2 || ^5.2.2",
123123
"webpack-subresource-integrity": "^5.1.0"
124124
},
@@ -223,8 +223,5 @@
223223
},
224224
"publishConfig": {
225225
"access": "public"
226-
},
227-
"workspaces": [
228-
"packages/*"
229-
]
226+
}
230227
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,5 @@
1+
// This thin re-export targets `shakapacker/rspack`, which resolves to the
2+
// compiled `package/rspack/index.js`. In a published install this is built by
3+
// `prepublishOnly`; for local monorepo development run `yarn build` in the
4+
// repository root before consuming this package against the source tree.
15
module.exports = require("shakapacker/rspack")
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,5 @@
1+
// This thin re-export forwards to the core `shakapacker` package. The value
2+
// is in this package's tighter peer-dependency declarations, not the runtime
3+
// surface; see packages/shakapacker-webpack/package.json. For local monorepo
4+
// development run `yarn build` in the repository root first.
15
module.exports = require("shakapacker")

packages/shakapacker-webpack/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@
1919
"peerDependencies": {
2020
"shakapacker": "^10.1.0",
2121
"webpack": "^5.76.0",
22-
"webpack-cli": "^6.0.0",
23-
"webpack-assets-manifest": "^5.0.6",
22+
"webpack-cli": "^6.0.0 || ^7.0.0",
23+
"webpack-assets-manifest": "^5.0.6 || ^6.0.0",
2424
"webpack-dev-server": "^5.2.0",
2525
"mini-css-extract-plugin": "^2.0.0",
2626
"terser-webpack-plugin": "^5.3.1",

0 commit comments

Comments
 (0)