shakapacker 9.0.0 → 9.1.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.
@@ -1,17 +1,23 @@
1
1
  # Rspack Migration Guide for Shakapacker
2
2
 
3
+ > 💡 **Quick Start**: For a step-by-step migration guide from Webpack to Rspack, see [Common Upgrades Guide - Webpack to Rspack](./common-upgrades.md#migrating-from-webpack-to-rspack).
4
+
3
5
  ## Overview
6
+
4
7
  This guide documents the differences between webpack and Rspack configurations in Shakapacker, and provides migration guidance for users switching to Rspack.
5
8
 
6
9
  ## Key Differences from Webpack
7
10
 
8
11
  ### 1. Built-in Loaders
12
+
9
13
  Rspack provides built-in loaders for better performance:
10
14
 
11
15
  **JavaScript/TypeScript:**
16
+
12
17
  - Use `builtin:swc-loader` instead of `babel-loader` or `ts-loader`
13
18
  - 20x faster than Babel on single thread, 70x on multiple cores
14
19
  - Configuration example:
20
+
15
21
  ```javascript
16
22
  {
17
23
  test: /\.(js|jsx|ts|tsx)$/,
@@ -36,28 +42,34 @@ Rspack provides built-in loaders for better performance:
36
42
  ### 2. Plugin Replacements
37
43
 
38
44
  #### Built-in Rspack Alternatives
39
- | Webpack Plugin | Rspack Alternative | Status |
40
- |---------------|-------------------|---------|
41
- | `copy-webpack-plugin` | `rspack.CopyRspackPlugin` | Built-in |
42
- | `mini-css-extract-plugin` | `rspack.CssExtractRspackPlugin` | ✅ Built-in |
43
- | `terser-webpack-plugin` | `rspack.SwcJsMinimizerRspackPlugin` | ✅ Built-in |
45
+
46
+ | Webpack Plugin | Rspack Alternative | Status |
47
+ | ------------------------------ | ------------------------------------------ | ----------- |
48
+ | `copy-webpack-plugin` | `rspack.CopyRspackPlugin` | ✅ Built-in |
49
+ | `mini-css-extract-plugin` | `rspack.CssExtractRspackPlugin` | ✅ Built-in |
50
+ | `terser-webpack-plugin` | `rspack.SwcJsMinimizerRspackPlugin` | ✅ Built-in |
44
51
  | `css-minimizer-webpack-plugin` | `rspack.LightningCssMinimizerRspackPlugin` | ✅ Built-in |
45
52
 
46
53
  #### Community Alternatives
47
- | Webpack Plugin | Rspack Alternative | Package |
48
- |---------------|-------------------|----------|
49
- | `fork-ts-checker-webpack-plugin` | `ts-checker-rspack-plugin` | `npm i -D ts-checker-rspack-plugin` |
54
+
55
+ | Webpack Plugin | Rspack Alternative | Package |
56
+ | -------------------------------------- | ------------------------------ | --------------------------------------- |
57
+ | `fork-ts-checker-webpack-plugin` | `ts-checker-rspack-plugin` | `npm i -D ts-checker-rspack-plugin` |
50
58
  | `@pmmmwh/react-refresh-webpack-plugin` | `@rspack/plugin-react-refresh` | `npm i -D @rspack/plugin-react-refresh` |
51
- | `eslint-webpack-plugin` | `eslint-rspack-plugin` | `npm i -D eslint-rspack-plugin` |
59
+ | `eslint-webpack-plugin` | `eslint-rspack-plugin` | `npm i -D eslint-rspack-plugin` |
52
60
 
53
61
  #### Incompatible Plugins
62
+
54
63
  The following webpack plugins are NOT compatible with Rspack:
64
+
55
65
  - `webpack.optimize.LimitChunkCountPlugin` - Use `optimization.splitChunks` configuration instead
56
66
  - `webpack-manifest-plugin` - Use `rspack-manifest-plugin` instead
57
67
  - Git revision plugins - Use alternative approaches
58
68
 
59
69
  ### 3. Asset Module Types
70
+
60
71
  Replace file loaders with asset modules:
72
+
61
73
  - `file-loader` → `type: 'asset/resource'`
62
74
  - `url-loader` → `type: 'asset/inline'`
63
75
  - `raw-loader` → `type: 'asset/source'`
@@ -65,7 +77,9 @@ Replace file loaders with asset modules:
65
77
  ### 4. Configuration Differences
66
78
 
67
79
  #### TypeScript Configuration
80
+
68
81
  **Required:** Add `isolatedModules: true` to your `tsconfig.json`:
82
+
69
83
  ```json
70
84
  {
71
85
  "compilerOptions": {
@@ -75,22 +89,22 @@ Replace file loaders with asset modules:
75
89
  ```
76
90
 
77
91
  #### React Fast Refresh
92
+
78
93
  ```javascript
79
94
  // Development configuration
80
- const ReactRefreshPlugin = require('@rspack/plugin-react-refresh');
95
+ const ReactRefreshPlugin = require("@rspack/plugin-react-refresh")
81
96
 
82
97
  module.exports = {
83
- plugins: [
84
- new ReactRefreshPlugin(),
85
- new rspack.HotModuleReplacementPlugin()
86
- ]
87
- };
98
+ plugins: [new ReactRefreshPlugin(), new rspack.HotModuleReplacementPlugin()]
99
+ }
88
100
  ```
89
101
 
90
102
  ### 5. Optimization Differences
91
103
 
92
104
  #### Code Splitting
105
+
93
106
  Rspack's `splitChunks` configuration is similar to webpack but with some differences:
107
+
94
108
  ```javascript
95
109
  optimization: {
96
110
  splitChunks: {
@@ -107,6 +121,7 @@ optimization: {
107
121
  ```
108
122
 
109
123
  #### Minimization
124
+
110
125
  ```javascript
111
126
  optimization: {
112
127
  minimize: true,
@@ -118,7 +133,9 @@ optimization: {
118
133
  ```
119
134
 
120
135
  ### 6. Development Server
136
+
121
137
  Rspack uses its own dev server with some configuration differences:
138
+
122
139
  ```javascript
123
140
  devServer: {
124
141
  // Rspack-specific: Force writing assets to disk
@@ -130,7 +147,55 @@ devServer: {
130
147
 
131
148
  ## Migration Checklist
132
149
 
150
+ ### Quick Start: Using the Switch Bundler Task
151
+
152
+ Shakapacker provides a convenient rake task to switch between webpack and rspack:
153
+
154
+ ```bash
155
+ # Switch to rspack with automatic dependency management
156
+ rails shakapacker:switch_bundler rspack --install-deps
157
+ # or with rake (note the -- separator)
158
+ rake shakapacker:switch_bundler rspack -- --install-deps
159
+
160
+ # Fast switching without uninstalling old bundler (keeps both)
161
+ rails shakapacker:switch_bundler webpack --install-deps --no-uninstall
162
+ rake shakapacker:switch_bundler rspack -- --install-deps --no-uninstall
163
+
164
+ # Switch to rspack manually (you manage dependencies yourself)
165
+ rails shakapacker:switch_bundler rspack
166
+ rake shakapacker:switch_bundler rspack
167
+
168
+ # Switch back to webpack if needed
169
+ rails shakapacker:switch_bundler webpack --install-deps
170
+ rake shakapacker:switch_bundler webpack -- --install-deps
171
+
172
+ # Show help
173
+ rails shakapacker:switch_bundler --help
174
+ rake shakapacker:switch_bundler -- --help
175
+ ```
176
+
177
+ **Note:** When using `rake`, you must use `--` to separate rake options from task arguments.
178
+
179
+ The task will:
180
+
181
+ - Update `config/shakapacker.yml` to switch the bundler
182
+ - Optionally install/uninstall npm dependencies with `--install-deps`
183
+ - Use `--no-uninstall` to skip uninstalling the old bundler's packages (faster switching, keeps both bundlers installed)
184
+ - Update `javascript_transpiler` to `swc` when switching to rspack (recommended)
185
+ - Preserve your config file comments and structure
186
+
187
+ **Custom Dependencies:** You can customize which dependencies are installed by creating a `.shakapacker-switch-bundler-dependencies.yml` file:
188
+
189
+ ```bash
190
+ rails shakapacker:switch_bundler --init-config
191
+ ```
192
+
193
+ ### Manual Migration Steps
194
+
195
+ If you prefer to migrate manually or need more control:
196
+
133
197
  ### Step 1: Update Dependencies
198
+
134
199
  ```bash
135
200
  # Remove webpack dependencies
136
201
  npm uninstall webpack webpack-cli webpack-dev-server
@@ -140,27 +205,33 @@ npm install --save-dev @rspack/core @rspack/cli
140
205
  ```
141
206
 
142
207
  ### Step 2: Update Configuration Files
208
+
143
209
  1. Create `config/rspack/rspack.config.js` based on your webpack config
144
210
  2. Update `config/shakapacker.yml`:
211
+
145
212
  ```yaml
146
- assets_bundler: 'rspack'
213
+ assets_bundler: "rspack"
147
214
  ```
148
215
 
149
216
  ### Step 3: Replace Loaders
217
+
150
218
  - Replace `babel-loader` with `builtin:swc-loader`
151
219
  - Remove `file-loader`, `url-loader`, `raw-loader` - use asset modules
152
220
  - Update CSS loaders to use Rspack's built-in support
153
221
 
154
222
  ### Step 4: Update Plugins
223
+
155
224
  - Replace plugins with Rspack alternatives (see table above)
156
225
  - Remove incompatible plugins
157
226
  - Add Rspack-specific plugins as needed
158
227
 
159
228
  ### Step 5: TypeScript Setup
229
+
160
230
  1. Add `isolatedModules: true` to `tsconfig.json`
161
231
  2. Optional: Add `ts-checker-rspack-plugin` for type checking
162
232
 
163
233
  ### Step 6: Test Your Build
234
+
164
235
  ```bash
165
236
  # Development build
166
237
  bin/shakapacker
@@ -172,18 +243,22 @@ bin/shakapacker --mode production
172
243
  ## Common Issues and Solutions
173
244
 
174
245
  ### Issue: LimitChunkCountPlugin Error
246
+
175
247
  **Error:** `Cannot read properties of undefined (reading 'tap')`
176
248
  **Solution:** Remove `webpack.optimize.LimitChunkCountPlugin` and use `splitChunks` configuration instead.
177
249
 
178
250
  ### Issue: Missing Loaders
251
+
179
252
  **Error:** Module parse errors
180
253
  **Solution:** Check console logs for skipped loaders and install missing dependencies.
181
254
 
182
255
  ### Issue: CSS Extraction
256
+
183
257
  **Error:** CSS not being extracted properly
184
258
  **Solution:** Use `rspack.CssExtractRspackPlugin` instead of `mini-css-extract-plugin`.
185
259
 
186
260
  ### Issue: TypeScript Errors
261
+
187
262
  **Error:** TypeScript compilation errors
188
263
  **Solution:** Ensure `isolatedModules: true` is set in `tsconfig.json`.
189
264
 
@@ -199,4 +274,4 @@ bin/shakapacker --mode production
199
274
  - [Rspack Documentation](https://rspack.rs)
200
275
  - [Rspack Examples](https://github.com/rspack-contrib/rspack-examples)
201
276
  - [Awesome Rspack](https://github.com/rspack-contrib/awesome-rspack)
202
- - [Migration Guide](https://rspack.rs/guide/migration/webpack)
277
+ - [Migration Guide](https://rspack.rs/guide/migration/webpack)
@@ -1,5 +1,7 @@
1
1
  # JavaScript Transpiler Configuration
2
2
 
3
+ > 💡 **Quick Start**: For a concise guide to migrating from Babel to SWC, see [Common Upgrades Guide - Babel to SWC](./common-upgrades.md#migrating-from-babel-to-swc).
4
+
3
5
  ## Default Transpilers
4
6
 
5
7
  Shakapacker uses different default JavaScript transpilers based on the bundler:
@@ -108,12 +110,31 @@ Typical build time improvements when migrating from Babel to SWC:
108
110
  - [ ] Back up your current configuration
109
111
  - [ ] Install SWC dependencies
110
112
  - [ ] Update `shakapacker.yml`
113
+ - [ ] If using Stimulus, ensure `keepClassNames: true` is set in `config/swc.config.js` (automatically included in v9.1.0+)
111
114
  - [ ] Test your build locally
112
115
  - [ ] Run your test suite
113
116
  - [ ] Check browser compatibility
114
117
  - [ ] Deploy to staging environment
115
118
  - [ ] Monitor for any runtime issues
116
119
 
120
+ #### Stimulus Compatibility
121
+
122
+ If you're using [Stimulus](https://stimulus.hotwired.dev/), you must configure SWC to preserve class names. See the [Using SWC with Stimulus](using_swc_loader.md#using-swc-with-stimulus) section for detailed instructions.
123
+
124
+ **Quick summary:** Add `keepClassNames: true` to your `config/swc.config.js`:
125
+
126
+ ```javascript
127
+ module.exports = {
128
+ options: {
129
+ jsc: {
130
+ keepClassNames: true // Required for Stimulus
131
+ }
132
+ }
133
+ }
134
+ ```
135
+
136
+ Starting with Shakapacker v9.1.0, running `rake shakapacker:migrate_to_swc` automatically creates a configuration with this setting.
137
+
117
138
  ### Rollback Plan
118
139
 
119
140
  If you encounter issues, rolling back is simple:
@@ -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