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
@@ -0,0 +1,379 @@
1
+ # TypeScript Migration Guide for Shakapacker
2
+
3
+ This guide helps you adopt TypeScript types in your Shakapacker configuration files for better type safety and IDE support.
4
+
5
+ ## Table of Contents
6
+ - [Benefits](#benefits)
7
+ - [Quick Start](#quick-start)
8
+ - [Migration Steps](#migration-steps)
9
+ - [Common Patterns](#common-patterns)
10
+ - [Troubleshooting](#troubleshooting)
11
+
12
+ ## Benefits
13
+
14
+ Using TypeScript with Shakapacker provides:
15
+ - **Type Safety**: Catch configuration errors at compile time
16
+ - **IDE Support**: Get autocompletion and inline documentation
17
+ - **Better Refactoring**: Safely rename and restructure configurations
18
+ - **Self-documenting**: Types serve as inline documentation
19
+
20
+ ## Quick Start
21
+
22
+ ### 1. Install TypeScript Dependencies
23
+
24
+ ```bash
25
+ yarn add --dev typescript @types/node @types/webpack
26
+ # or
27
+ npm install --save-dev typescript @types/node @types/webpack
28
+ ```
29
+
30
+ ### 2. Create a tsconfig.json
31
+
32
+ ```json
33
+ {
34
+ "compilerOptions": {
35
+ "target": "ES2020",
36
+ "module": "commonjs",
37
+ "lib": ["ES2020"],
38
+ "strict": true,
39
+ "esModuleInterop": true,
40
+ "skipLibCheck": true,
41
+ "forceConsistentCasingInFileNames": true,
42
+ "resolveJsonModule": true,
43
+ "moduleResolution": "node",
44
+ "allowJs": true,
45
+ "checkJs": false,
46
+ "noEmit": true
47
+ },
48
+ "include": ["config/webpack/**/*"],
49
+ "exclude": ["node_modules"]
50
+ }
51
+ ```
52
+
53
+ ### 3. Convert Your Webpack Config to TypeScript
54
+
55
+ Rename `config/webpack/webpack.config.js` to `config/webpack/webpack.config.ts`:
56
+
57
+ ```typescript
58
+ // config/webpack/webpack.config.ts
59
+ import { generateWebpackConfig, merge } from 'shakapacker'
60
+ import type { WebpackConfigWithDevServer } from 'shakapacker/types'
61
+ import type { Configuration } from 'webpack'
62
+
63
+ const customConfig: Configuration = {
64
+ resolve: {
65
+ extensions: ['.css', '.ts', '.tsx']
66
+ }
67
+ }
68
+
69
+ const config: Configuration = generateWebpackConfig(customConfig)
70
+
71
+ export default config
72
+ ```
73
+
74
+ ## Migration Steps
75
+
76
+ ### Step 1: Import Types
77
+
78
+ Start by importing the types you need:
79
+
80
+ ```typescript
81
+ import type {
82
+ Config,
83
+ WebpackConfigWithDevServer,
84
+ RspackConfigWithDevServer,
85
+ CompressionPluginOptions
86
+ } from 'shakapacker/types'
87
+ ```
88
+
89
+ ### Step 2: Type Your Configuration Objects
90
+
91
+ Add type annotations to your configuration objects:
92
+
93
+ ```typescript
94
+ // Before (JavaScript)
95
+ const customConfig = {
96
+ resolve: {
97
+ extensions: ['.css', '.ts', '.tsx']
98
+ }
99
+ }
100
+
101
+ // After (TypeScript)
102
+ import type { Configuration } from 'webpack'
103
+
104
+ const customConfig: Configuration = {
105
+ resolve: {
106
+ extensions: ['.css', '.ts', '.tsx']
107
+ }
108
+ }
109
+ ```
110
+
111
+ ### Step 3: Type Your Custom Functions
112
+
113
+ If you have custom configuration functions, add type annotations:
114
+
115
+ ```typescript
116
+ // Before (JavaScript)
117
+ function modifyConfig(config) {
118
+ config.plugins.push(new MyPlugin())
119
+ return config
120
+ }
121
+
122
+ // After (TypeScript)
123
+ import type { Configuration } from 'webpack'
124
+ import type { WebpackPluginInstance } from 'shakapacker/types'
125
+
126
+ function modifyConfig(config: Configuration): Configuration {
127
+ const plugins = config.plugins as WebpackPluginInstance[]
128
+ plugins.push(new MyPlugin())
129
+ return config
130
+ }
131
+ ```
132
+
133
+ ### Step 4: Handle Environment-Specific Configurations
134
+
135
+ ```typescript
136
+ // config/webpack/development.ts
137
+ import { generateWebpackConfig } from 'shakapacker'
138
+ import type { WebpackConfigWithDevServer } from 'shakapacker/types'
139
+
140
+ const developmentConfig: WebpackConfigWithDevServer = generateWebpackConfig({
141
+ devtool: 'eval-cheap-module-source-map',
142
+ devServer: {
143
+ hot: true,
144
+ port: 3035
145
+ }
146
+ })
147
+
148
+ export default developmentConfig
149
+ ```
150
+
151
+ ## Common Patterns
152
+
153
+ ### Pattern 1: Custom Loaders
154
+
155
+ ```typescript
156
+ import type { RuleSetRule } from 'webpack'
157
+
158
+ const customLoader: RuleSetRule = {
159
+ test: /\.svg$/,
160
+ use: ['@svgr/webpack']
161
+ }
162
+
163
+ const config: Configuration = generateWebpackConfig({
164
+ module: {
165
+ rules: [customLoader]
166
+ }
167
+ })
168
+ ```
169
+
170
+ ### Pattern 2: Plugin Configuration
171
+
172
+ ```typescript
173
+ import CompressionPlugin from 'compression-webpack-plugin'
174
+ import type { CompressionPluginOptions } from 'shakapacker/types'
175
+
176
+ const compressionOptions: CompressionPluginOptions = {
177
+ filename: '[path][base].gz',
178
+ algorithm: 'gzip',
179
+ test: /\.(js|css|html|json|ico|svg|eot|otf|ttf)$/
180
+ }
181
+
182
+ const config: Configuration = generateWebpackConfig({
183
+ plugins: [new CompressionPlugin(compressionOptions)]
184
+ })
185
+ ```
186
+
187
+ ### Pattern 3: Conditional Configuration
188
+
189
+ ```typescript
190
+ import type { Configuration } from 'webpack'
191
+ import { env } from 'shakapacker'
192
+
193
+ const config: Configuration = generateWebpackConfig()
194
+
195
+ if (env.isProduction) {
196
+ // TypeScript knows config.optimization exists
197
+ config.optimization = {
198
+ ...config.optimization,
199
+ minimize: true,
200
+ sideEffects: false
201
+ }
202
+ }
203
+
204
+ export default config
205
+ ```
206
+
207
+ ### Pattern 4: Rspack Configuration
208
+
209
+ ```typescript
210
+ // config/rspack/rspack.config.ts
211
+ import type { RspackConfigWithDevServer } from 'shakapacker/types'
212
+ import { generateWebpackConfig } from 'shakapacker'
213
+
214
+ const rspackConfig: RspackConfigWithDevServer = generateWebpackConfig({
215
+ mode: 'development',
216
+ devServer: {
217
+ hot: true,
218
+ port: 3036
219
+ }
220
+ })
221
+
222
+ export default rspackConfig
223
+ ```
224
+
225
+ ## Type-checking Your Configuration
226
+
227
+ Add a script to your package.json to type-check your configuration:
228
+
229
+ ```json
230
+ {
231
+ "scripts": {
232
+ "type-check": "tsc --noEmit",
233
+ "webpack:type-check": "tsc --noEmit config/webpack/*.ts"
234
+ }
235
+ }
236
+ ```
237
+
238
+ Run type checking:
239
+
240
+ ```bash
241
+ yarn type-check
242
+ # or
243
+ npm run type-check
244
+ ```
245
+
246
+ ## Available Types Reference
247
+
248
+ ### Core Types
249
+ - `Config` - Shakapacker configuration from shakapacker.yml
250
+ - `Env` - Environment variables and helpers
251
+ - `DevServerConfig` - Development server configuration
252
+
253
+ ### Webpack/Rspack Types
254
+ - `WebpackConfigWithDevServer` - Webpack configuration with dev server
255
+ - `RspackConfigWithDevServer` - Rspack configuration with dev server
256
+ - `WebpackPluginInstance` - Webpack plugin instance type
257
+ - `RspackPluginInstance` - Rspack plugin instance type
258
+ - `RspackPlugin` - **⚠️ Deprecated:** Use `RspackPluginInstance` instead
259
+
260
+ ### Helper Types
261
+ - `CompressionPluginOptions` - Compression plugin configuration
262
+ - `ReactRefreshWebpackPlugin` - React refresh for Webpack
263
+ - `ReactRefreshRspackPlugin` - React refresh for Rspack
264
+
265
+ ## Troubleshooting
266
+
267
+ ### Issue: "Cannot find module 'shakapacker/types'"
268
+
269
+ **Solution**: Make sure you're using Shakapacker v9.0.0 or later:
270
+
271
+ ```bash
272
+ yarn upgrade shakapacker
273
+ ```
274
+
275
+ ### Issue: Type errors with plugins
276
+
277
+ **Solution**: Cast plugin arrays when needed:
278
+
279
+ ```typescript
280
+ const plugins = (config.plugins || []) as WebpackPluginInstance[]
281
+ plugins.push(new MyPlugin())
282
+ ```
283
+
284
+ ### Issue: Missing types for custom loaders
285
+
286
+ **Solution**: Install type definitions or declare them:
287
+
288
+ ```typescript
289
+ // If types aren't available, declare them
290
+ declare module 'my-custom-loader' {
291
+ const loader: any
292
+ export default loader
293
+ }
294
+ ```
295
+
296
+ ### Issue: Conflicting types between webpack versions
297
+
298
+ **Solution**: Ensure your webpack types match your webpack version:
299
+
300
+ ```bash
301
+ yarn add --dev @types/webpack@^5
302
+ ```
303
+
304
+ ## Gradual Migration
305
+
306
+ You don't need to convert everything at once. Start with:
307
+
308
+ 1. Convert your main webpack.config.js to TypeScript
309
+ 2. Add types to the most complex configurations
310
+ 3. Gradually type other configuration files
311
+ 4. Add type checking to your CI pipeline
312
+
313
+ ## Example: Full Configuration
314
+
315
+ Here's a complete example of a typed webpack configuration:
316
+
317
+ ```typescript
318
+ // config/webpack/webpack.config.ts
319
+ import { generateWebpackConfig, merge, config as shakapackerConfig } from 'shakapacker'
320
+ import type { Configuration } from 'webpack'
321
+ import type { WebpackConfigWithDevServer } from 'shakapacker/types'
322
+ import CompressionPlugin from 'compression-webpack-plugin'
323
+ import { resolve } from 'path'
324
+
325
+ // Type-safe custom configuration
326
+ const customConfig: Configuration = {
327
+ resolve: {
328
+ extensions: ['.css', '.ts', '.tsx'],
329
+ alias: {
330
+ '@': resolve(__dirname, '../../app/javascript'),
331
+ 'components': resolve(__dirname, '../../app/javascript/components'),
332
+ 'utils': resolve(__dirname, '../../app/javascript/utils')
333
+ }
334
+ },
335
+ module: {
336
+ rules: [
337
+ {
338
+ test: /\.svg$/,
339
+ use: ['@svgr/webpack'],
340
+ issuer: /\.(tsx?|jsx?)$/
341
+ }
342
+ ]
343
+ }
344
+ }
345
+
346
+ // Generate the final configuration
347
+ const webpackConfig: Configuration = generateWebpackConfig(customConfig)
348
+
349
+ // Type-safe modifications based on environment
350
+ if (shakapackerConfig.env === 'production') {
351
+ const plugins = (webpackConfig.plugins || []) as WebpackPluginInstance[]
352
+
353
+ plugins.push(
354
+ new CompressionPlugin({
355
+ filename: '[path][base].br',
356
+ algorithm: 'brotliCompress',
357
+ test: /\.(js|css|html|json|ico|svg|eot|otf|ttf)$/
358
+ })
359
+ )
360
+ }
361
+
362
+ export default webpackConfig
363
+ ```
364
+
365
+ ## Next Steps
366
+
367
+ After migrating to TypeScript:
368
+
369
+ 1. **Enable strict checks**: Gradually enable stricter TypeScript options
370
+ 2. **Add custom types**: Create type definitions for your application-specific configurations
371
+ 3. **Share types**: Export reusable configuration types for your team
372
+ 4. **Document with types**: Use JSDoc comments with your types for better documentation
373
+
374
+ ## Resources
375
+
376
+ - [TypeScript Handbook](https://www.typescriptlang.org/docs/handbook/intro.html)
377
+ - [Webpack TypeScript Configuration](https://webpack.js.org/configuration/configuration-languages/#typescript)
378
+ - [Shakapacker Types Documentation](./types/README.md)
379
+ - [Migration Examples](https://github.com/shakacode/shakapacker/tree/main/examples/typescript-config)
@@ -0,0 +1,99 @@
1
+ # TypeScript Support
2
+
3
+ Shakapacker v9 includes TypeScript support, providing type safety and better IDE experience for your webpack configurations.
4
+
5
+ ## Quick Start
6
+
7
+ ### Using TypeScript Config
8
+
9
+ ```typescript
10
+ // webpack.config.ts
11
+ import { generateWebpackConfig } from 'shakapacker'
12
+ import type { Configuration } from 'webpack'
13
+
14
+ const config: Configuration = generateWebpackConfig({
15
+ // Your config with full type safety
16
+ })
17
+
18
+ export default config
19
+ ```
20
+
21
+ ### Using JSDoc (JavaScript)
22
+
23
+ ```javascript
24
+ // webpack.config.js
25
+ const { generateWebpackConfig } = require('shakapacker')
26
+
27
+ /** @type {import('webpack').Configuration} */
28
+ const config = {
29
+ // Still get autocomplete in JS files!
30
+ }
31
+
32
+ module.exports = generateWebpackConfig(config)
33
+ ```
34
+
35
+ ## Benefits
36
+
37
+ - **Compile-time error detection** - Catch config errors before runtime
38
+ - **IDE autocomplete** - Full IntelliSense for all options
39
+ - **Type safety** - Prevents 85-100% of common configuration errors
40
+ - **No breaking changes** - Fully backward compatible
41
+
42
+ ## Migration
43
+
44
+ 1. **No migration required** - Existing JavaScript configs continue to work
45
+ 2. **Optional TypeScript** - Use it only if you want the benefits
46
+ 3. **Gradual adoption** - Start with JSDoc comments, move to TypeScript later
47
+
48
+ ## IDE Setup
49
+
50
+ ### VS Code
51
+ - Install TypeScript extension (built-in)
52
+ - Set `"typescript.tsdk": "node_modules/typescript/lib"` in settings
53
+
54
+ ### WebStorm/IntelliJ
55
+ - Enable TypeScript service in Settings → Languages & Frameworks → TypeScript
56
+
57
+ ## Common Patterns
58
+
59
+ ### Environment-Specific Config
60
+
61
+ ```typescript
62
+ import { generateWebpackConfig, env } from 'shakapacker'
63
+
64
+ const config = generateWebpackConfig({
65
+ optimization: {
66
+ minimize: env.isProduction
67
+ }
68
+ })
69
+ ```
70
+
71
+ ### Rspack Config
72
+
73
+ ```typescript
74
+ import { generateRspackConfig } from 'shakapacker/rspack'
75
+ import type { RspackOptions } from '@rspack/core'
76
+
77
+ const config: RspackOptions = {
78
+ // Rspack-specific config
79
+ }
80
+
81
+ export default generateRspackConfig(config)
82
+ ```
83
+
84
+ ## Troubleshooting
85
+
86
+ **Cannot find module 'shakapacker'**
87
+ ```typescript
88
+ /// <reference types="shakapacker" />
89
+ ```
90
+
91
+ **Type errors with custom loaders**
92
+ ```typescript
93
+ use: [require.resolve('custom-loader') as any]
94
+ ```
95
+
96
+ ## Further Reading
97
+
98
+ - [Webpack TypeScript Documentation](https://webpack.js.org/configuration/configuration-languages/#typescript)
99
+ - [TypeScript Handbook](https://www.typescriptlang.org/docs/)
@@ -27,7 +27,7 @@ To use esbuild as your transpiler today. You need to do two things:
27
27
  npm install esbuild esbuild-loader
28
28
  ```
29
29
 
30
- 2. Add or change `webpack_loader` value in your default `shakapacker.yml` config to `esbuild`
30
+ 2. Add or change `javascript_transpiler` value in your default `shakapacker.yml` config to `esbuild`
31
31
  The default configuration of babel is done by using `package.json` to use the file within the `shakapacker` package.
32
32
 
33
33
  ```yml
@@ -46,8 +46,8 @@ default: &default
46
46
  # Reload manifest.json on all requests so we reload latest compiled packs
47
47
  cache_manifest: false
48
48
 
49
- # Select loader to use, available options are 'babel' (default), 'swc' or 'esbuild'
50
- webpack_loader: 'esbuild'
49
+ # Select JavaScript transpiler to use, available options are 'babel' (default), 'swc' or 'esbuild'
50
+ javascript_transpiler: 'esbuild'
51
51
  ```
52
52
 
53
53
  ### (Optional) Replace minification with esbuild
@@ -12,6 +12,8 @@ It supports all ECMAScript features and it's designed to be a drop-in replacemen
12
12
 
13
13
  For comparison between SWC and Babel, see the docs at https://swc.rs/docs/migrating-from-babel.
14
14
 
15
+ > **Note:** SWC is also natively built into RSpack bundler, providing even faster compilation speeds. When using RSpack (`assets_bundler: 'rspack'`), SWC is used automatically regardless of the `javascript_transpiler` setting.
16
+
15
17
  ## Switching your Shakapacker project to SWC
16
18
 
17
19
  In order to use SWC as your compiler today. You need to do two things:
@@ -22,8 +24,8 @@ In order to use SWC as your compiler today. You need to do two things:
22
24
  npm install @swc/core swc-loader
23
25
  ```
24
26
 
25
- 2. Add or change `webpack_loader` value in your default `shakapacker.yml` config to `swc`
26
- The default configuration of babel is done by using `package.json` to use the file within the `shakapacker` package.
27
+ 2. Add or change `javascript_transpiler` value in your default `shakapacker.yml` config to `swc`
28
+ The default configuration of babel is done by using `package.json` to use the file within the `shakapacker` package.
27
29
 
28
30
  ```yml
29
31
  default: &default
@@ -41,8 +43,8 @@ default: &default
41
43
  # Reload manifest.json on all requests so we reload latest compiled packs
42
44
  cache_manifest: false
43
45
 
44
- # Select loader to use, available options are 'babel' (default) or 'swc'
45
- webpack_loader: 'swc'
46
+ # Select JavaScript transpiler to use, available options are 'babel' (default) or 'swc'
47
+ javascript_transpiler: "swc"
46
48
  ```
47
49
 
48
50
  ## Usage
@@ -71,7 +73,6 @@ See some examples below of potential `config/swc.config.js`.
71
73
 
72
74
  ### Example: Enabling top level await and decorators
73
75
 
74
-
75
76
  ```js
76
77
  const customConfig = {
77
78
  options: {
@@ -90,7 +91,7 @@ module.exports = customConfig
90
91
  ### Example: Matching existing `@babel/present-env` config
91
92
 
92
93
  ```js
93
- const { env } = require('shakapacker')
94
+ const { env } = require("shakapacker")
94
95
 
95
96
  const customConfig = {
96
97
  options: {
@@ -112,9 +113,8 @@ module.exports = customConfig
112
113
 
113
114
  :warning: Remember that you still need to add [@pmmmwh/react-refresh-webpack-plugin](https://github.com/pmmmwh/react-refresh-webpack-plugin) to your webpack config. The setting below just replaces equivalent `react-refresh/babel` Babel plugin.
114
115
 
115
-
116
116
  ```js
117
- const { env } = require('shakapacker')
117
+ const { env } = require("shakapacker")
118
118
 
119
119
  const customConfig = {
120
120
  options: {
@@ -134,11 +134,10 @@ module.exports = customConfig
134
134
  ### Example: Adding browserslist config
135
135
 
136
136
  ```js
137
-
138
137
  const customConfig = {
139
138
  options: {
140
139
  env: {
141
- targets: '> 0.25%, not dead'
140
+ targets: "> 0.25%, not dead"
142
141
  }
143
142
  }
144
143
  }
@@ -146,6 +145,109 @@ const customConfig = {
146
145
  module.exports = customConfig
147
146
  ```
148
147
 
148
+ ## Using SWC with Stimulus
149
+
150
+ ⚠️ **Important:** If you're using [Stimulus](https://stimulus.hotwired.dev/), you need to configure SWC to preserve class names.
151
+
152
+ ### Required Configuration
153
+
154
+ SWC mangles (minifies) class names by default for optimization. Since Stimulus relies on class names to discover and instantiate controllers, you must preserve class names in your `config/swc.config.js`:
155
+
156
+ ```js
157
+ // config/swc.config.js
158
+ const { env } = require("shakapacker")
159
+
160
+ module.exports = {
161
+ options: {
162
+ jsc: {
163
+ // CRITICAL for Stimulus: Prevents SWC from mangling class names
164
+ keepClassNames: true,
165
+ transform: {
166
+ react: {
167
+ runtime: "automatic",
168
+ refresh: env.isDevelopment && env.runningWebpackDevServer
169
+ }
170
+ }
171
+ }
172
+ }
173
+ }
174
+ ```
175
+
176
+ **Note:** Starting with Shakapacker v9.1.0, the default `swc.config.js` created by `rake shakapacker:migrate_to_swc` includes `keepClassNames: true` automatically.
177
+
178
+ ### Why This Matters
179
+
180
+ Without `keepClassNames: true`, your Stimulus controllers will:
181
+
182
+ - Load without errors in the browser console
183
+ - Fail silently at runtime
184
+ - Not respond to events
185
+ - Not update the DOM as expected
186
+
187
+ This makes debugging very difficult since there are no visible JavaScript errors.
188
+
189
+ ### Symptoms of Missing Configuration
190
+
191
+ If your Stimulus controllers aren't working after migrating to SWC, you'll typically see test failures like:
192
+
193
+ ```
194
+ Failure/Error: expect(page).to have_text("Author: can't be blank")
195
+ expected to be truthy, got false
196
+
197
+ Failure/Error: expect(page).to have_css("h2", text: comment.author)
198
+ expected to be truthy, got false
199
+ ```
200
+
201
+ Your controllers appear to load but don't function correctly:
202
+
203
+ - Form submissions don't work
204
+ - Validation error messages don't appear
205
+ - Dynamic content doesn't get added to the page
206
+ - No JavaScript errors appear in the console
207
+
208
+ ### Common Configuration Error
209
+
210
+ ❌ **Error:** `` `env` and `jsc.target` cannot be used together``
211
+
212
+ If you see this error:
213
+
214
+ ```
215
+ ERROR in ./client/app/packs/stimulus-bundle.js
216
+ Module build failed (from ./node_modules/swc-loader/src/index.js):
217
+ Error:
218
+
219
+ Caused by:
220
+ `env` and `jsc.target` cannot be used together
221
+ ```
222
+
223
+ **Solution:** Do NOT add `jsc.target` to your configuration. Shakapacker already sets `env` for browser targeting. Use `env` OR `jsc.target`, never both.
224
+
225
+ ❌ **Incorrect:**
226
+
227
+ ```js
228
+ jsc: {
229
+ target: 'es2015', // Don't add this!
230
+ keepClassNames: true,
231
+ }
232
+ ```
233
+
234
+ ✅ **Correct:**
235
+
236
+ ```js
237
+ jsc: {
238
+ keepClassNames: true, // No target specified
239
+ }
240
+ ```
241
+
242
+ ### Troubleshooting Checklist
243
+
244
+ If your Stimulus controllers aren't working after migrating to SWC:
245
+
246
+ 1. ✅ Verify `keepClassNames: true` is set in `config/swc.config.js`
247
+ 2. ✅ Ensure your controllers have explicit class names (not anonymous classes)
248
+ 3. ✅ Test with `console.log()` in your controller's `connect()` method to verify it's being instantiated
249
+ 4. ✅ Check that you haven't added `jsc.target` (which conflicts with Shakapacker's `env` setting)
250
+ 5. ✅ Rebuild your assets: `bin/shakapacker clobber && bin/shakapacker compile`
149
251
 
150
252
  ## Known limitations
151
253
 
data/docs/v6_upgrade.md CHANGED
@@ -101,6 +101,16 @@ _If you're on webpacker v5, follow [how to upgrade to webpacker v6.0.0.rc.6 from
101
101
 
102
102
  1. Update `webpack-dev-server` to the current version, greater than 4.2, updating `package.json`.
103
103
 
104
+ **Important:** If you encounter the error `[webpack-cli] Invalid options object. Dev Server has been initialized using an options object that does not match the API schema` with an unknown property `_assetEmittingPreviousFiles`, this indicates your webpack-dev-server configuration contains deprecated options.
105
+
106
+ To resolve this issue:
107
+ - Ensure you're using webpack-cli >= 4.7.0 with webpack-dev-server 5.x (webpack-cli 4.7+ is compatible with webpack-dev-server v5)
108
+ - Check your current versions: `npm list webpack-cli webpack-dev-server`
109
+ - Remove any legacy options like `_assetEmittingPreviousFiles` from your dev-server configuration
110
+ - Review the [webpack-dev-server migration guide](https://github.com/webpack/webpack-dev-server/blob/master/migration-v5.md) for proper v4 to v5 migration steps
111
+
112
+ See [issue #526](https://github.com/shakacode/shakapacker/issues/526) for more details.
113
+
104
114
  1. Update API usage of the view helpers by changing `javascript_packs_with_chunks_tag` and `stylesheet_packs_with_chunks_tag` to `javascript_pack_tag` and `stylesheet_pack_tag`. Ensure that your layouts and views will only have **at most one call** to `javascript_pack_tag` and **at most one call** to `stylesheet_pack_tag`. You can now pass multiple bundles to these view helper methods. If you fail to changes this, you may experience performance issues, and other bugs related to multiple copies of React, like [issue 2932](https://github.com/rails/webpacker/issues/2932). If you expose jquery globally with `expose-loader` by using `import $ from "expose-loader?exposes=$,jQuery!jquery"` in your `app/javascript/application.js`, pass the option `defer: false` to your `javascript_pack_tag`.
105
115
 
106
116
  1. If you are using any integrations like `css`, `postcss`, `React` or `TypeScript`. Please see https://github.com/shakacode/shakapacker#integrations section on how they work in v6.