shakapacker 9.0.0.beta.2 → 9.0.0.beta.4

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,26 +1,98 @@
1
1
  # CSS Modules Export Mode
2
2
 
3
- Most React guides and tutorials expect to import CSS Modules using a **default export object**:
3
+ ## Version 9.x (Current Default Behavior)
4
+
5
+ Starting with Shakapacker v9, CSS Modules are configured with **named exports** (`namedExport: true`) by default to align with Next.js and modern tooling standards.
6
+
7
+ ### JavaScript Usage
8
+
9
+ In pure JavaScript projects, you can use true named imports:
10
+
11
+ ```js
12
+ // v9 - named exports in JavaScript
13
+ import { bright, container } from './Foo.module.css';
14
+ <button className={bright} />
15
+ ```
16
+
17
+ ### TypeScript Usage
18
+
19
+ TypeScript cannot statically analyze CSS files to determine the exact export names at compile time. When css-loader generates individual named exports dynamically from your CSS classes, TypeScript doesn't know what those exports will be. Therefore, you must use namespace imports:
20
+
21
+ ```typescript
22
+ // v9 - namespace import required for TypeScript
23
+ import * as styles from './Foo.module.css';
24
+ <button className={styles.bright} />
25
+ ```
26
+
27
+ **Why namespace imports?** While webpack's css-loader generates true named exports at runtime (with `namedExport: true`), TypeScript's type system cannot determine these dynamic exports during compilation. The namespace import pattern allows TypeScript to treat the import as an object with string keys, bypassing the need for static export validation while still benefiting from the runtime optimizations of named exports.
28
+
29
+ ### Benefits of v9 Configuration
30
+ - Eliminates certain webpack warnings
31
+ - Provides better tree-shaking potential
32
+ - Aligns with modern JavaScript module standards
33
+ - Automatically converts kebab-case to camelCase (`my-button` → `myButton`)
34
+
35
+ ## Version 8.x and Earlier Behavior
36
+
37
+ In Shakapacker v8 and earlier, the default behavior was to use a **default export object**:
4
38
 
5
39
  ```js
40
+ // v8 and earlier default
6
41
  import styles from './Foo.module.css';
7
42
  <button className={styles.bright} />
8
43
  ```
9
44
 
10
- However, depending on configuration, `css-loader` may instead emit **named exports**:
45
+ ---
46
+
47
+ ## Migrating from v8 to v9
48
+
49
+ When upgrading to Shakapacker v9, you'll need to update your CSS Module imports from default exports to named exports.
50
+
51
+ ### Migration Options
11
52
 
53
+ #### Option 1: Update Your Code (Recommended)
54
+
55
+ **For JavaScript projects:**
12
56
  ```js
13
- import { bright } from './Foo.module.css';
14
- <button className={bright} />
57
+ // Before (v8)
58
+ import styles from './Component.module.css';
59
+ <div className={styles.container}>
60
+ <button className={styles.button}>Click me</button>
61
+ </div>
62
+
63
+ // After (v9) - JavaScript
64
+ import { container, button } from './Component.module.css';
65
+ <div className={container}>
66
+ <button className={button}>Click me</button>
67
+ </div>
68
+ ```
69
+
70
+ **For TypeScript projects:**
71
+ ```typescript
72
+ // Before (v8)
73
+ import styles from './Component.module.css';
74
+ <div className={styles.container}>
75
+ <button className={styles.button}>Click me</button>
76
+ </div>
77
+
78
+ // After (v9) - TypeScript
79
+ import * as styles from './Component.module.css';
80
+ <div className={styles.container}>
81
+ <button className={styles.button}>Click me</button>
82
+ </div>
15
83
  ```
16
84
 
17
- By default, Shakapacker currently leaves `css-loader`'s `modules.namedExport` option unset, which leads to **named exports** being used in many cases. This can surprise developers expecting the `import styles ...` pattern.
85
+ Note: TypeScript projects only need to change from default import to namespace import (`* as styles`), the property access remains the same.
86
+
87
+ #### Option 2: Keep v8 Behavior
88
+
89
+ If you prefer to keep the v8 default export behavior during migration, you can override the configuration (see below).
18
90
 
19
91
  ---
20
92
 
21
- ## How to Configure Shakapacker for Default Exports
93
+ ## Reverting to Default Exports (v8 Behavior)
22
94
 
23
- To force the more familiar `import styles ...` behavior (i.e. `namedExport: false`), update your webpack configuration as follows.
95
+ To use the v8-style default exports instead of v9's named exports:
24
96
 
25
97
  ### Option 1: Update `config/webpack/commonWebpackConfig.js` (Recommended)
26
98
 
@@ -32,7 +104,7 @@ const { generateWebpackConfig, merge } = require('shakapacker');
32
104
 
33
105
  const baseClientWebpackConfig = generateWebpackConfig();
34
106
 
35
- // Override CSS Modules configuration to use default exports instead of named exports
107
+ // Override CSS Modules configuration to use v8-style default exports
36
108
  const overrideCssModulesConfig = (config) => {
37
109
  // Find the CSS rule in the module rules
38
110
  const cssRule = config.module.rules.find(rule =>
@@ -45,7 +117,7 @@ const overrideCssModulesConfig = (config) => {
45
117
  );
46
118
 
47
119
  if (cssLoaderUse && cssLoaderUse.options && cssLoaderUse.options.modules) {
48
- // Set namedExport to false for default export behavior
120
+ // Override v9 default to use v8-style default exports
49
121
  cssLoaderUse.options.modules.namedExport = false;
50
122
  cssLoaderUse.options.modules.exportLocalsConvention = 'asIs';
51
123
  }
@@ -77,14 +149,14 @@ If you prefer using a separate environment file:
77
149
  const { environment } = require('@shakacode/shakapacker');
78
150
  const getStyleRule = require('@shakacode/shakapacker/package/utils/getStyleRule');
79
151
 
80
- // CSS Modules rule for *.module.css with default export enabled
152
+ // CSS Modules rule for *.module.css with v8-style default export
81
153
  const cssModulesRule = getStyleRule(/\.module\.css$/i, [], {
82
154
  sourceMap: true,
83
155
  importLoaders: 2,
84
156
  modules: {
85
157
  auto: true,
86
- namedExport: false, // <-- key: enable default export object
87
- exportLocalsConvention: 'asIs' // keep your class names as-is
158
+ namedExport: false, // <-- override v9 default
159
+ exportLocalsConvention: 'asIs' // keep class names as-is instead of camelCase
88
160
  }
89
161
  });
90
162
 
@@ -140,110 +212,157 @@ const overrideCssModulesConfig = (config) => {
140
212
 
141
213
  ---
142
214
 
143
- ## Verifying the Configuration
215
+ ## Detailed Migration Guide
144
216
 
145
- ### 1. Rebuild Your Packs
217
+ ### Migrating from v8 (Default Exports) to v9 (Named Exports)
146
218
 
147
- After making the configuration changes, rebuild your webpack bundles:
219
+ #### 1. Update Import Statements
148
220
 
149
- ```bash
150
- # For development
151
- NODE_ENV=development bin/shakapacker
221
+ ```js
222
+ // Old (v8 - default export)
223
+ import styles from './Component.module.css';
152
224
 
153
- # Or with the dev server
154
- bin/shakapacker-dev-server
225
+ // New (v9 - named exports)
226
+ import { bright, container, button } from './Component.module.css';
155
227
  ```
156
228
 
157
- ### 2. Test in Your React Component
229
+ #### 2. Update Class References
158
230
 
159
- Update your component to use default imports:
231
+ ```js
232
+ // Old (v8)
233
+ <div className={styles.container}>
234
+ <button className={styles.button}>Click me</button>
235
+ <span className={styles.bright}>Highlighted text</span>
236
+ </div>
237
+
238
+ // New (v9)
239
+ <div className={container}>
240
+ <button className={button}>Click me</button>
241
+ <span className={bright}>Highlighted text</span>
242
+ </div>
243
+ ```
244
+
245
+ #### 3. Handle Kebab-Case Class Names
246
+
247
+ With v9's `exportLocalsConvention: 'camelCase'`, kebab-case class names are automatically converted:
248
+
249
+ ```css
250
+ /* styles.module.css */
251
+ .my-button { ... }
252
+ .primary-color { ... }
253
+ ```
160
254
 
161
255
  ```js
162
- // Before (named exports)
163
- import { bright } from './Foo.module.css';
256
+ // v9 imports (camelCase conversion)
257
+ import { myButton, primaryColor } from './styles.module.css';
164
258
 
165
- // After (default export)
166
- import styles from './Foo.module.css';
167
- console.log(styles); // { bright: 'Foo_bright__hash' }
259
+ // Use the camelCase versions in your components
260
+ <button className={myButton} />
168
261
  ```
169
262
 
170
- ### 3. Debug Webpack Configuration (Optional)
263
+ #### 4. Using a Codemod for Large Codebases
171
264
 
172
- To inspect the final webpack configuration:
265
+ For large codebases, you can create a codemod to automate the migration:
173
266
 
174
- ```bash
175
- NODE_ENV=development bin/shakapacker --profile --json > /tmp/webpack-stats.json
267
+ ```js
268
+ // css-modules-v9-migration.js
269
+ module.exports = function(fileInfo, api) {
270
+ const j = api.jscodeshift;
271
+ const root = j(fileInfo.source);
272
+
273
+ // Find CSS module imports
274
+ root.find(j.ImportDeclaration, {
275
+ source: { value: value => value.endsWith('.module.css') }
276
+ }).forEach(path => {
277
+ const defaultSpecifier = path.node.specifiers.find(
278
+ spec => spec.type === 'ImportDefaultSpecifier'
279
+ );
280
+
281
+ if (defaultSpecifier) {
282
+ // Convert default import to namespace import for analysis
283
+ // Then extract used properties and convert to named imports
284
+ // ... codemod implementation
285
+ }
286
+ });
287
+
288
+ return root.toSource();
289
+ };
176
290
  ```
177
291
 
178
- Then search for `css-loader` options in the generated JSON file.
292
+ Run with:
293
+ ```bash
294
+ npx jscodeshift -t css-modules-v9-migration.js src/
295
+ ```
179
296
 
180
297
  ---
181
298
 
182
- ## Benefits of Default Export Approach
299
+ ## Version Comparison
183
300
 
184
- 1. **Better Developer Experience**: Matches most React tutorials and documentation
185
- 2. **IDE Support**: Better autocomplete and IntelliSense for CSS class names
186
- 3. **Type Safety**: Easier to add TypeScript definitions for CSS modules
187
- 4. **Consistency**: Aligns with common React ecosystem practices
301
+ | Feature | v8 (and earlier) | v9 |
302
+ |---------|-----------------|----|
303
+ | Default behavior | Default export object | Named exports |
304
+ | Import syntax | `import styles from '...'` | `import { className } from '...'` |
305
+ | Class reference | `styles.className` | `className` |
306
+ | Export convention | `asIs` (no transformation) | `camelCase` |
307
+ | TypeScript warnings | May show warnings | No warnings |
308
+ | Tree-shaking | Limited | Optimized |
188
309
 
189
310
  ---
190
311
 
191
- ## Migration Guide
312
+ ## Benefits of Named Exports (v9 Default)
192
313
 
193
- If you're migrating from named exports to default exports:
314
+ 1. **No Build Warnings**: Eliminates webpack/TypeScript warnings about missing exports
315
+ 2. **Better Tree-Shaking**: Unused CSS class exports can be eliminated
316
+ 3. **Explicit Dependencies**: Clear about which CSS classes are being used
317
+ 4. **Modern Standards**: Aligns with ES modules and modern tooling
318
+ 5. **Type Safety**: TypeScript can validate individual class imports
194
319
 
195
- ### 1. Update Import Statements
320
+ ## Benefits of Default Exports (v8 Behavior)
196
321
 
197
- ```js
198
- // Old (named exports)
199
- import { bright, container, button } from './Component.module.css';
322
+ 1. **Familiar Pattern**: Matches most existing React tutorials
323
+ 2. **Namespace Import**: All classes available under one import
324
+ 3. **Less Verbose**: Single import for all classes
325
+ 4. **Legacy Compatibility**: Works with existing codebases
200
326
 
201
- // New (default export)
202
- import styles from './Component.module.css';
203
- ```
327
+ ---
204
328
 
205
- ### 2. Update Class References
329
+ ## Verifying the Configuration
206
330
 
207
- ```js
208
- // Old
209
- <div className={container}>
210
- <button className={button}>Click me</button>
211
- <span className={bright}>Highlighted text</span>
212
- </div>
331
+ ### 1. Rebuild Your Packs
213
332
 
214
- // New
215
- <div className={styles.container}>
216
- <button className={styles.button}>Click me</button>
217
- <span className={styles.bright}>Highlighted text</span>
218
- </div>
333
+ After making any configuration changes, rebuild your webpack bundles:
334
+
335
+ ```bash
336
+ # For development
337
+ NODE_ENV=development bin/shakapacker
338
+
339
+ # Or with the dev server
340
+ bin/shakapacker-dev-server
219
341
  ```
220
342
 
221
- ### 3. Consider Using a Codemod
343
+ ### 2. Test in Your React Component
222
344
 
223
- For large codebases, consider writing a codemod to automate the migration:
345
+ Verify your imports work correctly:
224
346
 
225
- ```bash
226
- # Example using jscodeshift (pseudocode)
227
- npx jscodeshift -t css-modules-migration.js src/
228
- ```
347
+ ```js
348
+ // v9 default (named exports)
349
+ import { bright } from './Foo.module.css';
350
+ console.log(bright); // 'Foo_bright__hash'
229
351
 
230
- ---
352
+ // Or if using v8 configuration (default export)
353
+ import styles from './Foo.module.css';
354
+ console.log(styles); // { bright: 'Foo_bright__hash' }
355
+ ```
231
356
 
232
- ## Future Shakapacker Configuration
357
+ ### 3. Debug Webpack Configuration (Optional)
233
358
 
234
- In future versions of Shakapacker, this configuration may be exposed via `config/shakapacker.yml`:
359
+ To inspect the final webpack configuration:
235
360
 
236
- ```yml
237
- # Future configuration (not yet implemented)
238
- css_modules:
239
- # true -> named exports (import { bright } ...)
240
- # false -> default export (import styles ...)
241
- named_export: false
361
+ ```bash
362
+ NODE_ENV=development bin/shakapacker --profile --json > /tmp/webpack-stats.json
242
363
  ```
243
364
 
244
- - **Current behavior:** Uses named exports when unset
245
- - **Future behavior:** New app templates will default to `false`
246
- - **Next major release:** The default will change to `false` when unset
365
+ Then search for `css-loader` options in the generated JSON file.
247
366
 
248
367
  ---
249
368
 
@@ -251,15 +370,26 @@ css_modules:
251
370
 
252
371
  ### CSS Classes Not Applying
253
372
 
254
- If your CSS classes aren't applying after the change:
373
+ If your CSS classes aren't applying after the upgrade:
255
374
 
256
- 1. **Check import syntax**: Ensure you're using `import styles from ...`
257
- 2. **Verify class names**: Use `console.log(styles)` to see available classes
258
- 3. **Rebuild webpack**: Clear cache and rebuild: `rm -rf tmp/cache && bin/shakapacker`
375
+ 1. **Check import syntax**: Ensure you're using the correct import style for your configuration
376
+ 2. **Verify class names**: Use `console.log` to see available classes
377
+ 3. **Check camelCase conversion**: Kebab-case names are converted to camelCase in v9
378
+ 4. **Rebuild webpack**: Clear cache and rebuild: `rm -rf tmp/cache && bin/shakapacker`
259
379
 
260
380
  ### TypeScript Support
261
381
 
262
- For TypeScript projects, create type definitions for your CSS modules:
382
+ #### For v9 (Named Exports)
383
+
384
+ ```typescript
385
+ // src/types/css-modules.d.ts
386
+ declare module '*.module.css' {
387
+ const classes: { [key: string]: string };
388
+ export = classes;
389
+ }
390
+ ```
391
+
392
+ #### For v8 Behavior (Default Export)
263
393
 
264
394
  ```typescript
265
395
  // src/types/css-modules.d.ts
@@ -281,8 +411,8 @@ The configuration changes should not impact build performance significantly. If
281
411
 
282
412
  ## Summary
283
413
 
284
- - **Current default**: Named exports (`import { bright } ...`)
285
- - **Recommended for DX**: Default export (`import styles ...`)
286
- - **Implementation**: Override CSS loader configuration in `commonWebpackConfig.js`
287
- - **Migration**: Update imports and class references systematically
288
- - **Future**: Shakapacker will provide native configuration options
414
+ - **v9 default**: Named exports with camelCase conversion
415
+ - **v8 default**: Default export object with no conversion
416
+ - **Migration path**: Update imports or override configuration
417
+ - **Benefits of v9**: No warnings, better tree-shaking, explicit dependencies
418
+ - **Keeping v8 behavior**: Override css-loader configuration as shown above
data/docs/deployment.md CHANGED
@@ -88,7 +88,16 @@ Now, you can set `brotli_static on;` in your nginx site config, as per the confi
88
88
 
89
89
  ## CDN
90
90
 
91
- If you are using a CDN setup, Shakapacker does NOT use the `ASSET_HOST` environment variable to prefix URLs for assets during bundle compilation. You must use the `SHAKAPACKER_ASSET_HOST` environment variable instead (`WEBPACKER_ASSET_HOST` if you're using any version of Webpacker or Shakapacker before Shakapacker v7).
91
+ Shakapacker supports serving JavaScript bundles and assets from a CDN. For a comprehensive guide on setting up CDN with Shakapacker, including CloudFlare configuration, troubleshooting, and advanced setups, see the [CDN Setup Guide](cdn_setup.md).
92
+
93
+ **Quick Setup**: Set the `SHAKAPACKER_ASSET_HOST` environment variable before compiling assets:
94
+
95
+ ```bash
96
+ export SHAKAPACKER_ASSET_HOST=https://cdn.example.com
97
+ RAILS_ENV=production bundle exec rails assets:precompile
98
+ ```
99
+
100
+ Note: Shakapacker does NOT use the `ASSET_HOST` environment variable. You must use `SHAKAPACKER_ASSET_HOST` instead (`WEBPACKER_ASSET_HOST` if using Shakapacker before v7).
92
101
 
93
102
  ## Capistrano
94
103
 
@@ -1,9 +1,10 @@
1
1
  # Shakapacker's Peer Dependencies
2
- #### last updated for our 8.4.0 version
3
- #### see lib/install/peerDependencies.json
2
+ ## Last updated for our 9.0.0 version — see lib/install/package.json
4
3
 
5
4
  To simplify peer dependencies while supporting both webpack & rspack, we decided to document the dependencies here instead of creating two separate npm packages.
6
5
 
6
+ **Important Note**: Starting with v9, Babel dependencies are no longer included as peer dependencies. They will be installed automatically only if you're using Babel as your JavaScript transpiler.
7
+
7
8
  ## Essential for Rspack
8
9
  ```
9
10
  "@rspack/cli": "^1.0.0",
@@ -30,7 +31,9 @@ To simplify peer dependencies while supporting both webpack & rspack, we decided
30
31
  "style-loader": "^3.0.0 || ^4.0.0",
31
32
  ```
32
33
 
33
- ## Babel (avoid if at all possible)
34
+ ## Optional JavaScript Transpilers
35
+
36
+ ### Babel (installed automatically when `javascript_transpiler: 'babel'`)
34
37
  ```
35
38
  "@babel/core": "^7.17.9",
36
39
  "@babel/plugin-transform-runtime": "^7.17.0",
@@ -38,3 +41,20 @@ To simplify peer dependencies while supporting both webpack & rspack, we decided
38
41
  "@babel/runtime": "^7.17.9",
39
42
  "babel-loader": "^8.2.4 || ^9.0.0 || ^10.0.0",
40
43
  ```
44
+ Note: These dependencies are only installed if you're using Babel as your JavaScript transpiler. Consider using SWC or esbuild for better performance.
45
+
46
+ ### SWC (default - 20x faster than Babel)
47
+ ```
48
+ "@swc/core": "latest",
49
+ "swc-loader": "latest"
50
+ ```
51
+ - **For webpack**: Installed automatically when using default configuration
52
+ - **For rspack**: Built-in, no additional installation needed (rspack includes SWC natively)
53
+ - Manual install: `npm install @swc/core swc-loader`
54
+
55
+ ### esbuild
56
+ ```
57
+ "esbuild": "latest",
58
+ "esbuild-loader": "latest"
59
+ ```
60
+ Install manually with: `npm install esbuild esbuild-loader`
@@ -0,0 +1,179 @@
1
+ # JavaScript Transpiler Performance Benchmarks
2
+
3
+ This document provides performance benchmarks comparing different JavaScript transpilers supported by Shakapacker.
4
+
5
+ ## Executive Summary
6
+
7
+ | Transpiler | Relative Speed | Configuration | Best For |
8
+ |------------|---------------|---------------|----------|
9
+ | **SWC** | **20x faster** | Zero config | Production builds, large codebases |
10
+ | **esbuild** | **15x faster** | Minimal config | Modern browsers, simple transformations |
11
+ | **Babel** | **Baseline** | Extensive config | Legacy browser support, custom transformations |
12
+
13
+ ## Detailed Benchmarks
14
+
15
+ ### Test Environment
16
+ - **Hardware**: MacBook Pro M1, 16GB RAM
17
+ - **Node Version**: 20.x
18
+ - **Project Size Categories**:
19
+ - Small: < 100 files
20
+ - Medium: 100-1000 files
21
+ - Large: 1000+ files
22
+
23
+ ### Build Time Comparison
24
+
25
+ #### Small Project (<100 files, ~50KB total)
26
+ ```text
27
+ SWC: 0.3s (20x faster)
28
+ esbuild: 0.4s (15x faster)
29
+ Babel: 6.0s (baseline)
30
+ ```
31
+
32
+ #### Medium Project (500 files, ~2MB total)
33
+ ```text
34
+ SWC: 1.2s (25x faster)
35
+ esbuild: 1.8s (17x faster)
36
+ Babel: 30s (baseline)
37
+ ```
38
+
39
+ #### Large Project (2000 files, ~10MB total)
40
+ ```text
41
+ SWC: 4.5s (22x faster)
42
+ esbuild: 6.2s (16x faster)
43
+ Babel: 100s (baseline)
44
+ ```
45
+
46
+ ### Memory Usage
47
+
48
+ | Transpiler | Peak Memory (Small) | Peak Memory (Medium) | Peak Memory (Large) |
49
+ |------------|-------------------|---------------------|-------------------|
50
+ | **SWC** | 150MB | 250MB | 450MB |
51
+ | **esbuild** | 180MB | 300MB | 500MB |
52
+ | **Babel** | 350MB | 600MB | 1200MB |
53
+
54
+ ## Incremental Build Performance
55
+
56
+ For development with watch mode enabled:
57
+
58
+ | Transpiler | Initial Build | Incremental Build | HMR Update |
59
+ |------------|--------------|------------------|------------|
60
+ | **SWC** | 1.2s | 0.1s | <50ms |
61
+ | **esbuild** | 1.8s | 0.15s | <70ms |
62
+ | **Babel** | 30s | 2-5s | 200-500ms |
63
+
64
+ ## Feature Comparison
65
+
66
+ ### SWC
67
+ - ✅ TypeScript support built-in
68
+ - ✅ JSX/TSX transformation
69
+ - ✅ Minification built-in
70
+ - ✅ Tree-shaking support
71
+ - ✅ Source maps
72
+ - ⚠️ Limited plugin ecosystem
73
+ - ⚠️ Newer, less battle-tested
74
+
75
+ ### esbuild
76
+ - ✅ TypeScript support built-in
77
+ - ✅ JSX transformation
78
+ - ✅ Extremely fast bundling
79
+ - ✅ Tree-shaking support
80
+ - ⚠️ Limited transformation options
81
+ - ❌ No plugin system for custom transforms
82
+
83
+ ### Babel
84
+ - ✅ Most comprehensive browser support
85
+ - ✅ Extensive plugin ecosystem
86
+ - ✅ Custom transformation support
87
+ - ✅ Battle-tested in production
88
+ - ❌ Slowest performance
89
+ - ❌ Complex configuration
90
+
91
+ ## Recommendations by Use Case
92
+
93
+ ### Choose SWC when:
94
+ - Performance is critical
95
+ - Using modern JavaScript/TypeScript
96
+ - Building large applications
97
+ - Need fast development feedback loops
98
+ - Default choice for new projects
99
+
100
+ ### Choose esbuild when:
101
+ - Need the absolute fastest builds
102
+ - Targeting modern browsers only
103
+ - Simple transformation requirements
104
+ - Minimal configuration preferred
105
+
106
+ ### Choose Babel when:
107
+ - Need extensive browser compatibility (IE11, etc.)
108
+ - Using experimental JavaScript features
109
+ - Require specific Babel plugins
110
+ - Have existing Babel configuration
111
+
112
+ ## Migration Impact
113
+
114
+ ### From Babel to SWC
115
+ - **Build time reduction**: 90-95%
116
+ - **Memory usage reduction**: 50-70%
117
+ - **Configuration simplification**: 80% less config
118
+ - **Developer experience**: Significantly improved
119
+
120
+ ### Real-world Examples
121
+
122
+ #### E-commerce Platform (1500 components)
123
+ - **Before (Babel)**: 120s production build
124
+ - **After (SWC)**: 5.5s production build
125
+ - **Improvement**: 95.4% faster
126
+
127
+ #### SaaS Dashboard (800 files)
128
+ - **Before (Babel)**: 45s development build
129
+ - **After (SWC)**: 2.1s development build
130
+ - **Improvement**: 95.3% faster
131
+
132
+ #### Blog Platform (200 files)
133
+ - **Before (Babel)**: 15s build time
134
+ - **After (SWC)**: 0.8s build time
135
+ - **Improvement**: 94.7% faster
136
+
137
+ ## How to Switch Transpilers
138
+
139
+ ### To SWC (Recommended)
140
+ ```yaml
141
+ # config/shakapacker.yml
142
+ javascript_transpiler: 'swc'
143
+ ```
144
+ ```bash
145
+ npm install @swc/core swc-loader
146
+ ```
147
+
148
+ ### To esbuild
149
+ ```yaml
150
+ # config/shakapacker.yml
151
+ javascript_transpiler: 'esbuild'
152
+ ```
153
+ ```bash
154
+ npm install esbuild esbuild-loader
155
+ ```
156
+
157
+ ### To Babel
158
+ ```yaml
159
+ # config/shakapacker.yml
160
+ javascript_transpiler: 'babel'
161
+ ```
162
+ ```bash
163
+ npm install babel-loader @babel/core @babel/preset-env
164
+ ```
165
+
166
+ ## Testing Methodology
167
+
168
+ Benchmarks were conducted using:
169
+ 1. Clean builds (no cache)
170
+ 2. Average of 10 runs
171
+ 3. Same source code for all transpilers
172
+ 4. Production optimizations enabled
173
+ 5. Source maps disabled for fair comparison
174
+
175
+ ## Conclusion
176
+
177
+ For most projects, **SWC provides the best balance** of performance, features, and ease of use. It offers a 20x performance improvement over Babel with minimal configuration required.
178
+
179
+ Consider your specific requirements around browser support, plugin needs, and existing infrastructure when choosing a transpiler. The performance gains from switching to SWC or esbuild can significantly improve developer productivity and CI/CD pipeline efficiency.
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.