shakapacker 8.0.2 → 9.2.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 (198) hide show
  1. checksums.yaml +4 -4
  2. data/.eslintignore +1 -0
  3. data/.eslintrc.fast.js +40 -0
  4. data/.eslintrc.js +48 -0
  5. data/.github/STATUS.md +1 -0
  6. data/.github/workflows/claude-code-review.yml +54 -0
  7. data/.github/workflows/claude.yml +50 -0
  8. data/.github/workflows/dummy.yml +9 -4
  9. data/.github/workflows/generator.yml +32 -10
  10. data/.github/workflows/node.yml +23 -1
  11. data/.github/workflows/ruby.yml +33 -2
  12. data/.github/workflows/test-bundlers.yml +170 -0
  13. data/.gitignore +20 -0
  14. data/.husky/pre-commit +2 -0
  15. data/.npmignore +56 -0
  16. data/.prettierignore +3 -0
  17. data/.rubocop.yml +1 -0
  18. data/.yalcignore +26 -0
  19. data/CHANGELOG.md +302 -16
  20. data/CLAUDE.md +29 -0
  21. data/CONTRIBUTING.md +138 -20
  22. data/Gemfile.lock +83 -89
  23. data/README.md +343 -105
  24. data/Rakefile +39 -4
  25. data/TODO.md +50 -0
  26. data/TODO_v9.md +87 -0
  27. data/bin/export-bundler-config +11 -0
  28. data/conductor-setup.sh +70 -0
  29. data/conductor.json +7 -0
  30. data/docs/cdn_setup.md +379 -0
  31. data/docs/common-upgrades.md +615 -0
  32. data/docs/css-modules-export-mode.md +512 -0
  33. data/docs/deployment.md +62 -9
  34. data/docs/optional-peer-dependencies.md +198 -0
  35. data/docs/peer-dependencies.md +60 -0
  36. data/docs/react.md +6 -14
  37. data/docs/releasing.md +197 -0
  38. data/docs/rspack.md +190 -0
  39. data/docs/rspack_migration_guide.md +305 -0
  40. data/docs/subresource_integrity.md +54 -0
  41. data/docs/transpiler-migration.md +209 -0
  42. data/docs/transpiler-performance.md +179 -0
  43. data/docs/troubleshooting.md +157 -22
  44. data/docs/typescript-migration.md +379 -0
  45. data/docs/typescript.md +99 -0
  46. data/docs/using_esbuild_loader.md +3 -3
  47. data/docs/using_swc_loader.md +112 -10
  48. data/docs/v6_upgrade.md +10 -0
  49. data/docs/v8_upgrade.md +3 -5
  50. data/docs/v9_upgrade.md +458 -0
  51. data/gemfiles/Gemfile-rails.6.0.x +2 -1
  52. data/gemfiles/Gemfile-rails.6.1.x +1 -1
  53. data/gemfiles/Gemfile-rails.7.0.x +2 -2
  54. data/gemfiles/Gemfile-rails.7.1.x +1 -2
  55. data/gemfiles/Gemfile-rails.7.2.x +11 -0
  56. data/gemfiles/Gemfile-rails.8.0.x +11 -0
  57. data/lib/install/bin/export-bundler-config +11 -0
  58. data/lib/install/bin/shakapacker +4 -6
  59. data/lib/install/bin/shakapacker-dev-server +1 -1
  60. data/lib/install/config/rspack/rspack.config.js +6 -0
  61. data/lib/install/config/rspack/rspack.config.ts +7 -0
  62. data/lib/install/config/shakapacker.yml +25 -5
  63. data/lib/install/config/webpack/webpack.config.ts +7 -0
  64. data/lib/install/package.json +38 -0
  65. data/lib/install/template.rb +194 -44
  66. data/lib/shakapacker/bundler_switcher.rb +329 -0
  67. data/lib/shakapacker/compiler.rb +2 -1
  68. data/lib/shakapacker/compiler_strategy.rb +2 -2
  69. data/lib/shakapacker/configuration.rb +173 -2
  70. data/lib/shakapacker/dev_server_runner.rb +29 -8
  71. data/lib/shakapacker/digest_strategy.rb +2 -1
  72. data/lib/shakapacker/doctor.rb +905 -0
  73. data/lib/shakapacker/helper.rb +64 -16
  74. data/lib/shakapacker/manifest.rb +10 -3
  75. data/lib/shakapacker/mtime_strategy.rb +1 -1
  76. data/lib/shakapacker/railtie.rb +4 -4
  77. data/lib/shakapacker/rspack_runner.rb +19 -0
  78. data/lib/shakapacker/runner.rb +159 -10
  79. data/lib/shakapacker/swc_migrator.rb +384 -0
  80. data/lib/shakapacker/utils/manager.rb +15 -2
  81. data/lib/shakapacker/version.rb +1 -1
  82. data/lib/shakapacker/version_checker.rb +2 -2
  83. data/lib/shakapacker/webpack_runner.rb +6 -43
  84. data/lib/shakapacker.rb +22 -11
  85. data/lib/tasks/shakapacker/doctor.rake +8 -0
  86. data/lib/tasks/shakapacker/export_bundler_config.rake +72 -0
  87. data/lib/tasks/shakapacker/install.rake +12 -2
  88. data/lib/tasks/shakapacker/migrate_to_swc.rake +13 -0
  89. data/lib/tasks/shakapacker/switch_bundler.rake +82 -0
  90. data/lib/tasks/shakapacker.rake +2 -0
  91. data/package/.npmignore +4 -0
  92. data/package/babel/preset.ts +56 -0
  93. data/package/config.ts +175 -0
  94. data/package/configExporter/cli.ts +683 -0
  95. data/package/configExporter/configDocs.ts +102 -0
  96. data/package/configExporter/fileWriter.ts +92 -0
  97. data/package/configExporter/index.ts +5 -0
  98. data/package/configExporter/types.ts +36 -0
  99. data/package/configExporter/yamlSerializer.ts +266 -0
  100. data/package/{dev_server.js → dev_server.ts} +8 -5
  101. data/package/env.ts +92 -0
  102. data/package/environments/__type-tests__/rspack-plugin-compatibility.ts +30 -0
  103. data/package/environments/{base.js → base.ts} +56 -60
  104. data/package/environments/development.ts +90 -0
  105. data/package/environments/production.ts +80 -0
  106. data/package/environments/test.ts +53 -0
  107. data/package/environments/types.ts +98 -0
  108. data/package/esbuild/index.ts +42 -0
  109. data/package/index.d.ts +3 -60
  110. data/package/index.ts +55 -0
  111. data/package/loaders.d.ts +28 -0
  112. data/package/optimization/rspack.ts +36 -0
  113. data/package/optimization/webpack.ts +57 -0
  114. data/package/plugins/rspack.ts +103 -0
  115. data/package/plugins/webpack.ts +62 -0
  116. data/package/rspack/index.ts +64 -0
  117. data/package/rules/{babel.js → babel.ts} +2 -2
  118. data/package/rules/{coffee.js → coffee.ts} +1 -1
  119. data/package/rules/css.ts +3 -0
  120. data/package/rules/{erb.js → erb.ts} +1 -1
  121. data/package/rules/esbuild.ts +10 -0
  122. data/package/rules/file.ts +40 -0
  123. data/package/rules/{jscommon.js → jscommon.ts} +4 -4
  124. data/package/rules/{less.js → less.ts} +4 -4
  125. data/package/rules/raw.ts +25 -0
  126. data/package/rules/rspack.ts +176 -0
  127. data/package/rules/{sass.js → sass.ts} +7 -3
  128. data/package/rules/{stylus.js → stylus.ts} +4 -8
  129. data/package/rules/swc.ts +10 -0
  130. data/package/rules/webpack.ts +16 -0
  131. data/package/swc/index.ts +56 -0
  132. data/package/types/README.md +88 -0
  133. data/package/types/index.ts +61 -0
  134. data/package/types.ts +108 -0
  135. data/package/utils/configPath.ts +6 -0
  136. data/package/utils/debug.ts +49 -0
  137. data/package/utils/defaultConfigPath.ts +4 -0
  138. data/package/utils/errorCodes.ts +219 -0
  139. data/package/utils/errorHelpers.ts +143 -0
  140. data/package/utils/getStyleRule.ts +64 -0
  141. data/package/utils/helpers.ts +85 -0
  142. data/package/utils/{inliningCss.js → inliningCss.ts} +3 -3
  143. data/package/utils/pathValidation.ts +139 -0
  144. data/package/utils/requireOrError.ts +15 -0
  145. data/package/utils/snakeToCamelCase.ts +5 -0
  146. data/package/utils/typeGuards.ts +342 -0
  147. data/package/utils/validateDependencies.ts +61 -0
  148. data/package/webpack-types.d.ts +33 -0
  149. data/package/webpackDevServerConfig.ts +117 -0
  150. data/package-lock.json +13047 -0
  151. data/package.json +154 -18
  152. data/scripts/remove-use-strict.js +45 -0
  153. data/scripts/type-check-no-emit.js +27 -0
  154. data/test/helpers.js +1 -1
  155. data/test/package/config.test.js +43 -0
  156. data/test/package/env.test.js +42 -7
  157. data/test/package/environments/base.test.js +5 -1
  158. data/test/package/rules/babel.test.js +16 -0
  159. data/test/package/rules/esbuild.test.js +1 -1
  160. data/test/package/rules/raw.test.js +40 -7
  161. data/test/package/rules/swc.test.js +1 -1
  162. data/test/package/rules/webpack.test.js +35 -0
  163. data/test/package/staging.test.js +4 -3
  164. data/test/package/transpiler-defaults.test.js +127 -0
  165. data/test/peer-dependencies.sh +85 -0
  166. data/test/scripts/remove-use-strict.test.js +125 -0
  167. data/test/typescript/build.test.js +118 -0
  168. data/test/typescript/environments.test.js +107 -0
  169. data/test/typescript/pathValidation.test.js +142 -0
  170. data/test/typescript/securityValidation.test.js +182 -0
  171. data/tools/README.md +124 -0
  172. data/tools/css-modules-v9-codemod.js +179 -0
  173. data/tsconfig.eslint.json +16 -0
  174. data/tsconfig.json +38 -0
  175. data/yarn.lock +4165 -2706
  176. metadata +129 -41
  177. data/package/babel/preset.js +0 -37
  178. data/package/config.js +0 -54
  179. data/package/env.js +0 -48
  180. data/package/environments/development.js +0 -13
  181. data/package/environments/production.js +0 -88
  182. data/package/environments/test.js +0 -3
  183. data/package/esbuild/index.js +0 -40
  184. data/package/index.js +0 -40
  185. data/package/rules/css.js +0 -3
  186. data/package/rules/esbuild.js +0 -10
  187. data/package/rules/file.js +0 -29
  188. data/package/rules/index.js +0 -20
  189. data/package/rules/raw.js +0 -5
  190. data/package/rules/swc.js +0 -10
  191. data/package/swc/index.js +0 -50
  192. data/package/utils/configPath.js +0 -4
  193. data/package/utils/defaultConfigPath.js +0 -2
  194. data/package/utils/getStyleRule.js +0 -40
  195. data/package/utils/helpers.js +0 -58
  196. data/package/utils/snakeToCamelCase.js +0 -5
  197. data/package/webpackDevServerConfig.js +0 -71
  198. data/test/package/rules/index.test.js +0 -16
data/docs/v8_upgrade.md CHANGED
@@ -21,9 +21,7 @@ If your host might differ, between various environments for example, you will ei
21
21
  - Ensure the assets are specifically rebuilt for each environment (Heroku pipeline promote feature for example does not do that by default).
22
22
  - Make sure the assets are compiled with `SHAKAPACKER_ASSET_HOST=''` ENV variable to avoid hardcording URLs in packs output.
23
23
 
24
- Second option has got a certain gotcha - dynamic imports and static asset references (like image paths in CSS) will end up without host reference and the app will try and fetch them from your app host rather than defined `config.asset_host`.
25
-
26
- Make sure the assets are compiled with `SHAKAPACKER_ASSET_HOST=''` ENV variable to avoid hardcoding URLs in packs output.
24
+ The second option has got a certain gotcha - dynamic imports and static asset references (like image paths in CSS) will end up without a host reference and the app will try and fetch them from your app host rather than defined `config.asset_host`.
27
25
 
28
26
  To get around that, you can use dynamic override as outlined by [Webpack documentation](https://webpack.js.org/guides/asset-modules/#on-the-fly-override).
29
27
 
@@ -102,10 +100,10 @@ namespace :assets do
102
100
  raise if File.exist?("package.json") && !(system "npm ci")
103
101
 
104
102
  # yarn v1.x (classic)
105
- raise if File.exist?("package.json") && !(system "yarn install --immutable")
103
+ raise if File.exist?("package.json") && !(system "yarn install --frozen-lockfile")
106
104
 
107
105
  # yarn v2+ (berry)
108
- raise if File.exist?("package.json") && !(system "yarn install --frozen-lockfile")
106
+ raise if File.exist?("package.json") && !(system "yarn install --immutable")
109
107
 
110
108
  # bun v1+
111
109
  raise if File.exist?("package.json") && !(system "bun install --frozen-lockfile")
@@ -0,0 +1,458 @@
1
+ # Shakapacker v9 Upgrade Guide
2
+
3
+ This guide outlines new features, breaking changes, and migration steps for upgrading from Shakapacker v8 to v9.
4
+
5
+ > **⚠️ Important for v9.1.0 Users:** If you're upgrading to v9.1.0 or later, please note the [SWC Configuration Breaking Change](#swc-loose-mode-breaking-change-v910) below. This affects users who previously configured SWC in v9.0.0.
6
+
7
+ ## New Features
8
+
9
+ ### TypeScript Support
10
+
11
+ Shakapacker v9 includes TypeScript definitions for better IDE support and type safety.
12
+
13
+ - **No breaking changes** - JavaScript configs continue to work
14
+ - **Optional** - Use TypeScript only if you want it
15
+ - **Type safety** - Catch configuration errors at compile-time
16
+ - **IDE support** - Full autocomplete for all options
17
+
18
+ See the [TypeScript Documentation](./typescript.md) for usage examples.
19
+
20
+ ### NODE_ENV Default Behavior Fixed
21
+
22
+ **What changed:** NODE_ENV now intelligently defaults based on RAILS_ENV instead of always defaulting to "production".
23
+
24
+ **New behavior:**
25
+
26
+ - When `RAILS_ENV=production` → `NODE_ENV` defaults to `"production"`
27
+ - When `RAILS_ENV=development` or unset → `NODE_ENV` defaults to `"development"`
28
+ - When `RAILS_ENV` is any other value (test, staging, etc.) → `NODE_ENV` defaults to `"development"`
29
+
30
+ **Benefits:**
31
+
32
+ - **Dev server "just works"** - No need to explicitly set NODE_ENV when running the development server
33
+ - **Correct configuration loaded** - Development server now properly loads the development configuration from shakapacker.yml
34
+ - **Fixes port issues** - Dev server uses the configured port (e.g., 3035) instead of defaulting to 8080
35
+ - **Fixes 404 errors** - Assets load correctly without requiring manual NODE_ENV configuration
36
+
37
+ **No action required** - This change improves the default behavior and requires no migration.
38
+
39
+ **If you previously worked around this bug**, you can now remove these workarounds:
40
+
41
+ - Remove `NODE_ENV=development` from your `.env`, `.env.development`, or `.env.local` files
42
+ - Remove `NODE_ENV=development` from your `docker-compose.yml` or Dockerfile
43
+ - Remove custom scripts that set NODE_ENV before running the dev server
44
+ - Remove `NODE_ENV=development` from your `bin/dev` or Procfile.dev
45
+
46
+ ## SWC Loose Mode Breaking Change (v9.1.0)
47
+
48
+ > **⚠️ This breaking change was introduced in v9.1.0.** If you're upgrading from v9.0.0, pay special attention to this section.
49
+
50
+ **What changed:** SWC default configuration now uses `loose: false` instead of `loose: true`.
51
+
52
+ **Why:** The previous default of `loose: true` caused:
53
+
54
+ - **Silent failures with Stimulus controllers** - Controllers wouldn't register properly
55
+ - **Incorrect behavior with spread operators** on iterables (e.g., `[...new Set()]`)
56
+ - **Deviation from SWC and Babel defaults** - Both tools default to `loose: false`
57
+
58
+ **Impact:**
59
+
60
+ - **Most projects:** No action needed. The new default is more correct and fixes bugs.
61
+ - **Stimulus users:** This fixes silent controller failures you may have experienced.
62
+ - **Projects relying on loose mode behavior:** May need to explicitly configure `loose: true` (not recommended).
63
+
64
+ **When you might need the old behavior:**
65
+
66
+ - If you have code that breaks with spec-compliant transforms
67
+ - Note: `loose: true` provides slightly faster build times but generates less spec-compliant code
68
+
69
+ **How to restore old behavior (not recommended):**
70
+
71
+ Create or update `config/swc.config.js`:
72
+
73
+ ```javascript
74
+ module.exports = {
75
+ options: {
76
+ jsc: {
77
+ // Only use this if you have code that requires loose transforms.
78
+ // This provides slightly faster build performance but may cause runtime bugs.
79
+ loose: true // Restore v9.0.0 behavior
80
+ }
81
+ }
82
+ }
83
+ ```
84
+
85
+ **Better solution:** Fix your code to work with spec-compliant transforms. The `loose: false` default aligns with both SWC and Babel standards and prevents subtle bugs.
86
+
87
+ **Using Stimulus?** The new default includes `keepClassNames: true` to prevent SWC from mangling class names. If you use `rake shakapacker:migrate_to_swc`, this is configured automatically. See [Using SWC with Stimulus](./using_swc_loader.md#using-swc-with-stimulus) for details.
88
+
89
+ ## Breaking Changes
90
+
91
+ ### 1. CSS Modules Configuration Changed to Named Exports
92
+
93
+ **What changed:** CSS Modules are now configured with `namedExport: true` and `exportLocalsConvention: 'camelCaseOnly'` by default, aligning with Next.js and modern tooling standards.
94
+
95
+ > **Important:** When `namedExport: true` is enabled, css-loader requires `exportLocalsConvention` to be either `'camelCaseOnly'` or `'dashesOnly'`. Using `'camelCase'` will cause a build error: `"exportLocalsConvention" with "camelCase" value is incompatible with "namedExport: true" option`.
96
+
97
+ **Quick Reference: Configuration Options**
98
+
99
+ | Configuration | namedExport | exportLocalsConvention | CSS: `.my-button` | Export Available | Works With |
100
+ | --------------- | ----------- | ---------------------- | ----------------- | --------------------------------- | ----------------- |
101
+ | **v9 Default** | `true` | `'camelCaseOnly'` | `.my-button` | `myButton` only | ✅ Named exports |
102
+ | **Alternative** | `true` | `'dashesOnly'` | `.my-button` | `'my-button'` only | ✅ Named exports |
103
+ | **v8 Style** | `false` | `'camelCase'` | `.my-button` | Both `myButton` AND `'my-button'` | ✅ Default export |
104
+ | **❌ Invalid** | `true` | `'camelCase'` | - | - | ❌ Build Error |
105
+
106
+ **JavaScript Projects:**
107
+
108
+ ```js
109
+ // Before (v8)
110
+ import styles from "./Component.module.css"
111
+ ;<button className={styles.button} />
112
+
113
+ // After (v9)
114
+ import { button } from "./Component.module.css"
115
+ ;<button className={button} />
116
+ ```
117
+
118
+ **TypeScript Projects:**
119
+
120
+ ```typescript
121
+ // Before (v8)
122
+ import styles from './Component.module.css';
123
+ <button className={styles.button} />
124
+
125
+ // After (v9) - namespace import due to TypeScript limitations
126
+ import * as styles from './Component.module.css';
127
+ <button className={styles.button} />
128
+ ```
129
+
130
+ **Migration Options:**
131
+
132
+ 1. **Update your code** (Recommended):
133
+
134
+ - JavaScript: Change to named imports (`import { className }`)
135
+ - TypeScript: Change to namespace imports (`import * as styles`)
136
+ - Kebab-case class names are automatically converted to camelCase
137
+
138
+ 2. **Keep v8 behavior** temporarily:
139
+ - Override the css-loader configuration as shown in [CSS Modules Export Mode documentation](./css-modules-export-mode.md)
140
+ - This gives you time to migrate gradually
141
+
142
+ **Benefits of the change:**
143
+
144
+ - Eliminates webpack/TypeScript warnings
145
+ - Better tree-shaking of unused CSS classes
146
+ - More explicit about which classes are used
147
+ - Aligns with modern JavaScript standards
148
+
149
+ ### 2. Configuration Option Renamed: `webpack_loader` → `javascript_transpiler`
150
+
151
+ **What changed:** The configuration option has been renamed to better reflect its purpose.
152
+
153
+ **Before (v8):**
154
+
155
+ ```yml
156
+ # config/shakapacker.yml
157
+ webpack_loader: "babel"
158
+ ```
159
+
160
+ **After (v9):**
161
+
162
+ ```yml
163
+ # config/shakapacker.yml
164
+ javascript_transpiler: "babel"
165
+ ```
166
+
167
+ **Note:** The old `webpack_loader` option is deprecated but still supported with a warning.
168
+
169
+ ### 3. SWC is Now the Default JavaScript Transpiler
170
+
171
+ **What changed:** SWC replaces Babel as the default JavaScript transpiler. Babel is no longer included in peer dependencies.
172
+
173
+ **Why:** SWC is 20x faster than Babel while maintaining compatibility with most JavaScript and TypeScript code.
174
+
175
+ **Impact on existing projects:**
176
+
177
+ - Your project will continue using Babel if you already have babel packages in package.json
178
+ - To switch to SWC for better performance, see migration options below
179
+
180
+ **Impact on new projects:**
181
+
182
+ - New installations will use SWC by default
183
+ - Babel dependencies won't be installed unless explicitly configured
184
+
185
+ ### Migration Options
186
+
187
+ #### Option 1 (Recommended): Switch to SWC
188
+
189
+ ```yml
190
+ # config/shakapacker.yml
191
+ javascript_transpiler: "swc"
192
+ ```
193
+
194
+ Then install SWC:
195
+
196
+ ```bash
197
+ npm install @swc/core swc-loader
198
+ ```
199
+
200
+ #### Option 2: Keep using Babel
201
+
202
+ ```yml
203
+ # config/shakapacker.yml
204
+ javascript_transpiler: "babel"
205
+ ```
206
+
207
+ No other changes needed - your existing babel packages will continue to work.
208
+
209
+ #### Option 3: Use esbuild
210
+
211
+ ```yml
212
+ # config/shakapacker.yml
213
+ javascript_transpiler: "esbuild"
214
+ ```
215
+
216
+ Then install esbuild:
217
+
218
+ ```bash
219
+ npm install esbuild esbuild-loader
220
+ ```
221
+
222
+ ### 4. Rspack Support Added
223
+
224
+ **New feature:** Shakapacker v9 adds support for Rspack as an alternative bundler to webpack.
225
+
226
+ ```yml
227
+ # config/shakapacker.yml
228
+ assets_bundler: "rspack" # or 'webpack' (default)
229
+ ```
230
+
231
+ ### 5. All Peer Dependencies Now Optional
232
+
233
+ **What changed:** All peer dependencies are now marked as optional via `peerDependenciesMeta`.
234
+
235
+ **Benefits:**
236
+
237
+ - **No installation warnings** - You won't see peer dependency warnings for packages you don't use
238
+ - **Install only what you need** - Using webpack? Don't install rspack. Using SWC? Don't install Babel.
239
+ - **Clear version constraints** - When you do install a package, version compatibility is still enforced
240
+
241
+ **What this means for you:**
242
+
243
+ - **Existing projects:** No changes needed. Your existing dependencies will continue to work.
244
+ - **New projects:** The installer only adds the packages you actually need based on your configuration.
245
+ - **Package manager behavior:** npm, yarn, and pnpm will no longer warn about missing peer dependencies.
246
+
247
+ **Example:** If you're using SWC with webpack, you only need:
248
+
249
+ ```json
250
+ {
251
+ "dependencies": {
252
+ "shakapacker": "^9.0.0",
253
+ "@swc/core": "^1.3.0",
254
+ "swc-loader": "^0.2.0",
255
+ "webpack": "^5.76.0",
256
+ "webpack-cli": "^5.0.0",
257
+ "webpack-dev-server": "^5.0.0"
258
+ }
259
+ }
260
+ ```
261
+
262
+ You won't get warnings about missing Babel, Rspack, or esbuild packages.
263
+
264
+ ## Migration Steps
265
+
266
+ ### Step 1: Update Dependencies
267
+
268
+ ```bash
269
+ npm update shakapacker@^9.0.0
270
+ # or
271
+ yarn upgrade shakapacker@^9.0.0
272
+ ```
273
+
274
+ ### Step 2: Update CSS Module Imports
275
+
276
+ #### For each CSS module import:
277
+
278
+ ```js
279
+ // Find imports like this:
280
+ import styles from "./styles.module.css"
281
+
282
+ // Replace with named imports:
283
+ import { className1, className2 } from "./styles.module.css"
284
+ ```
285
+
286
+ #### Update TypeScript definitions:
287
+
288
+ ```typescript
289
+ // Update your CSS module type definitions
290
+ declare module "*.module.css" {
291
+ // With namedExport: true, css-loader generates individual named exports
292
+ // TypeScript can't know the exact names at compile time, so we declare
293
+ // a module with any number of string exports
294
+ const classes: { readonly [key: string]: string }
295
+ export = classes
296
+ // Note: This allows 'import * as styles' but not 'import styles from'
297
+ // because css-loader with namedExport: true doesn't generate a default export
298
+ }
299
+ ```
300
+
301
+ ### Step 3: Handle Kebab-Case Class Names
302
+
303
+ v9 automatically converts kebab-case to camelCase with `exportLocalsConvention: 'camelCaseOnly'`:
304
+
305
+ ```css
306
+ /* styles.module.css */
307
+ .my-button {
308
+ }
309
+ .primary-color {
310
+ }
311
+ ```
312
+
313
+ ```js
314
+ // v9 default - camelCase conversion
315
+ import { myButton, primaryColor } from "./styles.module.css"
316
+ ```
317
+
318
+ **Alternative: Keep kebab-case names with 'dashesOnly'**
319
+
320
+ If you prefer to keep kebab-case names in JavaScript, you can override the configuration to use `'dashesOnly'`:
321
+
322
+ ```js
323
+ // config/webpack/commonWebpackConfig.js
324
+ modules: {
325
+ namedExport: true,
326
+ exportLocalsConvention: 'dashesOnly' // Keep original kebab-case names
327
+ }
328
+ ```
329
+
330
+ Then use the original kebab-case names in your imports:
331
+
332
+ ```js
333
+ // With dashesOnly configuration
334
+ import { 'my-button': myButton, 'primary-color': primaryColor } from './styles.module.css';
335
+ // or access as properties
336
+ import * as styles from './styles.module.css';
337
+ const buttonClass = styles['my-button'];
338
+ ```
339
+
340
+ **Note:** With `'camelCaseOnly'` (default) or `'dashesOnly'`, only one version is exported. If you need both the original and camelCase versions, you would need to use `'camelCase'` instead, but this requires `namedExport: false` (v8 behavior). See the [CSS Modules Export Mode documentation](./css-modules-export-mode.md) for details on reverting to v8 behavior.
341
+
342
+ ### Step 4: Update Configuration Files
343
+
344
+ If you have `webpack_loader` in your configuration:
345
+
346
+ ```yml
347
+ # config/shakapacker.yml
348
+ # OLD:
349
+ # webpack_loader: 'babel'
350
+
351
+ # NEW:
352
+ javascript_transpiler: "babel"
353
+ ```
354
+
355
+ ### Step 5: Run Tests
356
+
357
+ ```bash
358
+ # Run your test suite
359
+ npm test
360
+
361
+ # Build your application
362
+ bin/shakapacker
363
+
364
+ # Test in development
365
+ bin/shakapacker-dev-server
366
+ ```
367
+
368
+ ## Troubleshooting
369
+
370
+ ### CSS Classes Not Applying
371
+
372
+ - Ensure you're using named imports: `import { className } from '...'`
373
+ - Check camelCase conversion for kebab-case names
374
+ - Clear cache: `rm -rf tmp/cache && bin/shakapacker`
375
+
376
+ ### TypeScript Errors
377
+
378
+ Update your global type definitions as shown in Step 2.
379
+
380
+ ### Build Warnings
381
+
382
+ If you see warnings about CSS module exports, ensure you've updated all imports to use named exports or have properly configured the override.
383
+
384
+ ### Build Error: exportLocalsConvention Incompatible with namedExport
385
+
386
+ If you see this error:
387
+
388
+ ```
389
+ "exportLocalsConvention" with "camelCase" value is incompatible with "namedExport: true" option
390
+ ```
391
+
392
+ This means your webpack configuration has `namedExport: true` with `exportLocalsConvention: 'camelCase'`. The fix is to change to `'camelCaseOnly'` or `'dashesOnly'`:
393
+
394
+ ```js
395
+ // config/webpack/commonWebpackConfig.js or wherever you configure css-loader
396
+ modules: {
397
+ namedExport: true,
398
+ exportLocalsConvention: 'camelCaseOnly' // or 'dashesOnly'
399
+ }
400
+ ```
401
+
402
+ If you want to use `'camelCase'` (which exports both original and camelCase versions), you must set `namedExport: false` and revert to v8 behavior. See the [CSS Modules Export Mode documentation](./css-modules-export-mode.md) for details.
403
+
404
+ ### Unexpected Peer Dependency Warnings After Upgrade
405
+
406
+ 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.
407
+
408
+ **For npm:**
409
+
410
+ ```bash
411
+ rm -rf node_modules package-lock.json
412
+ npm install
413
+ ```
414
+
415
+ **For Yarn:**
416
+
417
+ ```bash
418
+ rm -rf node_modules yarn.lock
419
+ yarn install
420
+ ```
421
+
422
+ **For pnpm:**
423
+
424
+ ```bash
425
+ rm -rf node_modules pnpm-lock.yaml
426
+ pnpm install
427
+ ```
428
+
429
+ **For Bun:**
430
+
431
+ ```bash
432
+ rm -rf node_modules bun.lockb
433
+ bun install
434
+ ```
435
+
436
+ **When is this necessary?**
437
+
438
+ - If you see peer dependency warnings for packages you don't use (e.g., warnings about Babel when using SWC)
439
+ - If your package manager cached the old dependency resolution from v8
440
+ - After switching transpilers or bundlers (e.g., from Babel to SWC, or webpack to rspack)
441
+
442
+ **Note:** This is typically only needed once after the v8 → v9 upgrade. Subsequent installs will use the correct dependency resolution.
443
+
444
+ ## Need Help?
445
+
446
+ - See [CSS Modules Export Mode documentation](./css-modules-export-mode.md) for detailed configuration options
447
+ - Check the [CHANGELOG](../CHANGELOG.md) for all changes
448
+ - File issues at [GitHub Issues](https://github.com/shakacode/shakapacker/issues)
449
+
450
+ ## Gradual Migration Strategy
451
+
452
+ If you have a large codebase and need to migrate gradually:
453
+
454
+ 1. Override the CSS configuration to keep v8 behavior (see [documentation](./css-modules-export-mode.md))
455
+ 2. Migrate files incrementally
456
+ 3. Remove the override once migration is complete
457
+
458
+ This allows you to upgrade to v9 immediately while taking time to update your CSS module imports.
@@ -2,8 +2,9 @@ source "https://rubygems.org"
2
2
 
3
3
  gemspec path: "../"
4
4
 
5
- gem "rails", "~> 6.0.0.rc2"
5
+ gem "rails", "~> 6.0.0"
6
6
  gem "rake", ">= 11.1"
7
7
  gem "rack-proxy", require: false
8
8
  gem "rspec-rails", "~> 5.0.0"
9
9
  gem "byebug"
10
+ gem "concurrent-ruby", "1.3.4"
@@ -5,8 +5,8 @@ git_source(:github) { |repo| "https://github.com/#{repo}.git" }
5
5
  gemspec path: "../"
6
6
 
7
7
  gem "rails", '~>6.1.0'
8
- gem "arel", github: "rails/arel"
9
8
  gem "rake", ">= 11.1"
10
9
  gem "rack-proxy", require: false
11
10
  gem "rspec-rails", "~> 6.0.0"
12
11
  gem "byebug"
12
+ gem "concurrent-ruby", "1.3.4"
@@ -5,8 +5,8 @@ git_source(:github) { |repo| "https://github.com/#{repo}.git" }
5
5
  gemspec path: "../"
6
6
 
7
7
  gem "rails", '~>7.0.0'
8
- gem "arel", github: "rails/arel"
9
8
  gem "rake", ">= 11.1"
10
9
  gem "rack-proxy", require: false
11
- gem "rspec-rails", "~> 6.0.0"
10
+ gem "rspec-rails", "~> 7.0"
12
11
  gem "byebug"
12
+ gem "concurrent-ruby", "1.3.4"
@@ -5,8 +5,7 @@ git_source(:github) { |repo| "https://github.com/#{repo}.git" }
5
5
  gemspec path: "../"
6
6
 
7
7
  gem "rails", '~>7.1.0'
8
- gem "arel", github: "rails/arel"
9
8
  gem "rake", ">= 11.1"
10
9
  gem "rack-proxy", require: false
11
- gem "rspec-rails", "~> 6.0.0"
10
+ gem "rspec-rails", "~> 7.0"
12
11
  gem "byebug"
@@ -0,0 +1,11 @@
1
+ source "https://rubygems.org"
2
+
3
+ git_source(:github) { |repo| "https://github.com/#{repo}.git" }
4
+
5
+ gemspec path: "../"
6
+
7
+ gem "rails", '~>7.2.0'
8
+ gem "rake", ">= 11.1"
9
+ gem "rack-proxy", require: false
10
+ gem "rspec-rails", "~> 7.0"
11
+ gem "byebug"
@@ -0,0 +1,11 @@
1
+ source "https://rubygems.org"
2
+
3
+ git_source(:github) { |repo| "https://github.com/#{repo}.git" }
4
+
5
+ gemspec path: "../"
6
+
7
+ gem "rails", '~>8.0.0'
8
+ gem "rake", ">= 11.1"
9
+ gem "rack-proxy", require: false
10
+ gem "rspec-rails", "~> 7.0"
11
+ gem "byebug"
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env node
2
+
3
+ // Minimal shim - all logic is in the TypeScript module
4
+ const { run } = require('shakapacker/configExporter')
5
+
6
+ run(process.argv.slice(2))
7
+ .then((exitCode) => process.exit(exitCode))
8
+ .catch((error) => {
9
+ console.error(error.message)
10
+ process.exit(1)
11
+ })
@@ -1,13 +1,11 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  ENV["RAILS_ENV"] ||= "development"
4
- ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", __FILE__)
4
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
5
+ ENV["APP_ROOT"] ||= File.expand_path("..", __dir__)
5
6
 
6
7
  require "bundler/setup"
7
8
  require "shakapacker"
8
- require "shakapacker/webpack_runner"
9
+ require "shakapacker/runner"
9
10
 
10
- APP_ROOT = File.expand_path("..", __dir__)
11
- Dir.chdir(APP_ROOT) do
12
- Shakapacker::WebpackRunner.run(ARGV)
13
- end
11
+ Shakapacker::Runner.run(ARGV)
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  ENV["RAILS_ENV"] ||= "development"
4
- ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", __FILE__)
4
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
5
5
 
6
6
  require "bundler/setup"
7
7
  require "shakapacker"
@@ -0,0 +1,6 @@
1
+ // See the shakacode/shakapacker README and docs directory for advice on customizing your rspackConfig.
2
+ const { generateRspackConfig } = require('shakapacker/rspack')
3
+
4
+ const rspackConfig = generateRspackConfig()
5
+
6
+ module.exports = rspackConfig
@@ -0,0 +1,7 @@
1
+ // See the shakacode/shakapacker README and docs directory for advice on customizing your rspackConfig.
2
+ import { generateRspackConfig } from 'shakapacker/rspack'
3
+ import type { RspackOptions } from '@rspack/core'
4
+
5
+ const rspackConfig: RspackOptions = generateRspackConfig()
6
+
7
+ export default rspackConfig
@@ -29,6 +29,10 @@ default: &default
29
29
  # Location for manifest.json, defaults to {public_output_path}/manifest.json if unset
30
30
  # manifest_path: public/packs/manifest.json
31
31
 
32
+ # Location for private server-side bundles (e.g., for SSR)
33
+ # These bundles are not served publicly, unlike public_output_path
34
+ # private_output_path: ssr-generated
35
+
32
36
  # Additional paths webpack should look up modules
33
37
  # ['app/assets', 'engine/foo/app/assets']
34
38
  additional_paths: []
@@ -36,13 +40,19 @@ default: &default
36
40
  # Reload manifest.json on all requests so we reload latest compiled packs
37
41
  cache_manifest: false
38
42
 
39
- # Select loader to use, available options are 'babel' (default), 'swc' or 'esbuild'
40
- webpack_loader: 'babel'
43
+ # Select JavaScript transpiler to use
44
+ # Available options: 'swc' (default, 20x faster), 'babel', or 'esbuild'
45
+ # Note: When using rspack, swc is used automatically regardless of this setting
46
+ javascript_transpiler: 'swc'
47
+
48
+ # Select assets bundler to use
49
+ # Available options: 'webpack' (default) or 'rspack'
50
+ assets_bundler: 'webpack'
41
51
 
42
52
  # Raises an error if there is a mismatch in the shakapacker gem and npm package being used
43
53
  ensure_consistent_versioning: true
44
54
 
45
- # Select whether the compiler will use SHA digest ('digest' option) or most most recent modified timestamp ('mtime') to determine freshness
55
+ # Select whether the compiler will use SHA digest ('digest' option) or most recent modified timestamp ('mtime') to determine freshness
46
56
  compiler_strategy: digest
47
57
 
48
58
  # Select whether the compiler will always use a content hash and not just in production
@@ -55,6 +65,16 @@ default: &default
55
65
  # SHAKAPACKER_ASSET_HOST will override both configurations.
56
66
  # asset_host: custom-path
57
67
 
68
+ # Utilizing webpack-subresource-integrity plugin, will generate integrity hashes for all entries in manifest.json
69
+ # https://github.com/waysact/webpack-subresource-integrity/tree/main/webpack-subresource-integrity
70
+ integrity:
71
+ enabled: false
72
+ # Which cryptographic function(s) to use, for generating the integrity hash(es). Default sha-384. Other possible values sha256, sha512
73
+ hash_functions: ["sha384"]
74
+ # Default "anonymous". Other possible value "use-credentials"
75
+ # https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity#cross-origin_resource_sharing_and_subresource_integrity
76
+ cross_origin: "anonymous"
77
+
58
78
  development:
59
79
  <<: *default
60
80
  compile: true
@@ -71,7 +91,7 @@ development:
71
91
  # Hot Module Replacement updates modules while the application is running without a full reload
72
92
  # Used instead of the `hot` key in https://webpack.js.org/configuration/dev-server/#devserverhot
73
93
  hmr: false
74
- # If HMR is on, CSS will by inlined by delivering it as part of the script payload via style-loader. Be sure
94
+ # If HMR is on, CSS will be inlined by delivering it as part of the script payload via style-loader. Be sure
75
95
  # that you add style-loader to your project dependencies.
76
96
  #
77
97
  # If you want to instead deliver CSS via <link> with the mini-css-extract-plugin, set inline_css to false.
@@ -114,7 +134,7 @@ production:
114
134
  # Production depends on precompilation of packs prior to booting for performance.
115
135
  compile: false
116
136
 
117
- # Use content hash for naming assets. Cannot be overridden by for production.
137
+ # Use content hash for naming assets. Cannot be overridden in production.
118
138
  useContentHash: true
119
139
 
120
140
  # Cache manifest.json for performance