shakapacker 9.0.0.beta.5 → 9.0.0.beta.6

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c4e7529c9a1e2dee69667d688581f6c684c775c18a17ac527a3328876d45c523
4
- data.tar.gz: 305d71e3efd30913c856066b7195ff259094bafb2cc2f7fa7f1730cdbfc49cdf
3
+ metadata.gz: 65a49f86249eeb2035e56d7f21da2d8e4edbe5a26da50b0a63a9534a720a84cf
4
+ data.tar.gz: 153cb1df867355c881a3a7fe31b3aed526355ff30f7eaaacb497d231cb5f3bcc
5
5
  SHA512:
6
- metadata.gz: cdba0281b3a0bc4e43d50ac4e84fa1a9b029ff6999afeabea56eada8ffded1c366e4b084734758566f009c1214ac36d7da874ea4887c70010551330f678bccbc
7
- data.tar.gz: 97a96fa177348c19929aae4fe53865f9f738f21c060e77863dfd79c3cc22869c4a6eb78af34d2139eb842baf61f59b3a9040b1e42cec3ed2fa216d1818124ca1
6
+ metadata.gz: c237ee4221a14f19ae86067632ad00baaf1f05d3464c21804b8aa3fa7029429bc8d678d630f1762f940ea780f4ff81023c26d26342aa27380a461f1485f50b3d
7
+ data.tar.gz: b37633ed02a416c423bfb410b189b1ca7c508a162339e9def8401622c2ac198b4649ad0392795a9eb3301d6fc3d9858c2e39f1130b8c6bbd219887566126b91e
data/.eslintignore CHANGED
@@ -2,3 +2,4 @@ lib/*
2
2
  node_modules/*
3
3
  vendor/*
4
4
  spec/*
5
+ package/*
@@ -50,5 +50,5 @@ jobs:
50
50
 
51
51
  # See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
52
52
  # or https://docs.claude.com/en/docs/claude-code/sdk#command-line for available options
53
- claude_args: '--allowed-tools "Bash(gh issue view:*),Bash(gh search:*),Bash(gh issue list:*),Bash(gh pr comment:*),Bash(gh pr diff:*),Bash(gh pr view:*),Bash(gh pr list:*)"'
53
+ claude_args: '--model claude-sonnet-4-5-20250929 --allowed-tools "Bash(gh issue view:*),Bash(gh search:*),Bash(gh issue list:*),Bash(gh pr comment:*),Bash(gh pr diff:*),Bash(gh pr view:*),Bash(gh pr list:*)"'
54
54
 
@@ -27,8 +27,8 @@ jobs:
27
27
  uses: actions/setup-node@v4
28
28
  with:
29
29
  node-version: '20'
30
- cache: 'npm'
31
- cache-dependency-path: spec/dummy/package-lock.json
30
+ cache: 'yarn'
31
+ cache-dependency-path: spec/dummy/yarn.lock
32
32
 
33
33
  - name: Install yalc
34
34
  run: npm install -g yalc
@@ -47,7 +47,7 @@ jobs:
47
47
  - name: Install dependencies
48
48
  run: |
49
49
  yalc link shakapacker
50
- npm ci
50
+ yarn install
51
51
 
52
52
  - name: Switch to Webpack
53
53
  run: bin/test-bundler webpack
@@ -80,8 +80,8 @@ jobs:
80
80
  uses: actions/setup-node@v4
81
81
  with:
82
82
  node-version: '20'
83
- cache: 'npm'
84
- cache-dependency-path: spec/dummy/package-lock.json
83
+ cache: 'yarn'
84
+ cache-dependency-path: spec/dummy/yarn.lock
85
85
 
86
86
  - name: Install yalc
87
87
  run: npm install -g yalc
@@ -100,7 +100,7 @@ jobs:
100
100
  - name: Install dependencies
101
101
  run: |
102
102
  yalc link shakapacker
103
- npm ci
103
+ yarn install
104
104
 
105
105
  - name: Switch to RSpack
106
106
  run: bin/test-bundler rspack
@@ -133,8 +133,8 @@ jobs:
133
133
  uses: actions/setup-node@v4
134
134
  with:
135
135
  node-version: '20'
136
- cache: 'npm'
137
- cache-dependency-path: spec/dummy/package-lock.json
136
+ cache: 'yarn'
137
+ cache-dependency-path: spec/dummy/yarn.lock
138
138
 
139
139
  - name: Install yalc
140
140
  run: npm install -g yalc
@@ -153,7 +153,7 @@ jobs:
153
153
  - name: Install dependencies
154
154
  run: |
155
155
  yalc link shakapacker
156
- npm ci
156
+ yarn install
157
157
 
158
158
  - name: Test switching between bundlers
159
159
  run: |
data/CONTRIBUTING.md CHANGED
@@ -50,6 +50,34 @@ We welcome pull requests that fix bugs, add new features, or improve existing on
50
50
  yarn install
51
51
  ```
52
52
 
53
+ ## Understanding Optional Peer Dependencies
54
+
55
+ Shakapacker uses optional peer dependencies (via `peerDependenciesMeta`) for maximum flexibility:
56
+
57
+ - **All peer dependencies are optional** - Users only install what they need
58
+ - **No installation warnings** - Package managers won't warn about missing optional dependencies
59
+ - **Version constraints still apply** - When a package is installed, version compatibility is enforced
60
+
61
+ ### When modifying dependencies:
62
+ 1. Add new peer dependencies to both `peerDependencies` and `peerDependenciesMeta` (marking as optional)
63
+ 2. Keep version ranges synchronized between `devDependencies` and `peerDependencies`
64
+ 3. Test with multiple package managers: `npm`, `yarn`, and `pnpm`
65
+
66
+ ### Testing peer dependency changes:
67
+ ```bash
68
+ # Test with npm (no warnings expected)
69
+ cd /tmp && mkdir test-npm && cd test-npm
70
+ npm init -y && npm install /path/to/shakapacker
71
+
72
+ # Test with yarn (no warnings expected)
73
+ cd /tmp && mkdir test-yarn && cd test-yarn
74
+ yarn init -y && yarn add /path/to/shakapacker
75
+
76
+ # Test with pnpm (no warnings expected)
77
+ cd /tmp && mkdir test-pnpm && cd test-pnpm
78
+ pnpm init && pnpm add /path/to/shakapacker
79
+ ```
80
+
53
81
  ## Making sure your changes pass all tests
54
82
 
55
83
  There are several specs, covering different aspects of Shakapacker gem. You may run them locally or rely on GitHub CI actions configured to test the gem functionality if different Ruby, Rails, and Node environment.
@@ -125,3 +153,39 @@ To ensure that your installer works as expected, either you can run `bundle exec
125
153
  3. Run `bundle exec rails shakapacker:install` to confirm that you got the right changes.
126
154
 
127
155
  **Note:** Ensure that you use bundle exec otherwise the installed shakapacker gem will run and not the one you are working on.
156
+
157
+ ## CI Workflows
158
+
159
+ Shakapacker uses GitHub Actions for continuous integration. The CI workflows use **Yarn** as the package manager for consistency and reliability.
160
+
161
+ ### Package Manager Choice
162
+
163
+ The project uses Yarn in CI workflows for the following reasons:
164
+ - Deterministic dependency resolution with `yarn.lock`
165
+ - Faster installation with offline mirror support
166
+ - Better workspace support for monorepo-style testing
167
+ - Consistent behavior across different Node.js versions
168
+
169
+ ### Key CI Workflow Files
170
+
171
+ - `.github/workflows/test-bundlers.yml` - Tests webpack, rspack, and bundler switching
172
+ - `.github/workflows/ruby.yml` - Ruby test suite across Ruby/Rails versions
173
+ - `.github/workflows/node.yml` - Node.js test suite across Node versions
174
+ - `.github/workflows/generator.yml` - Generator installation tests
175
+
176
+ All workflows use:
177
+ ```yaml
178
+ - uses: actions/setup-node@v4
179
+ with:
180
+ cache: 'yarn'
181
+ cache-dependency-path: spec/dummy/yarn.lock
182
+ ```
183
+
184
+ And install dependencies with:
185
+ ```bash
186
+ yarn install
187
+ ```
188
+
189
+ ### Testing with Other Package Managers
190
+
191
+ While CI uses Yarn, the gem supports all major package managers (npm, yarn, pnpm, bun). Generator specs test against all package managers to ensure compatibility.
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- shakapacker (9.0.0.beta.5)
4
+ shakapacker (9.0.0.beta.6)
5
5
  activesupport (>= 5.2)
6
6
  package_json
7
7
  rack-proxy (>= 0.6.1)
data/README.md CHANGED
@@ -199,6 +199,83 @@ Note, in v6+, most JS packages are peer dependencies. Thus, the installer will a
199
199
  Previously, these "webpack" and "babel" packages were direct dependencies for `shakapacker`. By
200
200
  making these peer dependencies, you have control over the versions used in your webpack and babel configs.
201
201
 
202
+ ### Optional Peer Dependencies
203
+
204
+ All peer dependencies in Shakapacker are marked as optional via `peerDependenciesMeta`. This design decision ensures:
205
+ - **No warnings during package installation** when dependencies are not needed
206
+ - **Clear visibility of supported package versions** for upgrades
207
+ - **Flexibility to choose only the tools you need** (webpack vs rspack, babel vs swc vs esbuild)
208
+
209
+ The optional peer dependencies approach means you only install what you actually use, while still maintaining
210
+ version compatibility constraints when you do install those packages.
211
+
212
+ #### Required Dependencies by Configuration
213
+
214
+ Depending on your setup, you'll need different subsets of the optional peer dependencies:
215
+
216
+ **For Webpack + Babel (traditional setup):**
217
+ ```json
218
+ {
219
+ "dependencies": {
220
+ "shakapacker": "^9.0.0",
221
+ "@babel/core": "^7.17.9",
222
+ "@babel/plugin-transform-runtime": "^7.17.0",
223
+ "@babel/preset-env": "^7.16.11",
224
+ "@babel/runtime": "^7.17.9",
225
+ "babel-loader": "^8.2.4",
226
+ "compression-webpack-plugin": "^9.0.0",
227
+ "terser-webpack-plugin": "^5.3.1",
228
+ "webpack": "^5.76.0",
229
+ "webpack-assets-manifest": "^5.0.6",
230
+ "webpack-cli": "^5.0.0",
231
+ "webpack-dev-server": "^5.0.0"
232
+ }
233
+ }
234
+ ```
235
+
236
+ **For Webpack + SWC (faster alternative):**
237
+ ```json
238
+ {
239
+ "dependencies": {
240
+ "shakapacker": "^9.0.0",
241
+ "@swc/core": "^1.3.0",
242
+ "swc-loader": "^0.2.0",
243
+ "compression-webpack-plugin": "^9.0.0",
244
+ "terser-webpack-plugin": "^5.3.1",
245
+ "webpack": "^5.76.0",
246
+ "webpack-assets-manifest": "^5.0.6",
247
+ "webpack-cli": "^5.0.0",
248
+ "webpack-dev-server": "^5.0.0"
249
+ }
250
+ }
251
+ ```
252
+
253
+ **For Rspack + SWC (10x faster bundling):**
254
+ ```json
255
+ {
256
+ "dependencies": {
257
+ "shakapacker": "^9.0.0",
258
+ "@rspack/core": "^1.0.0",
259
+ "@rspack/cli": "^1.0.0",
260
+ "@swc/core": "^1.3.0",
261
+ "swc-loader": "^0.2.0",
262
+ "rspack-manifest-plugin": "^5.0.0"
263
+ }
264
+ }
265
+ ```
266
+
267
+ **For CSS/Sass processing (add to any config above):**
268
+ ```json
269
+ {
270
+ "dependencies": {
271
+ "css-loader": "^6.8.1",
272
+ "mini-css-extract-plugin": "^2.0.0",
273
+ "sass": "^1.50.0",
274
+ "sass-loader": "^13.0.0"
275
+ }
276
+ }
277
+ ```
278
+
202
279
  ## Concepts
203
280
 
204
281
  At its core, Shakapacker's essential function is to:
@@ -0,0 +1,198 @@
1
+ # Optional Peer Dependencies in Shakapacker
2
+
3
+ ## Overview
4
+
5
+ As of Shakapacker v9, all peer dependencies are marked as optional via `peerDependenciesMeta`. This design provides maximum flexibility while maintaining clear version constraints.
6
+
7
+ ## Key Benefits
8
+
9
+ 1. **No Installation Warnings** - Package managers (npm, yarn, pnpm) won't warn about missing peer dependencies
10
+ 2. **Install Only What You Need** - Users only install packages for their chosen configuration
11
+ 3. **Clear Version Constraints** - When packages are installed, version compatibility is still enforced
12
+ 4. **Smaller Node Modules** - Reduced disk usage by not installing unnecessary packages
13
+
14
+ ## Implementation Details
15
+
16
+ ### Package.json Structure
17
+
18
+ ```json
19
+ {
20
+ "dependencies": {
21
+ "js-yaml": "^4.1.0",
22
+ "path-complete-extname": "^1.0.0",
23
+ "webpack-merge": "^5.8.0" // Direct dependency - always available
24
+ },
25
+ "peerDependencies": {
26
+ "webpack": "^5.76.0",
27
+ "@rspack/core": "^1.0.0",
28
+ // ... all build tools
29
+ },
30
+ "peerDependenciesMeta": {
31
+ "webpack": { "optional": true },
32
+ "@rspack/core": { "optional": true },
33
+ // ... all marked as optional
34
+ }
35
+ }
36
+ ```
37
+
38
+ ### TypeScript Type-Only Imports
39
+
40
+ To prevent runtime errors when optional packages aren't installed, all webpack imports use type-only syntax:
41
+
42
+ ```typescript
43
+ // @ts-ignore: webpack is an optional peer dependency (using type-only import)
44
+ import type { Configuration } from "webpack"
45
+ ```
46
+
47
+ Type-only imports are erased during compilation and don't trigger module resolution at runtime.
48
+
49
+ ## Configuration Examples
50
+
51
+ ### Webpack + Babel (Traditional)
52
+ ```json
53
+ {
54
+ "dependencies": {
55
+ "shakapacker": "^9.0.0",
56
+ "webpack": "^5.76.0",
57
+ "webpack-cli": "^5.0.0",
58
+ "babel-loader": "^8.2.4",
59
+ "@babel/core": "^7.17.9",
60
+ "@babel/preset-env": "^7.16.11"
61
+ }
62
+ }
63
+ ```
64
+
65
+ ### Webpack + SWC (20x Faster)
66
+ ```json
67
+ {
68
+ "dependencies": {
69
+ "shakapacker": "^9.0.0",
70
+ "webpack": "^5.76.0",
71
+ "webpack-cli": "^5.0.0",
72
+ "@swc/core": "^1.3.0",
73
+ "swc-loader": "^0.2.0"
74
+ }
75
+ }
76
+ ```
77
+
78
+ ### Rspack + SWC (10x Faster Bundling)
79
+ ```json
80
+ {
81
+ "dependencies": {
82
+ "shakapacker": "^9.0.0",
83
+ "@rspack/core": "^1.0.0",
84
+ "@rspack/cli": "^1.0.0",
85
+ "rspack-manifest-plugin": "^5.0.0"
86
+ }
87
+ }
88
+ ```
89
+
90
+ ## Migration Guide
91
+
92
+ ### From v8 to v9
93
+
94
+ If upgrading from Shakapacker v8:
95
+
96
+ 1. **No action required** - Your existing dependencies will continue to work
97
+ 2. **No more warnings** - Peer dependency warnings will disappear after upgrading
98
+ 3. **Option to optimize** - You can now remove unused dependencies (e.g., remove Babel if using SWC)
99
+
100
+ ### New Installations
101
+
102
+ The installer (`rails shakapacker:install`) only adds packages needed for your configuration:
103
+ - Detects your preferred bundler (webpack/rspack)
104
+ - Installs appropriate JavaScript transpiler (babel/swc/esbuild)
105
+ - Adds only required dependencies
106
+
107
+ ## Version Constraints
108
+
109
+ Version ranges are carefully chosen for compatibility:
110
+
111
+ - **Broader ranges for peer deps** - Allows flexibility (e.g., `^5.76.0` for webpack)
112
+ - **Specific versions in devDeps** - Ensures testing against known versions
113
+ - **Forward compatibility** - Ranges include future minor versions (e.g., `^5.0.0 || ^6.0.0`)
114
+
115
+ ## Testing
116
+
117
+ ### Installation Tests
118
+
119
+ Test that no warnings appear during installation:
120
+
121
+ ```bash
122
+ # Test script available at test/peer-dependencies.sh
123
+ ./test/peer-dependencies.sh
124
+ ```
125
+
126
+ ### Runtime Tests
127
+
128
+ Verify Shakapacker loads without optional dependencies:
129
+
130
+ ```javascript
131
+ // This works even without webpack installed (when using rspack)
132
+ const shakapacker = require('shakapacker');
133
+ ```
134
+
135
+ ### CI Integration
136
+
137
+ The test suite includes:
138
+ - `spec/shakapacker/optional_dependencies_spec.rb` - Package.json structure validation
139
+ - `spec/shakapacker/doctor_optional_peer_spec.rb` - Doctor command validation
140
+ - `test/peer-dependencies.sh` - Installation warning tests
141
+
142
+ ## Troubleshooting
143
+
144
+ ### Still seeing peer dependency warnings?
145
+
146
+ 1. Ensure you're using Shakapacker v9.0.0 or later
147
+ 2. Clear your package manager cache:
148
+ - npm: `npm cache clean --force`
149
+ - yarn: `yarn cache clean`
150
+ - pnpm: `pnpm store prune`
151
+ 3. Reinstall dependencies
152
+
153
+ ### Module not found errors?
154
+
155
+ 1. Check you've installed required dependencies for your configuration
156
+ 2. Refer to the configuration examples above
157
+ 3. Run `rails shakapacker:doctor` for diagnostics
158
+
159
+ ### TypeScript errors?
160
+
161
+ The `@ts-ignore` comments are intentional and necessary for optional dependencies.
162
+ They prevent TypeScript errors when optional packages aren't installed.
163
+
164
+ ## Contributing
165
+
166
+ When adding new dependencies:
167
+
168
+ 1. Add to `peerDependencies` with appropriate version range
169
+ 2. Mark as optional in `peerDependenciesMeta`
170
+ 3. Use type-only imports in TypeScript: `import type { ... }`
171
+ 4. Test with all package managers (npm, yarn, pnpm)
172
+ 5. Update this documentation if needed
173
+
174
+ ## Design Rationale
175
+
176
+ This approach balances several concerns:
177
+
178
+ 1. **User Experience** - No confusing warnings during installation
179
+ 2. **Flexibility** - Support multiple configurations without forcing unnecessary installs
180
+ 3. **Compatibility** - Maintain version constraints for safety
181
+ 4. **Performance** - Reduce installation time and disk usage
182
+ 5. **Type Safety** - TypeScript support without runtime dependencies
183
+
184
+ ## Future Improvements
185
+
186
+ Potential enhancements for future versions:
187
+
188
+ 1. **Conditional exports** - Use package.json exports field for better tree-shaking
189
+ 2. **Dynamic imports** - Load bundler-specific code only when needed
190
+ 3. **Doctor updates** - Enhance doctor command to better understand optional dependencies
191
+ 4. **Automated testing** - Add CI jobs testing each configuration combination
192
+
193
+ ## References
194
+
195
+ - [npm: peerDependenciesMeta](https://docs.npmjs.com/cli/v8/configuring-npm/package-json#peerdependenciesmeta)
196
+ - [TypeScript: Type-Only Imports](https://www.typescriptlang.org/docs/handbook/modules.html#type-only-imports-and-exports)
197
+ - [Shakapacker Issue #565](https://github.com/shakacode/shakapacker/issues/565)
198
+ - [Pull Request #615](https://github.com/shakacode/shakapacker/pull/615)
data/docs/v9_upgrade.md CHANGED
@@ -130,6 +130,35 @@ npm install esbuild esbuild-loader
130
130
  assets_bundler: 'rspack' # or 'webpack' (default)
131
131
  ```
132
132
 
133
+ ### 5. All Peer Dependencies Now Optional
134
+
135
+ **What changed:** All peer dependencies are now marked as optional via `peerDependenciesMeta`.
136
+
137
+ **Benefits:**
138
+ - **No installation warnings** - You won't see peer dependency warnings for packages you don't use
139
+ - **Install only what you need** - Using webpack? Don't install rspack. Using SWC? Don't install Babel.
140
+ - **Clear version constraints** - When you do install a package, version compatibility is still enforced
141
+
142
+ **What this means for you:**
143
+ - **Existing projects:** No changes needed. Your existing dependencies will continue to work.
144
+ - **New projects:** The installer only adds the packages you actually need based on your configuration.
145
+ - **Package manager behavior:** npm, yarn, and pnpm will no longer warn about missing peer dependencies.
146
+
147
+ **Example:** If you're using SWC with webpack, you only need:
148
+ ```json
149
+ {
150
+ "dependencies": {
151
+ "shakapacker": "^9.0.0",
152
+ "@swc/core": "^1.3.0",
153
+ "swc-loader": "^0.2.0",
154
+ "webpack": "^5.76.0",
155
+ "webpack-cli": "^5.0.0",
156
+ "webpack-dev-server": "^5.0.0"
157
+ }
158
+ }
159
+ ```
160
+ You won't get warnings about missing Babel, Rspack, or esbuild packages.
161
+
133
162
  ## Migration Steps
134
163
 
135
164
  ### Step 1: Update Dependencies
@@ -224,6 +253,41 @@ Update your global type definitions as shown in Step 2.
224
253
 
225
254
  If you see warnings about CSS module exports, ensure you've updated all imports to use named exports or have properly configured the override.
226
255
 
256
+ ### Unexpected Peer Dependency Warnings After Upgrade
257
+
258
+ If you experience unexpected peer dependency warnings after upgrading to v9, you may need to clear your package manager's cache and reinstall dependencies. This ensures the new optional peer dependency configuration takes effect properly.
259
+
260
+ **For npm:**
261
+ ```bash
262
+ rm -rf node_modules package-lock.json
263
+ npm install
264
+ ```
265
+
266
+ **For Yarn:**
267
+ ```bash
268
+ rm -rf node_modules yarn.lock
269
+ yarn install
270
+ ```
271
+
272
+ **For pnpm:**
273
+ ```bash
274
+ rm -rf node_modules pnpm-lock.yaml
275
+ pnpm install
276
+ ```
277
+
278
+ **For Bun:**
279
+ ```bash
280
+ rm -rf node_modules bun.lockb
281
+ bun install
282
+ ```
283
+
284
+ **When is this necessary?**
285
+ - If you see peer dependency warnings for packages you don't use (e.g., warnings about Babel when using SWC)
286
+ - If your package manager cached the old dependency resolution from v8
287
+ - After switching transpilers or bundlers (e.g., from Babel to SWC, or webpack to rspack)
288
+
289
+ **Note:** This is typically only needed once after the v8 → v9 upgrade. Subsequent installs will use the correct dependency resolution.
290
+
227
291
  ## Need Help?
228
292
 
229
293
  - See [CSS Modules Export Mode documentation](./css-modules-export-mode.md) for detailed configuration options
@@ -238,4 +302,4 @@ If you have a large codebase and need to migrate gradually:
238
302
  2. Migrate files incrementally
239
303
  3. Remove the override once migration is complete
240
304
 
241
- This allows you to upgrade to v9 immediately while taking time to update your CSS module imports.
305
+ This allows you to upgrade to v9 immediately while taking time to update your CSS module imports.
@@ -211,8 +211,7 @@ module Shakapacker
211
211
  def check_webpack_peer_deps(deps)
212
212
  essential_webpack = {
213
213
  "webpack" => "^5.76.0",
214
- "webpack-cli" => "^4.9.2 || ^5.0.0",
215
- "webpack-merge" => "^5.8.0 || ^6.0.0"
214
+ "webpack-cli" => "^4.9.2 || ^5.0.0"
216
215
  }
217
216
 
218
217
  essential_webpack.each do |package, version|
@@ -1,4 +1,4 @@
1
1
  module Shakapacker
2
2
  # Change the version in package.json too, please!
3
- VERSION = "9.0.0.beta.5".freeze
3
+ VERSION = "9.0.0.beta.6".freeze
4
4
  end
@@ -1,116 +1,103 @@
1
+ "use strict";
1
2
  /* eslint global-require: 0 */
2
3
  /* eslint import/no-dynamic-require: 0 */
3
- const { basename, dirname, join, relative, resolve } = require("path")
4
- const { existsSync, readdirSync } = require("fs")
5
- const extname = require("path-complete-extname")
6
- const config = require("../config")
7
- const { isProduction } = require("../env")
8
-
9
- const pluginsPath = resolve(
10
- __dirname,
11
- "..",
12
- "plugins",
13
- `${config.assets_bundler}.js`
14
- )
15
- const { getPlugins } = require(pluginsPath)
16
- const rulesPath = resolve(
17
- __dirname,
18
- "..",
19
- "rules",
20
- `${config.assets_bundler}.js`
21
- )
22
- const rules = require(rulesPath)
23
-
4
+ const { basename, dirname, join, relative, resolve } = require("path");
5
+ const { existsSync, readdirSync } = require("fs");
6
+ const extname = require("path-complete-extname");
7
+ const config = require("../config");
8
+ const { isProduction } = require("../env");
9
+ const pluginsPath = resolve(__dirname, "..", "plugins", `${config.assets_bundler}.js`);
10
+ const { getPlugins } = require(pluginsPath);
11
+ const rulesPath = resolve(__dirname, "..", "rules", `${config.assets_bundler}.js`);
12
+ const rules = require(rulesPath);
24
13
  // Don't use contentHash except for production for performance
25
14
  // https://webpack.js.org/guides/build-performance/#avoid-production-specific-tooling
26
- const hash = isProduction || config.useContentHash ? "-[contenthash]" : ""
15
+ const hash = isProduction || config.useContentHash ? "-[contenthash]" : "";
27
16
  const getFilesInDirectory = (dir, includeNested) => {
28
- if (!existsSync(dir)) {
29
- return []
30
- }
31
- return readdirSync(dir, { withFileTypes: true }).flatMap((dirent) => {
32
- const filePath = join(dir, dirent.name)
33
- if (dirent.isDirectory() && includeNested) {
34
- return getFilesInDirectory(filePath, includeNested)
17
+ if (!existsSync(dir)) {
18
+ return [];
35
19
  }
36
- if (dirent.isFile()) {
37
- return filePath
38
- }
39
- return []
40
- })
41
- }
20
+ return readdirSync(dir, { withFileTypes: true }).flatMap((dirent) => {
21
+ const filePath = join(dir, dirent.name);
22
+ if (dirent.isDirectory() && includeNested) {
23
+ return getFilesInDirectory(filePath, includeNested);
24
+ }
25
+ if (dirent.isFile()) {
26
+ return filePath;
27
+ }
28
+ return [];
29
+ });
30
+ };
42
31
  const getEntryObject = () => {
43
- const entries = {}
44
- const rootPath = join(config.source_path, config.source_entry_path)
45
- if (config.source_entry_path === "/" && config.nested_entries) {
46
- throw new Error(
47
- `Invalid Shakapacker configuration detected!\n\n` +
48
- `You have set source_entry_path to '/' with nested_entries enabled.\n` +
49
- `This would create webpack entry points for EVERY file in your source directory,\n` +
50
- `which would severely impact build performance.\n\n` +
51
- `To fix this issue, either:\n` +
52
- `1. Set 'nested_entries: false' in your shakapacker.yml\n` +
53
- `2. Change 'source_entry_path' to a specific subdirectory (e.g., 'packs')\n` +
54
- `3. Or use both options for better organization of your entry points`
55
- )
56
- }
57
- getFilesInDirectory(rootPath, config.nested_entries).forEach((path) => {
58
- const namespace = relative(join(rootPath), dirname(path))
59
- const name = join(namespace, basename(path, extname(path)))
60
- const assetPath = resolve(path)
61
- // Allows for multiple filetypes per entry (https://webpack.js.org/guides/entry-advanced/)
62
- // Transforms the config object value to an array with all values under the same name
63
- const previousPaths = entries[name]
64
- if (previousPaths) {
65
- const pathArray = Array.isArray(previousPaths)
66
- ? previousPaths
67
- : [previousPaths]
68
- pathArray.push(assetPath)
69
- entries[name] = pathArray
70
- } else {
71
- entries[name] = assetPath
32
+ const entries = {};
33
+ const rootPath = join(config.source_path, config.source_entry_path);
34
+ if (config.source_entry_path === "/" && config.nested_entries) {
35
+ throw new Error(`Invalid Shakapacker configuration detected!\n\n` +
36
+ `You have set source_entry_path to '/' with nested_entries enabled.\n` +
37
+ `This would create webpack entry points for EVERY file in your source directory,\n` +
38
+ `which would severely impact build performance.\n\n` +
39
+ `To fix this issue, either:\n` +
40
+ `1. Set 'nested_entries: false' in your shakapacker.yml\n` +
41
+ `2. Change 'source_entry_path' to a specific subdirectory (e.g., 'packs')\n` +
42
+ `3. Or use both options for better organization of your entry points`);
72
43
  }
73
- })
74
- return entries
75
- }
44
+ getFilesInDirectory(rootPath, config.nested_entries).forEach((path) => {
45
+ const namespace = relative(join(rootPath), dirname(path));
46
+ const name = join(namespace, basename(path, extname(path)));
47
+ const assetPath = resolve(path);
48
+ // Allows for multiple filetypes per entry (https://webpack.js.org/guides/entry-advanced/)
49
+ // Transforms the config object value to an array with all values under the same name
50
+ const previousPaths = entries[name];
51
+ if (previousPaths) {
52
+ const pathArray = Array.isArray(previousPaths)
53
+ ? previousPaths
54
+ : [previousPaths];
55
+ pathArray.push(assetPath);
56
+ entries[name] = pathArray;
57
+ }
58
+ else {
59
+ entries[name] = assetPath;
60
+ }
61
+ });
62
+ return entries;
63
+ };
76
64
  const getModulePaths = () => {
77
- const result = [resolve(config.source_path)]
78
- if (config.additional_paths) {
79
- config.additional_paths.forEach((path) => result.push(resolve(path)))
80
- }
81
- result.push("node_modules")
82
- return result
83
- }
65
+ const result = [resolve(config.source_path)];
66
+ if (config.additional_paths) {
67
+ config.additional_paths.forEach((path) => result.push(resolve(path)));
68
+ }
69
+ result.push("node_modules");
70
+ return result;
71
+ };
84
72
  const baseConfig = {
85
- mode: "production",
86
- output: {
87
- filename: `js/[name]${hash}.js`,
88
- chunkFilename: `js/[name]${hash}.chunk.js`,
89
- // https://webpack.js.org/configuration/output/#outputhotupdatechunkfilename
90
- hotUpdateChunkFilename: "js/[id].[fullhash].hot-update.js",
91
- path: config.outputPath,
92
- publicPath: config.publicPath,
93
- // This is required for SRI to work.
94
- crossOriginLoading:
95
- config.integrity && config.integrity.enabled
96
- ? config.integrity.cross_origin
97
- : false
98
- },
99
- entry: getEntryObject(),
100
- resolve: {
101
- extensions: [".js", ".jsx", ".mjs", ".ts", ".tsx", ".coffee"],
102
- modules: getModulePaths()
103
- },
104
- plugins: getPlugins(),
105
- resolveLoader: {
106
- modules: ["node_modules"]
107
- },
108
- optimization: {
109
- splitChunks: { chunks: "all" },
110
- runtimeChunk: "single"
111
- },
112
- module: {
113
- rules
114
- }
115
- }
116
- module.exports = baseConfig
73
+ mode: "production",
74
+ output: {
75
+ filename: `js/[name]${hash}.js`,
76
+ chunkFilename: `js/[name]${hash}.chunk.js`,
77
+ // https://webpack.js.org/configuration/output/#outputhotupdatechunkfilename
78
+ hotUpdateChunkFilename: "js/[id].[fullhash].hot-update.js",
79
+ path: config.outputPath,
80
+ publicPath: config.publicPath,
81
+ // This is required for SRI to work.
82
+ crossOriginLoading: config.integrity && config.integrity.enabled
83
+ ? config.integrity.cross_origin
84
+ : false
85
+ },
86
+ entry: getEntryObject(),
87
+ resolve: {
88
+ extensions: [".js", ".jsx", ".mjs", ".ts", ".tsx", ".coffee"],
89
+ modules: getModulePaths()
90
+ },
91
+ plugins: getPlugins(),
92
+ resolveLoader: {
93
+ modules: ["node_modules"]
94
+ },
95
+ optimization: {
96
+ splitChunks: { chunks: "all" },
97
+ runtimeChunk: "single"
98
+ },
99
+ module: {
100
+ rules
101
+ }
102
+ };
103
+ module.exports = baseConfig;
@@ -5,7 +5,8 @@ const { basename, dirname, join, relative, resolve } = require("path")
5
5
  const { existsSync, readdirSync } = require("fs")
6
6
  import { Dirent } from "fs"
7
7
  const extname = require("path-complete-extname")
8
- import { Configuration, Entry } from "webpack"
8
+ // @ts-ignore: webpack is an optional peer dependency (using type-only import)
9
+ import type { Configuration, Entry } from "webpack"
9
10
  const config = require("../config")
10
11
  const { isProduction } = require("../env")
11
12
 
data/package/index.ts CHANGED
@@ -4,7 +4,8 @@
4
4
  const webpackMerge = require("webpack-merge")
5
5
  import { resolve } from "path"
6
6
  import { existsSync } from "fs"
7
- import { Configuration } from "webpack"
7
+ // @ts-ignore: webpack is an optional peer dependency (using type-only import)
8
+ import type { Configuration } from "webpack"
8
9
  const config = require("./config")
9
10
  const baseConfig = require("./environments/base")
10
11
  const devServer = require("./dev_server")
data/package/loaders.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ // @ts-ignore: webpack is an optional peer dependency (using type-only import)
1
2
  import type { LoaderDefinitionFunction } from 'webpack'
2
3
 
3
4
  export interface ShakapackerLoaderOptions {
@@ -1,3 +1,4 @@
1
+ // @ts-ignore: webpack is an optional peer dependency (using type-only import)
1
2
  import type { Configuration, RuleSetRule, RuleSetUseItem } from 'webpack'
2
3
 
3
4
  export interface ShakapackerWebpackConfig extends Configuration {
data/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shakapacker",
3
- "version": "9.0.0-beta.5",
3
+ "version": "9.0.0-beta.6",
4
4
  "description": "Use webpack to manage app-like JavaScript modules in Rails",
5
5
  "homepage": "https://github.com/shakacode/shakapacker",
6
6
  "bugs": {
@@ -38,7 +38,8 @@
38
38
  },
39
39
  "dependencies": {
40
40
  "js-yaml": "^4.1.0",
41
- "path-complete-extname": "^1.0.0"
41
+ "path-complete-extname": "^1.0.0",
42
+ "webpack-merge": "^5.8.0"
42
43
  },
43
44
  "devDependencies": {
44
45
  "@rspack/cli": "^1.4.11",
@@ -73,9 +74,112 @@
73
74
  "typescript": "^5.9.2",
74
75
  "webpack": "5.93.0",
75
76
  "webpack-assets-manifest": "^5.0.6",
76
- "webpack-merge": "^5.8.0",
77
77
  "webpack-subresource-integrity": "^5.1.0"
78
78
  },
79
+ "peerDependencies": {
80
+ "@babel/core": "^7.17.9",
81
+ "@babel/plugin-transform-runtime": "^7.17.0",
82
+ "@babel/preset-env": "^7.16.11",
83
+ "@babel/runtime": "^7.17.9",
84
+ "@rspack/core": "^1.0.0",
85
+ "@rspack/cli": "^1.0.0",
86
+ "@rspack/plugin-react-refresh": "^1.0.0",
87
+ "@types/babel__core": "^7.0.0",
88
+ "@types/webpack": "^5.0.0",
89
+ "babel-loader": "^8.2.4 || ^9.0.0 || ^10.0.0",
90
+ "compression-webpack-plugin": "^9.0.0 || ^10.0.0 || ^11.0.0",
91
+ "css-loader": "^6.8.1 || ^7.0.0",
92
+ "esbuild": "^0.14.0 || ^0.15.0 || ^0.16.0 || ^0.17.0 || ^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0 || ^0.24.0",
93
+ "esbuild-loader": "^2.0.0 || ^3.0.0 || ^4.0.0",
94
+ "mini-css-extract-plugin": "^2.0.0",
95
+ "rspack-manifest-plugin": "^5.0.0",
96
+ "sass": "^1.50.0",
97
+ "sass-loader": "^13.0.0 || ^14.0.0 || ^15.0.0 || ^16.0.0",
98
+ "swc-loader": "^0.1.15 || ^0.2.0",
99
+ "terser-webpack-plugin": "^5.3.1",
100
+ "webpack": "^5.76.0",
101
+ "webpack-assets-manifest": "^5.0.6 || ^6.0.0",
102
+ "webpack-cli": "^4.9.2 || ^5.0.0 || ^6.0.0",
103
+ "webpack-dev-server": "^4.15.2 || ^5.2.2",
104
+ "webpack-subresource-integrity": "^5.1.0"
105
+ },
106
+ "peerDependenciesMeta": {
107
+ "@babel/core": {
108
+ "optional": true
109
+ },
110
+ "@babel/plugin-transform-runtime": {
111
+ "optional": true
112
+ },
113
+ "@babel/preset-env": {
114
+ "optional": true
115
+ },
116
+ "@babel/runtime": {
117
+ "optional": true
118
+ },
119
+ "@rspack/core": {
120
+ "optional": true
121
+ },
122
+ "@rspack/cli": {
123
+ "optional": true
124
+ },
125
+ "@rspack/plugin-react-refresh": {
126
+ "optional": true
127
+ },
128
+ "@types/babel__core": {
129
+ "optional": true
130
+ },
131
+ "@types/webpack": {
132
+ "optional": true
133
+ },
134
+ "babel-loader": {
135
+ "optional": true
136
+ },
137
+ "compression-webpack-plugin": {
138
+ "optional": true
139
+ },
140
+ "css-loader": {
141
+ "optional": true
142
+ },
143
+ "esbuild": {
144
+ "optional": true
145
+ },
146
+ "esbuild-loader": {
147
+ "optional": true
148
+ },
149
+ "mini-css-extract-plugin": {
150
+ "optional": true
151
+ },
152
+ "rspack-manifest-plugin": {
153
+ "optional": true
154
+ },
155
+ "sass": {
156
+ "optional": true
157
+ },
158
+ "sass-loader": {
159
+ "optional": true
160
+ },
161
+ "swc-loader": {
162
+ "optional": true
163
+ },
164
+ "terser-webpack-plugin": {
165
+ "optional": true
166
+ },
167
+ "webpack": {
168
+ "optional": true
169
+ },
170
+ "webpack-assets-manifest": {
171
+ "optional": true
172
+ },
173
+ "webpack-cli": {
174
+ "optional": true
175
+ },
176
+ "webpack-dev-server": {
177
+ "optional": true
178
+ },
179
+ "webpack-subresource-integrity": {
180
+ "optional": true
181
+ }
182
+ },
79
183
  "packageManager": "yarn@1.22.22",
80
184
  "engines": {
81
185
  "node": ">= 14",
@@ -0,0 +1,85 @@
1
+ #!/bin/bash
2
+
3
+ # Test script for verifying optional peer dependencies work correctly
4
+ # This ensures no warnings are shown during installation with different package managers
5
+
6
+ set -e
7
+
8
+ echo "Testing optional peer dependencies installation..."
9
+
10
+ # Colors for output
11
+ RED='\033[0;31m'
12
+ GREEN='\033[0;32m'
13
+ NC='\033[0m' # No Color
14
+
15
+ # Get the current directory (shakapacker root)
16
+ SHAKAPACKER_PATH=$(pwd)
17
+
18
+ # Create a temporary directory for tests
19
+ TEST_DIR=$(mktemp -d)
20
+ echo "Testing in: $TEST_DIR"
21
+
22
+ # Function to check for peer dependency warnings
23
+ check_warnings() {
24
+ local output=$1
25
+ local pkg_manager=$2
26
+
27
+ # Check for common peer dependency warning patterns
28
+ if echo "$output" | grep -i "peer" | grep -i "warn" > /dev/null 2>&1; then
29
+ echo -e "${RED}✗ $pkg_manager shows peer dependency warnings${NC}"
30
+ return 1
31
+ else
32
+ echo -e "${GREEN}✓ $pkg_manager installation clean (no warnings)${NC}"
33
+ return 0
34
+ fi
35
+ }
36
+
37
+ # Test with npm
38
+ echo ""
39
+ echo "Testing with npm..."
40
+ mkdir -p "$TEST_DIR/npm-test"
41
+ cd "$TEST_DIR/npm-test"
42
+ npm init -y > /dev/null 2>&1
43
+ NPM_OUTPUT=$(npm install "$SHAKAPACKER_PATH" 2>&1)
44
+ check_warnings "$NPM_OUTPUT" "npm"
45
+ NPM_RESULT=$?
46
+
47
+ # Test with yarn
48
+ echo ""
49
+ echo "Testing with yarn..."
50
+ mkdir -p "$TEST_DIR/yarn-test"
51
+ cd "$TEST_DIR/yarn-test"
52
+ yarn init -y > /dev/null 2>&1
53
+ YARN_OUTPUT=$(yarn add "$SHAKAPACKER_PATH" 2>&1)
54
+ check_warnings "$YARN_OUTPUT" "yarn"
55
+ YARN_RESULT=$?
56
+
57
+ # Test with pnpm (if available)
58
+ if command -v pnpm &> /dev/null; then
59
+ echo ""
60
+ echo "Testing with pnpm..."
61
+ mkdir -p "$TEST_DIR/pnpm-test"
62
+ cd "$TEST_DIR/pnpm-test"
63
+ pnpm init > /dev/null 2>&1
64
+ PNPM_OUTPUT=$(pnpm add "$SHAKAPACKER_PATH" 2>&1)
65
+ check_warnings "$PNPM_OUTPUT" "pnpm"
66
+ PNPM_RESULT=$?
67
+ else
68
+ echo ""
69
+ echo "Skipping pnpm test (not installed)"
70
+ PNPM_RESULT=0
71
+ fi
72
+
73
+ # Cleanup
74
+ rm -rf "$TEST_DIR"
75
+
76
+ # Summary
77
+ echo ""
78
+ echo "===== Test Summary ====="
79
+ if [ $NPM_RESULT -eq 0 ] && [ $YARN_RESULT -eq 0 ] && [ $PNPM_RESULT -eq 0 ]; then
80
+ echo -e "${GREEN}All tests passed! No peer dependency warnings detected.${NC}"
81
+ exit 0
82
+ else
83
+ echo -e "${RED}Some tests failed. Peer dependency warnings were detected.${NC}"
84
+ exit 1
85
+ fi
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shakapacker
3
3
  version: !ruby/object:Gem::Version
4
- version: 9.0.0.beta.5
4
+ version: 9.0.0.beta.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Heinemeier Hansson
@@ -172,6 +172,7 @@ files:
172
172
  - docs/customizing_babel_config.md
173
173
  - docs/deployment.md
174
174
  - docs/developing_shakapacker.md
175
+ - docs/optional-peer-dependencies.md
175
176
  - docs/peer-dependencies.md
176
177
  - docs/react.md
177
178
  - docs/rspack.md
@@ -317,6 +318,7 @@ files:
317
318
  - test/package/rules/webpack.test.js
318
319
  - test/package/staging.test.js
319
320
  - test/package/test.test.js
321
+ - test/peer-dependencies.sh
320
322
  - test/resolver.js
321
323
  - test/typescript/build.test.js
322
324
  - tools/README.md
@@ -327,7 +329,7 @@ homepage: https://github.com/shakacode/shakapacker
327
329
  licenses:
328
330
  - MIT
329
331
  metadata:
330
- source_code_uri: https://github.com/shakacode/shakapacker/tree/v9.0.0.beta.5
332
+ source_code_uri: https://github.com/shakacode/shakapacker/tree/v9.0.0.beta.6
331
333
  rdoc_options: []
332
334
  require_paths:
333
335
  - lib
@@ -367,5 +369,6 @@ test_files:
367
369
  - test/package/rules/webpack.test.js
368
370
  - test/package/staging.test.js
369
371
  - test/package/test.test.js
372
+ - test/peer-dependencies.sh
370
373
  - test/resolver.js
371
374
  - test/typescript/build.test.js