shakapacker 9.0.0 → 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 (47) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -0
  3. data/CHANGELOG.md +108 -11
  4. data/Gemfile.lock +1 -1
  5. data/README.md +182 -107
  6. data/bin/export-bundler-config +11 -0
  7. data/docs/common-upgrades.md +615 -0
  8. data/docs/deployment.md +52 -8
  9. data/docs/releasing.md +197 -0
  10. data/docs/rspack_migration_guide.md +120 -17
  11. data/docs/transpiler-migration.md +21 -0
  12. data/docs/troubleshooting.md +124 -23
  13. data/docs/typescript-migration.md +2 -1
  14. data/docs/using_swc_loader.md +108 -8
  15. data/docs/v9_upgrade.md +45 -0
  16. data/lib/install/bin/export-bundler-config +11 -0
  17. data/lib/install/bin/shakapacker +1 -1
  18. data/lib/install/bin/shakapacker-dev-server +1 -1
  19. data/lib/shakapacker/bundler_switcher.rb +329 -0
  20. data/lib/shakapacker/configuration.rb +28 -2
  21. data/lib/shakapacker/doctor.rb +65 -4
  22. data/lib/shakapacker/rspack_runner.rb +1 -1
  23. data/lib/shakapacker/runner.rb +1 -1
  24. data/lib/shakapacker/swc_migrator.rb +14 -6
  25. data/lib/shakapacker/version.rb +1 -1
  26. data/lib/shakapacker/webpack_runner.rb +1 -1
  27. data/lib/shakapacker.rb +10 -0
  28. data/lib/tasks/shakapacker/export_bundler_config.rake +72 -0
  29. data/lib/tasks/shakapacker/switch_bundler.rake +82 -0
  30. data/lib/tasks/shakapacker.rake +2 -1
  31. data/package/configExporter/cli.ts +683 -0
  32. data/package/configExporter/configDocs.ts +102 -0
  33. data/package/configExporter/fileWriter.ts +92 -0
  34. data/package/configExporter/index.ts +5 -0
  35. data/package/configExporter/types.ts +36 -0
  36. data/package/configExporter/yamlSerializer.ts +266 -0
  37. data/package/environments/__type-tests__/rspack-plugin-compatibility.ts +30 -0
  38. data/package/environments/types.ts +22 -14
  39. data/package/index.ts +12 -9
  40. data/package/swc/index.ts +5 -3
  41. data/package/types/README.md +2 -1
  42. data/package/types/index.ts +1 -0
  43. data/package/utils/debug.ts +5 -5
  44. data/package-lock.json +13047 -0
  45. data/package.json +7 -1
  46. data/yarn.lock +261 -389
  47. metadata +17 -2
@@ -17,12 +17,72 @@
17
17
 
18
18
  4. You can also pass additional options to the command to run the webpack-dev-server and start the webpack-dev-server with the option `--debug-shakapacker`
19
19
 
20
- 5. ChatGPT and other AI tools can consume this output file. Change the NODE_ENV per your needs. Then upload the file to your favorite AI tool.
20
+ 5. **Export your full webpack/rspack configuration for analysis**: Use the `bin/export-bundler-config` utility to export your complete resolved configuration. This is especially helpful for:
21
+
22
+ - **Migrations**: Comparing configurations before and after migrating between webpack and rspack, or between different Shakapacker versions
23
+ - **Debugging**: Inspecting the exact configuration webpack/rspack is using, including all merged settings
24
+ - **AI Analysis**: Uploading the exported config to ChatGPT or other AI tools for troubleshooting
25
+
26
+ **Installation**: The utility is installed when you run `rake shakapacker:binstubs` or can be used directly via `rake shakapacker:export_bundler_config`.
27
+
28
+ **RECOMMENDED - Quick troubleshooting:**
29
+
30
+ ```bash
31
+ # Install the binstub (one-time setup)
32
+ rake shakapacker:binstubs
33
+
34
+ # Export EVERYTHING for troubleshooting (dev + prod, annotated YAML)
35
+ bin/export-bundler-config --doctor
36
+ # Creates: webpack-development-client.yaml, webpack-development-server.yaml,
37
+ # webpack-production-client.yaml, webpack-production-server.yaml
38
+ ```
39
+
40
+ **Other usage examples:**
41
+
42
+ ```bash
43
+ # Save current environment configs with auto-generated names
44
+ bin/export-bundler-config --save
45
+ # Creates: webpack-development-client.yaml, webpack-development-server.yaml
46
+
47
+ # Save to specific directory
48
+ bin/export-bundler-config --save --save-dir=./debug-configs
49
+
50
+ # Export only client config for production
51
+ bin/export-bundler-config --save --env=production --client-only
52
+ # Creates: webpack-production-client.yaml
53
+
54
+ # Compare development vs production configs
55
+ bin/export-bundler-config --save --save-dir=./configs
56
+ diff configs/webpack-development-client.yaml configs/webpack-production-client.yaml
57
+
58
+ # View config in terminal (no files created)
59
+ bin/export-bundler-config
60
+
61
+ # Export without inline documentation annotations
62
+ bin/export-bundler-config --save --no-annotate
63
+
64
+ # Export in JSON format for programmatic analysis
65
+ bin/export-bundler-config --save --format=json
21
66
  ```
67
+
68
+ **Config files are automatically named:** `{bundler}-{env}-{type}.{ext}`
69
+
70
+ - Examples: `webpack-development-client.yaml`, `rspack-production-server.yaml`
71
+ - YAML format includes inline documentation explaining each config key
72
+ - Separate files for client and server bundles (cleaner than combined)
73
+
74
+ See `bin/export-bundler-config --help` for all available options.
75
+
76
+ 6. Generate webpack stats for build analysis (useful for bundle size optimization):
77
+
78
+ ```bash
22
79
  NODE_ENV=development bin/shakapacker --profile --json > /tmp/webpack-stats.json
23
80
  ```
24
81
 
82
+ ChatGPT and other AI tools can consume this output file. Change the NODE_ENV per your needs.
83
+
25
84
  ## Incorrect peer dependencies
85
+
26
86
  Shakapacker uses peer dependencies to make it easier to manage what versions are being used for your app, which is especially
27
87
  useful for patching security vulnerabilities. However, not all package managers will actually enforce these versions - notably,
28
88
  Yarn will omit a warning rather than erroring if you forget to update a peer dependency:
@@ -32,6 +92,7 @@ warning " > shakapacker@6.1.1" has incorrect peer dependency "compression-webpac
32
92
  ```
33
93
 
34
94
  This omission resulted in an error in the browser:
95
+
35
96
  ```
36
97
  Failed to load resource: net::ERR_CONTENT_DECODING_FAILED
37
98
  ```
@@ -40,6 +101,40 @@ The error was caused by an old version of the peer dependency `webpack-compressi
40
101
 
41
102
  So, be sure to investigate warnings from `yarn install`!
42
103
 
104
+ ## NoMethodError: undefined method 'deep_symbolize_keys' for nil:NilClass
105
+
106
+ If you see this error during deployment (especially on Heroku with a staging environment):
107
+
108
+ ```
109
+ NoMethodError: undefined method 'deep_symbolize_keys' for nil:NilClass
110
+ from shakapacker/configuration.rb:XXX:in 'load'
111
+ ```
112
+
113
+ This happens when deploying to a custom Rails environment (like `staging`) that isn't explicitly defined in your `config/shakapacker.yml` file.
114
+
115
+ **Solution:** This was fixed in Shakapacker v9.1.1+. Upgrade to the latest version:
116
+
117
+ ```ruby
118
+ # Gemfile
119
+ gem 'shakapacker', '~> 9.1'
120
+ ```
121
+
122
+ After upgrading, Shakapacker will automatically fall back to sensible defaults when your environment isn't defined:
123
+
124
+ 1. First tries your environment (e.g., `staging`)
125
+ 2. Falls back to `production` configuration
126
+
127
+ **Alternative:** If you can't upgrade immediately, explicitly add your environment to `config/shakapacker.yml`:
128
+
129
+ ```yaml
130
+ staging:
131
+ <<: *default
132
+ compile: false
133
+ cache_manifest: true
134
+ ```
135
+
136
+ See the [deployment guide](./deployment.md#custom-rails-environments-eg-staging) for more details.
137
+
43
138
  ## ENOENT: no such file or directory - node-sass
44
139
 
45
140
  If you get the error `ENOENT: no such file or directory - node-sass` on deploy with
@@ -54,7 +149,7 @@ thing, like Heroku.
54
149
 
55
150
  However, if you get this on local development, or not during a deploy then you
56
151
  may need to rebuild `node-sass`. It's a bit of a weird error; basically, it
57
- can't find the `node-sass` binary. An easy solution is to create a postinstall
152
+ can't find the `node-sass` binary. An easy solution is to create a postinstall
58
153
  hook to ensure `node-sass` is rebuilt whenever new modules are installed.
59
154
 
60
155
  In `package.json`:
@@ -67,19 +162,18 @@ In `package.json`:
67
162
 
68
163
  ## Can't find hello_react.js in manifest.json
69
164
 
70
- * If you get this error `Can't find hello_react.js in manifest.json`
71
- when loading a view in the browser it's because webpack is still compiling packs.
72
- Shakapacker uses a `manifest.json` file to keep track of packs in all environments,
73
- however since this file is generated after packs are compiled by webpack. So,
74
- if you load a view in browser whilst webpack is compiling you will get this error.
75
- Therefore, make sure webpack
76
- (i.e `./bin/shakapacker-dev-server`) is running and has
77
- completed the compilation successfully before loading a view.
78
-
165
+ - If you get this error `Can't find hello_react.js in manifest.json`
166
+ when loading a view in the browser it's because webpack is still compiling packs.
167
+ Shakapacker uses a `manifest.json` file to keep track of packs in all environments,
168
+ however since this file is generated after packs are compiled by webpack. So,
169
+ if you load a view in browser whilst webpack is compiling you will get this error.
170
+ Therefore, make sure webpack
171
+ (i.e `./bin/shakapacker-dev-server`) is running and has
172
+ completed the compilation successfully before loading a view.
79
173
 
80
174
  ## throw er; // Unhandled 'error' event
81
175
 
82
- * If you get this error while trying to use Elm, try rebuilding Elm. You can do
176
+ - If you get this error while trying to use Elm, try rebuilding Elm. You can do
83
177
  so with a postinstall hook in your `package.json`:
84
178
 
85
179
  ```json
@@ -90,9 +184,9 @@ completed the compilation successfully before loading a view.
90
184
 
91
185
  ## webpack or webpack-dev-server not found
92
186
 
93
- * This could happen if `shakapacker:install` step is skipped. Please run `bundle exec rails shakapacker:install` to fix the issue.
187
+ - This could happen if `shakapacker:install` step is skipped. Please run `bundle exec rails shakapacker:install` to fix the issue.
94
188
 
95
- * If you encounter the above error on heroku after upgrading from Rails 4.x to 5.1.x, then the problem might be related to missing `yarn` binstub. Please run following commands to update/add binstubs:
189
+ - If you encounter the above error on heroku after upgrading from Rails 4.x to 5.1.x, then the problem might be related to missing `yarn` binstub. Please run following commands to update/add binstubs:
96
190
 
97
191
  ```bash
98
192
  bundle config --delete bin
@@ -137,6 +231,7 @@ chmod +x $HOME/your_rails_app/node_modules/.bin/elm-make
137
231
  ```
138
232
 
139
233
  ## Rake assets:precompile fails. ExecJS::RuntimeError
234
+
140
235
  This error occurs because you are trying to minify by `terser` a pack that's already been minified by Shakapacker. To avoid this conflict and prevent appearing of `ExecJS::RuntimeError` error, you will need to disable uglifier from Rails config:
141
236
 
142
237
  ```ruby
@@ -152,10 +247,11 @@ Rails.application.config.assets.js_compressor = Uglifier.new(harmony: true)
152
247
  ### Angular: WARNING in ./node_modules/@angular/core/esm5/core.js, Critical dependency: the request of a dependency is an expression
153
248
 
154
249
  To silent these warnings, please update `config/webpack/webpack.config.js`:
250
+
155
251
  ```js
156
- const webpack = require('webpack')
157
- const { resolve } = require('path')
158
- const { generateWebpackConfig } = require('shakapacker')
252
+ const webpack = require("webpack")
253
+ const { resolve } = require("path")
254
+ const { generateWebpackConfig } = require("shakapacker")
159
255
 
160
256
  module.exports = generateWebpackConfig({
161
257
  plugins: [
@@ -192,6 +288,7 @@ Thus ProvidePlugin manages build-time dependencies to global symbols whereas the
192
288
  **You don't need to assign dependencies on `window`.**
193
289
 
194
290
  For instance, with [jQuery](https://jquery.com/):
291
+
195
292
  ```diff
196
293
  // app/javascript/entrypoints/application.js
197
294
 
@@ -200,19 +297,20 @@ For instance, with [jQuery](https://jquery.com/):
200
297
  ```
201
298
 
202
299
  Instead do:
300
+
203
301
  ```js
204
302
  // config/webpack/webpack.config.js
205
303
 
206
- const webpack = require('webpack')
207
- const { generateWebpackConfig } = require('shakapacker')
304
+ const webpack = require("webpack")
305
+ const { generateWebpackConfig } = require("shakapacker")
208
306
 
209
307
  module.exports = generateWebpackConfig({
210
308
  plugins: [
211
309
  new webpack.ProvidePlugin({
212
- $: 'jquery',
213
- jQuery: 'jquery',
310
+ $: "jquery",
311
+ jQuery: "jquery"
214
312
  })
215
- ],
313
+ ]
216
314
  })
217
315
  ```
218
316
 
@@ -225,7 +323,7 @@ application is using your staging `config.asset_host` host when using
225
323
 
226
324
  This can be fixed by setting the environment variable `SHAKAPACKER_ASSET_HOST` to
227
325
  an empty string where your assets are compiled. On Heroku this is done under
228
- *Settings* -> *Config Vars*.
326
+ _Settings_ -> _Config Vars_.
229
327
 
230
328
  This way shakapacker won't hard-code the CDN host into the manifest file used by
231
329
  `javascript_pack_tag`, but instead fetch the CDN host at runtime, resolving the
@@ -243,6 +341,7 @@ In order to generate the storage path, we rely on the filename that's [provided
243
341
  This usually works out of the box. There's a potential problem however, if you use the [context setting](https://webpack.js.org/configuration/entry-context/#context) in your webpack config. By default this is set to current Node working directory/project root.
244
342
 
245
343
  If you were to override it like:
344
+
246
345
  ```
247
346
  {
248
347
  context: path.resolve(__dirname, '../../app/javascript')
@@ -252,12 +351,14 @@ If you were to override it like:
252
351
  Then the filename available in the rule generator will be relative to that directory.
253
352
 
254
353
  This means for example:
354
+
255
355
  - a static asset from `node_modules` folder could end up being referenced with path of `../../node_modules/some_module/static_file.jpg` rather than simply `node_modules/some_module/static_file.jpg`.
256
356
  - a static asset in one of the `additional_paths`, example `app/assets/images/image.jpg`, would end up being referenced with path of `../assets/images/image.jpg`.
257
357
 
258
358
  Those paths are later passed to [output path generation in the rule](https://github.com/shakacode/shakapacker/blob/e52b335dbabfb934fe7d3076a8322b97d5ef3470/package/rules/file.js#L25-L26), where we would end up with a path like `static/../../node_modules/some_module/static_file.jpg`, resulting in the file being output in a location two directories above the desired path.
259
359
 
260
360
  You can avoid this by:
361
+
261
362
  - not using overridden `context` in your webpack config, if there's no good reason for it.
262
363
  - using custom Webpack config to modify the static file rule, following a similar process as outlined in the [Webpack Configuration](https://github.com/shakacode/shakapacker/blob/main/README.md#webpack-configuration) section of the readme.
263
364
 
@@ -254,7 +254,8 @@ npm run type-check
254
254
  - `WebpackConfigWithDevServer` - Webpack configuration with dev server
255
255
  - `RspackConfigWithDevServer` - Rspack configuration with dev server
256
256
  - `WebpackPluginInstance` - Webpack plugin instance type
257
- - `RspackPlugin` - Rspack plugin interface
257
+ - `RspackPluginInstance` - Rspack plugin instance type
258
+ - `RspackPlugin` - **⚠️ Deprecated:** Use `RspackPluginInstance` instead
258
259
 
259
260
  ### Helper Types
260
261
  - `CompressionPluginOptions` - Compression plugin configuration
@@ -25,7 +25,7 @@ npm install @swc/core swc-loader
25
25
  ```
26
26
 
27
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.
28
+ The default configuration of babel is done by using `package.json` to use the file within the `shakapacker` package.
29
29
 
30
30
  ```yml
31
31
  default: &default
@@ -44,7 +44,7 @@ default: &default
44
44
  cache_manifest: false
45
45
 
46
46
  # Select JavaScript transpiler to use, available options are 'babel' (default) or 'swc'
47
- javascript_transpiler: 'swc'
47
+ javascript_transpiler: "swc"
48
48
  ```
49
49
 
50
50
  ## Usage
@@ -73,7 +73,6 @@ See some examples below of potential `config/swc.config.js`.
73
73
 
74
74
  ### Example: Enabling top level await and decorators
75
75
 
76
-
77
76
  ```js
78
77
  const customConfig = {
79
78
  options: {
@@ -92,7 +91,7 @@ module.exports = customConfig
92
91
  ### Example: Matching existing `@babel/present-env` config
93
92
 
94
93
  ```js
95
- const { env } = require('shakapacker')
94
+ const { env } = require("shakapacker")
96
95
 
97
96
  const customConfig = {
98
97
  options: {
@@ -114,9 +113,8 @@ module.exports = customConfig
114
113
 
115
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.
116
115
 
117
-
118
116
  ```js
119
- const { env } = require('shakapacker')
117
+ const { env } = require("shakapacker")
120
118
 
121
119
  const customConfig = {
122
120
  options: {
@@ -136,11 +134,10 @@ module.exports = customConfig
136
134
  ### Example: Adding browserslist config
137
135
 
138
136
  ```js
139
-
140
137
  const customConfig = {
141
138
  options: {
142
139
  env: {
143
- targets: '> 0.25%, not dead'
140
+ targets: "> 0.25%, not dead"
144
141
  }
145
142
  }
146
143
  }
@@ -148,6 +145,109 @@ const customConfig = {
148
145
  module.exports = customConfig
149
146
  ```
150
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`
151
251
 
152
252
  ## Known limitations
153
253
 
data/docs/v9_upgrade.md CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  This guide outlines new features, breaking changes, and migration steps for upgrading from Shakapacker v8 to v9.
4
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
+
5
7
  ## New Features
6
8
 
7
9
  ### TypeScript Support
@@ -41,6 +43,49 @@ See the [TypeScript Documentation](./typescript.md) for usage examples.
41
43
  - Remove custom scripts that set NODE_ENV before running the dev server
42
44
  - Remove `NODE_ENV=development` from your `bin/dev` or Procfile.dev
43
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
+
44
89
  ## Breaking Changes
45
90
 
46
91
  ### 1. CSS Modules Configuration Changed to Named Exports
@@ -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,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
  ENV["APP_ROOT"] ||= File.expand_path("..", __dir__)
6
6
 
7
7
  require "bundler/setup"
@@ -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"