shakapacker 9.0.0.beta.9 → 9.0.0.beta.11
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +98 -16
- data/Gemfile.lock +1 -1
- data/docs/transpiler-migration.md +33 -36
- data/docs/v9_upgrade.md +80 -26
- data/lib/shakapacker/doctor.rb +10 -11
- data/lib/shakapacker/swc_migrator.rb +64 -38
- data/lib/shakapacker/version.rb +1 -1
- data/lib/shakapacker.rb +1 -1
- data/package/env.ts +25 -13
- data/package.json +1 -1
- data/test/package/config.test.js +3 -0
- data/test/package/env.test.js +42 -7
- data/test/package/environments/base.test.js +4 -0
- data/test/package/staging.test.js +4 -3
- metadata +2 -2
data/docs/v9_upgrade.md
CHANGED
|
@@ -9,12 +9,38 @@ This guide outlines new features, breaking changes, and migration steps for upgr
|
|
|
9
9
|
Shakapacker v9 includes TypeScript definitions for better IDE support and type safety.
|
|
10
10
|
|
|
11
11
|
- **No breaking changes** - JavaScript configs continue to work
|
|
12
|
-
- **Optional** - Use TypeScript only if you want it
|
|
12
|
+
- **Optional** - Use TypeScript only if you want it
|
|
13
13
|
- **Type safety** - Catch configuration errors at compile-time
|
|
14
14
|
- **IDE support** - Full autocomplete for all options
|
|
15
15
|
|
|
16
16
|
See the [TypeScript Documentation](./typescript.md) for usage examples.
|
|
17
17
|
|
|
18
|
+
### NODE_ENV Default Behavior Fixed
|
|
19
|
+
|
|
20
|
+
**What changed:** NODE_ENV now intelligently defaults based on RAILS_ENV instead of always defaulting to "production".
|
|
21
|
+
|
|
22
|
+
**New behavior:**
|
|
23
|
+
|
|
24
|
+
- When `RAILS_ENV=production` → `NODE_ENV` defaults to `"production"`
|
|
25
|
+
- When `RAILS_ENV=development` or unset → `NODE_ENV` defaults to `"development"`
|
|
26
|
+
- When `RAILS_ENV` is any other value (test, staging, etc.) → `NODE_ENV` defaults to `"development"`
|
|
27
|
+
|
|
28
|
+
**Benefits:**
|
|
29
|
+
|
|
30
|
+
- **Dev server "just works"** - No need to explicitly set NODE_ENV when running the development server
|
|
31
|
+
- **Correct configuration loaded** - Development server now properly loads the development configuration from shakapacker.yml
|
|
32
|
+
- **Fixes port issues** - Dev server uses the configured port (e.g., 3035) instead of defaulting to 8080
|
|
33
|
+
- **Fixes 404 errors** - Assets load correctly without requiring manual NODE_ENV configuration
|
|
34
|
+
|
|
35
|
+
**No action required** - This change improves the default behavior and requires no migration.
|
|
36
|
+
|
|
37
|
+
**If you previously worked around this bug**, you can now remove these workarounds:
|
|
38
|
+
|
|
39
|
+
- Remove `NODE_ENV=development` from your `.env`, `.env.development`, or `.env.local` files
|
|
40
|
+
- Remove `NODE_ENV=development` from your `docker-compose.yml` or Dockerfile
|
|
41
|
+
- Remove custom scripts that set NODE_ENV before running the dev server
|
|
42
|
+
- Remove `NODE_ENV=development` from your `bin/dev` or Procfile.dev
|
|
43
|
+
|
|
18
44
|
## Breaking Changes
|
|
19
45
|
|
|
20
46
|
### 1. CSS Modules Configuration Changed to Named Exports
|
|
@@ -25,25 +51,27 @@ See the [TypeScript Documentation](./typescript.md) for usage examples.
|
|
|
25
51
|
|
|
26
52
|
**Quick Reference: Configuration Options**
|
|
27
53
|
|
|
28
|
-
| Configuration
|
|
29
|
-
|
|
30
|
-
| **v9 Default**
|
|
31
|
-
| **Alternative** | `true`
|
|
32
|
-
| **v8 Style**
|
|
33
|
-
| **❌ Invalid**
|
|
54
|
+
| Configuration | namedExport | exportLocalsConvention | CSS: `.my-button` | Export Available | Works With |
|
|
55
|
+
| --------------- | ----------- | ---------------------- | ----------------- | --------------------------------- | ----------------- |
|
|
56
|
+
| **v9 Default** | `true` | `'camelCaseOnly'` | `.my-button` | `myButton` only | ✅ Named exports |
|
|
57
|
+
| **Alternative** | `true` | `'dashesOnly'` | `.my-button` | `'my-button'` only | ✅ Named exports |
|
|
58
|
+
| **v8 Style** | `false` | `'camelCase'` | `.my-button` | Both `myButton` AND `'my-button'` | ✅ Default export |
|
|
59
|
+
| **❌ Invalid** | `true` | `'camelCase'` | - | - | ❌ Build Error |
|
|
34
60
|
|
|
35
61
|
**JavaScript Projects:**
|
|
62
|
+
|
|
36
63
|
```js
|
|
37
64
|
// Before (v8)
|
|
38
|
-
import styles from
|
|
39
|
-
|
|
65
|
+
import styles from "./Component.module.css"
|
|
66
|
+
;<button className={styles.button} />
|
|
40
67
|
|
|
41
68
|
// After (v9)
|
|
42
|
-
import { button } from
|
|
43
|
-
|
|
69
|
+
import { button } from "./Component.module.css"
|
|
70
|
+
;<button className={button} />
|
|
44
71
|
```
|
|
45
72
|
|
|
46
73
|
**TypeScript Projects:**
|
|
74
|
+
|
|
47
75
|
```typescript
|
|
48
76
|
// Before (v8)
|
|
49
77
|
import styles from './Component.module.css';
|
|
@@ -57,6 +85,7 @@ import * as styles from './Component.module.css';
|
|
|
57
85
|
**Migration Options:**
|
|
58
86
|
|
|
59
87
|
1. **Update your code** (Recommended):
|
|
88
|
+
|
|
60
89
|
- JavaScript: Change to named imports (`import { className }`)
|
|
61
90
|
- TypeScript: Change to namespace imports (`import * as styles`)
|
|
62
91
|
- Kebab-case class names are automatically converted to camelCase
|
|
@@ -66,6 +95,7 @@ import * as styles from './Component.module.css';
|
|
|
66
95
|
- This gives you time to migrate gradually
|
|
67
96
|
|
|
68
97
|
**Benefits of the change:**
|
|
98
|
+
|
|
69
99
|
- Eliminates webpack/TypeScript warnings
|
|
70
100
|
- Better tree-shaking of unused CSS classes
|
|
71
101
|
- More explicit about which classes are used
|
|
@@ -76,15 +106,17 @@ import * as styles from './Component.module.css';
|
|
|
76
106
|
**What changed:** The configuration option has been renamed to better reflect its purpose.
|
|
77
107
|
|
|
78
108
|
**Before (v8):**
|
|
109
|
+
|
|
79
110
|
```yml
|
|
80
111
|
# config/shakapacker.yml
|
|
81
|
-
webpack_loader:
|
|
112
|
+
webpack_loader: "babel"
|
|
82
113
|
```
|
|
83
114
|
|
|
84
115
|
**After (v9):**
|
|
116
|
+
|
|
85
117
|
```yml
|
|
86
118
|
# config/shakapacker.yml
|
|
87
|
-
javascript_transpiler:
|
|
119
|
+
javascript_transpiler: "babel"
|
|
88
120
|
```
|
|
89
121
|
|
|
90
122
|
**Note:** The old `webpack_loader` option is deprecated but still supported with a warning.
|
|
@@ -96,38 +128,48 @@ javascript_transpiler: 'babel'
|
|
|
96
128
|
**Why:** SWC is 20x faster than Babel while maintaining compatibility with most JavaScript and TypeScript code.
|
|
97
129
|
|
|
98
130
|
**Impact on existing projects:**
|
|
131
|
+
|
|
99
132
|
- Your project will continue using Babel if you already have babel packages in package.json
|
|
100
133
|
- To switch to SWC for better performance, see migration options below
|
|
101
134
|
|
|
102
135
|
**Impact on new projects:**
|
|
136
|
+
|
|
103
137
|
- New installations will use SWC by default
|
|
104
138
|
- Babel dependencies won't be installed unless explicitly configured
|
|
105
139
|
|
|
106
140
|
### Migration Options
|
|
107
141
|
|
|
108
142
|
#### Option 1 (Recommended): Switch to SWC
|
|
143
|
+
|
|
109
144
|
```yml
|
|
110
145
|
# config/shakapacker.yml
|
|
111
|
-
javascript_transpiler:
|
|
146
|
+
javascript_transpiler: "swc"
|
|
112
147
|
```
|
|
148
|
+
|
|
113
149
|
Then install SWC:
|
|
150
|
+
|
|
114
151
|
```bash
|
|
115
152
|
npm install @swc/core swc-loader
|
|
116
153
|
```
|
|
117
154
|
|
|
118
155
|
#### Option 2: Keep using Babel
|
|
156
|
+
|
|
119
157
|
```yml
|
|
120
158
|
# config/shakapacker.yml
|
|
121
|
-
javascript_transpiler:
|
|
159
|
+
javascript_transpiler: "babel"
|
|
122
160
|
```
|
|
161
|
+
|
|
123
162
|
No other changes needed - your existing babel packages will continue to work.
|
|
124
163
|
|
|
125
164
|
#### Option 3: Use esbuild
|
|
165
|
+
|
|
126
166
|
```yml
|
|
127
167
|
# config/shakapacker.yml
|
|
128
|
-
javascript_transpiler:
|
|
168
|
+
javascript_transpiler: "esbuild"
|
|
129
169
|
```
|
|
170
|
+
|
|
130
171
|
Then install esbuild:
|
|
172
|
+
|
|
131
173
|
```bash
|
|
132
174
|
npm install esbuild esbuild-loader
|
|
133
175
|
```
|
|
@@ -138,7 +180,7 @@ npm install esbuild esbuild-loader
|
|
|
138
180
|
|
|
139
181
|
```yml
|
|
140
182
|
# config/shakapacker.yml
|
|
141
|
-
assets_bundler:
|
|
183
|
+
assets_bundler: "rspack" # or 'webpack' (default)
|
|
142
184
|
```
|
|
143
185
|
|
|
144
186
|
### 5. All Peer Dependencies Now Optional
|
|
@@ -146,16 +188,19 @@ assets_bundler: 'rspack' # or 'webpack' (default)
|
|
|
146
188
|
**What changed:** All peer dependencies are now marked as optional via `peerDependenciesMeta`.
|
|
147
189
|
|
|
148
190
|
**Benefits:**
|
|
191
|
+
|
|
149
192
|
- **No installation warnings** - You won't see peer dependency warnings for packages you don't use
|
|
150
193
|
- **Install only what you need** - Using webpack? Don't install rspack. Using SWC? Don't install Babel.
|
|
151
194
|
- **Clear version constraints** - When you do install a package, version compatibility is still enforced
|
|
152
195
|
|
|
153
196
|
**What this means for you:**
|
|
197
|
+
|
|
154
198
|
- **Existing projects:** No changes needed. Your existing dependencies will continue to work.
|
|
155
199
|
- **New projects:** The installer only adds the packages you actually need based on your configuration.
|
|
156
200
|
- **Package manager behavior:** npm, yarn, and pnpm will no longer warn about missing peer dependencies.
|
|
157
201
|
|
|
158
202
|
**Example:** If you're using SWC with webpack, you only need:
|
|
203
|
+
|
|
159
204
|
```json
|
|
160
205
|
{
|
|
161
206
|
"dependencies": {
|
|
@@ -168,6 +213,7 @@ assets_bundler: 'rspack' # or 'webpack' (default)
|
|
|
168
213
|
}
|
|
169
214
|
}
|
|
170
215
|
```
|
|
216
|
+
|
|
171
217
|
You won't get warnings about missing Babel, Rspack, or esbuild packages.
|
|
172
218
|
|
|
173
219
|
## Migration Steps
|
|
@@ -186,22 +232,22 @@ yarn upgrade shakapacker@^9.0.0
|
|
|
186
232
|
|
|
187
233
|
```js
|
|
188
234
|
// Find imports like this:
|
|
189
|
-
import styles from
|
|
235
|
+
import styles from "./styles.module.css"
|
|
190
236
|
|
|
191
237
|
// Replace with named imports:
|
|
192
|
-
import { className1, className2 } from
|
|
238
|
+
import { className1, className2 } from "./styles.module.css"
|
|
193
239
|
```
|
|
194
240
|
|
|
195
241
|
#### Update TypeScript definitions:
|
|
196
242
|
|
|
197
243
|
```typescript
|
|
198
244
|
// Update your CSS module type definitions
|
|
199
|
-
declare module
|
|
245
|
+
declare module "*.module.css" {
|
|
200
246
|
// With namedExport: true, css-loader generates individual named exports
|
|
201
247
|
// TypeScript can't know the exact names at compile time, so we declare
|
|
202
248
|
// a module with any number of string exports
|
|
203
|
-
const classes: { readonly [key: string]: string }
|
|
204
|
-
export = classes
|
|
249
|
+
const classes: { readonly [key: string]: string }
|
|
250
|
+
export = classes
|
|
205
251
|
// Note: This allows 'import * as styles' but not 'import styles from'
|
|
206
252
|
// because css-loader with namedExport: true doesn't generate a default export
|
|
207
253
|
}
|
|
@@ -213,13 +259,15 @@ v9 automatically converts kebab-case to camelCase with `exportLocalsConvention:
|
|
|
213
259
|
|
|
214
260
|
```css
|
|
215
261
|
/* styles.module.css */
|
|
216
|
-
.my-button {
|
|
217
|
-
|
|
262
|
+
.my-button {
|
|
263
|
+
}
|
|
264
|
+
.primary-color {
|
|
265
|
+
}
|
|
218
266
|
```
|
|
219
267
|
|
|
220
268
|
```js
|
|
221
269
|
// v9 default - camelCase conversion
|
|
222
|
-
import { myButton, primaryColor } from
|
|
270
|
+
import { myButton, primaryColor } from "./styles.module.css"
|
|
223
271
|
```
|
|
224
272
|
|
|
225
273
|
**Alternative: Keep kebab-case names with 'dashesOnly'**
|
|
@@ -256,7 +304,7 @@ If you have `webpack_loader` in your configuration:
|
|
|
256
304
|
# webpack_loader: 'babel'
|
|
257
305
|
|
|
258
306
|
# NEW:
|
|
259
|
-
javascript_transpiler:
|
|
307
|
+
javascript_transpiler: "babel"
|
|
260
308
|
```
|
|
261
309
|
|
|
262
310
|
### Step 5: Run Tests
|
|
@@ -291,6 +339,7 @@ If you see warnings about CSS module exports, ensure you've updated all imports
|
|
|
291
339
|
### Build Error: exportLocalsConvention Incompatible with namedExport
|
|
292
340
|
|
|
293
341
|
If you see this error:
|
|
342
|
+
|
|
294
343
|
```
|
|
295
344
|
"exportLocalsConvention" with "camelCase" value is incompatible with "namedExport: true" option
|
|
296
345
|
```
|
|
@@ -312,30 +361,35 @@ If you want to use `'camelCase'` (which exports both original and camelCase vers
|
|
|
312
361
|
If you experience unexpected peer dependency warnings after upgrading to v9, you may need to clear your package manager's cache and reinstall dependencies. This ensures the new optional peer dependency configuration takes effect properly.
|
|
313
362
|
|
|
314
363
|
**For npm:**
|
|
364
|
+
|
|
315
365
|
```bash
|
|
316
366
|
rm -rf node_modules package-lock.json
|
|
317
367
|
npm install
|
|
318
368
|
```
|
|
319
369
|
|
|
320
370
|
**For Yarn:**
|
|
371
|
+
|
|
321
372
|
```bash
|
|
322
373
|
rm -rf node_modules yarn.lock
|
|
323
374
|
yarn install
|
|
324
375
|
```
|
|
325
376
|
|
|
326
377
|
**For pnpm:**
|
|
378
|
+
|
|
327
379
|
```bash
|
|
328
380
|
rm -rf node_modules pnpm-lock.yaml
|
|
329
381
|
pnpm install
|
|
330
382
|
```
|
|
331
383
|
|
|
332
384
|
**For Bun:**
|
|
385
|
+
|
|
333
386
|
```bash
|
|
334
387
|
rm -rf node_modules bun.lockb
|
|
335
388
|
bun install
|
|
336
389
|
```
|
|
337
390
|
|
|
338
391
|
**When is this necessary?**
|
|
392
|
+
|
|
339
393
|
- If you see peer dependency warnings for packages you don't use (e.g., warnings about Babel when using SWC)
|
|
340
394
|
- If your package manager cached the old dependency resolution from v8
|
|
341
395
|
- After switching transpilers or bundlers (e.g., from Babel to SWC, or webpack to rspack)
|
data/lib/shakapacker/doctor.rb
CHANGED
|
@@ -442,18 +442,17 @@ module Shakapacker
|
|
|
442
442
|
|
|
443
443
|
def check_swc_config_conflicts
|
|
444
444
|
swcrc_path = root_path.join(".swcrc")
|
|
445
|
-
|
|
445
|
+
swc_config_path = root_path.join("config/swc.config.js")
|
|
446
446
|
|
|
447
|
-
|
|
448
|
-
swcrc
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
@warnings << "SWC configuration: .swcrc exists but contains invalid JSON"
|
|
447
|
+
if swcrc_path.exist?
|
|
448
|
+
@warnings << "SWC configuration: .swcrc file detected. This file completely overrides Shakapacker's default SWC settings and may cause build failures. " \
|
|
449
|
+
"Please migrate to config/swc.config.js which properly merges with Shakapacker defaults. " \
|
|
450
|
+
"To migrate: Move your custom settings from .swcrc to config/swc.config.js (see docs for format). " \
|
|
451
|
+
"See: https://github.com/shakacode/shakapacker/blob/main/docs/using_swc_loader.md"
|
|
452
|
+
end
|
|
453
|
+
|
|
454
|
+
if swc_config_path.exist?
|
|
455
|
+
@info << "SWC configuration: Using config/swc.config.js (recommended). This config is merged with Shakapacker's defaults."
|
|
457
456
|
end
|
|
458
457
|
end
|
|
459
458
|
|
|
@@ -8,8 +8,9 @@ module Shakapacker
|
|
|
8
8
|
class SwcMigrator
|
|
9
9
|
attr_reader :root_path, :logger
|
|
10
10
|
|
|
11
|
+
# Babel packages safe to remove when migrating to SWC
|
|
12
|
+
# Note: @babel/core and @babel/eslint-parser are excluded as they may be needed for ESLint
|
|
11
13
|
BABEL_PACKAGES = [
|
|
12
|
-
"@babel/core",
|
|
13
14
|
"@babel/plugin-proposal-class-properties",
|
|
14
15
|
"@babel/plugin-proposal-object-rest-spread",
|
|
15
16
|
"@babel/plugin-syntax-dynamic-import",
|
|
@@ -25,6 +26,12 @@ module Shakapacker
|
|
|
25
26
|
"babel-plugin-transform-react-remove-prop-types"
|
|
26
27
|
].freeze
|
|
27
28
|
|
|
29
|
+
# Babel packages that may be needed for ESLint - only remove if user explicitly confirms
|
|
30
|
+
ESLINT_BABEL_PACKAGES = [
|
|
31
|
+
"@babel/core",
|
|
32
|
+
"@babel/eslint-parser"
|
|
33
|
+
].freeze
|
|
34
|
+
|
|
28
35
|
SWC_PACKAGES = {
|
|
29
36
|
"@swc/core" => "^1.7.39",
|
|
30
37
|
"swc-loader" => "^0.2.6"
|
|
@@ -39,23 +46,21 @@ module Shakapacker
|
|
|
39
46
|
.eslintrc.json
|
|
40
47
|
].freeze
|
|
41
48
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
49
|
+
DEFAULT_SWC_CONFIG = <<~JS.freeze
|
|
50
|
+
// config/swc.config.js
|
|
51
|
+
// This file is merged with Shakapacker's default SWC configuration
|
|
52
|
+
// See: https://swc.rs/docs/configuration/compilation
|
|
53
|
+
|
|
54
|
+
module.exports = {
|
|
55
|
+
jsc: {
|
|
56
|
+
transform: {
|
|
57
|
+
react: {
|
|
58
|
+
runtime: "automatic"
|
|
59
|
+
}
|
|
52
60
|
}
|
|
53
61
|
}
|
|
54
|
-
},
|
|
55
|
-
"module" => {
|
|
56
|
-
"type" => "es6"
|
|
57
62
|
}
|
|
58
|
-
|
|
63
|
+
JS
|
|
59
64
|
|
|
60
65
|
def initialize(root_path, logger: nil)
|
|
61
66
|
@root_path = Pathname.new(root_path)
|
|
@@ -68,7 +73,7 @@ module Shakapacker
|
|
|
68
73
|
results = {
|
|
69
74
|
config_updated: update_shakapacker_config,
|
|
70
75
|
packages_installed: install_swc_packages,
|
|
71
|
-
|
|
76
|
+
swc_config_created: create_swc_config,
|
|
72
77
|
babel_packages_found: find_babel_packages
|
|
73
78
|
}
|
|
74
79
|
|
|
@@ -76,9 +81,9 @@ module Shakapacker
|
|
|
76
81
|
logger.info " Note: SWC is approximately 20x faster than Babel for transpilation."
|
|
77
82
|
logger.info " Please test your application thoroughly after migration."
|
|
78
83
|
logger.info "\n📝 Configuration Info:"
|
|
79
|
-
logger.info " - .
|
|
80
|
-
logger.info " -
|
|
81
|
-
logger.info " -
|
|
84
|
+
logger.info " - config/swc.config.js is merged with Shakapacker's default SWC configuration"
|
|
85
|
+
logger.info " - You can customize config/swc.config.js to add additional options"
|
|
86
|
+
logger.info " - Avoid using .swcrc as it overrides Shakapacker defaults completely"
|
|
82
87
|
|
|
83
88
|
# Show cleanup recommendations if babel packages found
|
|
84
89
|
if results[:babel_packages_found].any?
|
|
@@ -108,20 +113,21 @@ module Shakapacker
|
|
|
108
113
|
package_json_path = root_path.join("package.json")
|
|
109
114
|
unless package_json_path.exist?
|
|
110
115
|
logger.error "❌ No package.json found"
|
|
111
|
-
return { removed_packages: [], config_files_deleted: [] }
|
|
116
|
+
return { removed_packages: [], config_files_deleted: [], preserved_packages: [] }
|
|
112
117
|
end
|
|
113
118
|
|
|
114
119
|
# Check if ESLint uses Babel parser
|
|
120
|
+
preserved_for_eslint = []
|
|
115
121
|
if eslint_uses_babel?
|
|
116
|
-
logger.info "\n⚠️
|
|
117
|
-
logger.info "
|
|
118
|
-
logger.info "
|
|
119
|
-
logger.info "
|
|
120
|
-
logger.info "
|
|
121
|
-
|
|
122
|
+
logger.info "\n⚠️ ESLint configuration detected that uses Babel parser"
|
|
123
|
+
logger.info " Preserving @babel/core and @babel/eslint-parser for ESLint compatibility"
|
|
124
|
+
logger.info " To switch ESLint parser:"
|
|
125
|
+
logger.info " 1. For TypeScript: use @typescript-eslint/parser"
|
|
126
|
+
logger.info " 2. For JavaScript: use espree (ESLint's default parser)"
|
|
127
|
+
preserved_for_eslint = ESLINT_BABEL_PACKAGES
|
|
122
128
|
end
|
|
123
129
|
|
|
124
|
-
removed_packages = remove_babel_from_package_json(package_json_path)
|
|
130
|
+
removed_packages = remove_babel_from_package_json(package_json_path, preserve: preserved_for_eslint)
|
|
125
131
|
deleted_files = delete_babel_config_files
|
|
126
132
|
|
|
127
133
|
if removed_packages.any?
|
|
@@ -131,7 +137,7 @@ module Shakapacker
|
|
|
131
137
|
logger.info "ℹ️ No Babel packages found to remove"
|
|
132
138
|
end
|
|
133
139
|
|
|
134
|
-
{ removed_packages: removed_packages, config_files_deleted: deleted_files }
|
|
140
|
+
{ removed_packages: removed_packages, config_files_deleted: deleted_files, preserved_packages: preserved_for_eslint }
|
|
135
141
|
end
|
|
136
142
|
|
|
137
143
|
def find_babel_packages
|
|
@@ -144,7 +150,9 @@ module Shakapacker
|
|
|
144
150
|
dev_dependencies = package_json["devDependencies"] || {}
|
|
145
151
|
all_deps = dependencies.merge(dev_dependencies)
|
|
146
152
|
|
|
147
|
-
|
|
153
|
+
# Find all babel packages (including ESLint-related ones for display)
|
|
154
|
+
all_babel_packages = BABEL_PACKAGES + ESLINT_BABEL_PACKAGES
|
|
155
|
+
found_packages = all_babel_packages.select { |pkg| all_deps.key?(pkg) }
|
|
148
156
|
found_packages
|
|
149
157
|
rescue JSON::ParserError => e
|
|
150
158
|
logger.error "Failed to parse package.json: #{e.message}"
|
|
@@ -174,6 +182,11 @@ module Shakapacker
|
|
|
174
182
|
begin
|
|
175
183
|
package_json = JSON.parse(File.read(package_json_path))
|
|
176
184
|
if package_json["eslintConfig"]
|
|
185
|
+
# Check parser field explicitly
|
|
186
|
+
parser = package_json["eslintConfig"]["parser"]
|
|
187
|
+
return true if parser && parser.match?(/@babel\/eslint-parser|babel-eslint/)
|
|
188
|
+
|
|
189
|
+
# Also check entire config for babel parser references (catches nested configs)
|
|
177
190
|
return true if package_json["eslintConfig"].to_json.match?(/@babel\/eslint-parser|babel-eslint/)
|
|
178
191
|
end
|
|
179
192
|
|
|
@@ -254,29 +267,35 @@ module Shakapacker
|
|
|
254
267
|
{}
|
|
255
268
|
end
|
|
256
269
|
|
|
257
|
-
def
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
270
|
+
def create_swc_config
|
|
271
|
+
config_dir = root_path.join("config")
|
|
272
|
+
swc_config_path = config_dir.join("swc.config.js")
|
|
273
|
+
|
|
274
|
+
if swc_config_path.exist?
|
|
275
|
+
logger.info "ℹ️ config/swc.config.js already exists"
|
|
261
276
|
return false
|
|
262
277
|
end
|
|
263
278
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
logger.info "
|
|
279
|
+
FileUtils.mkdir_p(config_dir) unless config_dir.exist?
|
|
280
|
+
|
|
281
|
+
logger.info "📄 Creating config/swc.config.js..."
|
|
282
|
+
File.write(swc_config_path, DEFAULT_SWC_CONFIG)
|
|
283
|
+
logger.info "✅ config/swc.config.js created"
|
|
267
284
|
true
|
|
268
285
|
rescue StandardError => e
|
|
269
|
-
logger.error "Failed to create .
|
|
286
|
+
logger.error "Failed to create config/swc.config.js: #{e.message}"
|
|
270
287
|
false
|
|
271
288
|
end
|
|
272
289
|
|
|
273
|
-
def remove_babel_from_package_json(package_json_path)
|
|
290
|
+
def remove_babel_from_package_json(package_json_path, preserve: [])
|
|
274
291
|
package_json = JSON.parse(File.read(package_json_path))
|
|
275
292
|
dependencies = package_json["dependencies"] || {}
|
|
276
293
|
dev_dependencies = package_json["devDependencies"] || {}
|
|
277
294
|
removed_packages = []
|
|
278
295
|
|
|
279
296
|
BABEL_PACKAGES.each do |package|
|
|
297
|
+
next if preserve.include?(package)
|
|
298
|
+
|
|
280
299
|
if dependencies.delete(package)
|
|
281
300
|
removed_packages << package
|
|
282
301
|
logger.info " - Removed #{package} from dependencies"
|
|
@@ -287,6 +306,13 @@ module Shakapacker
|
|
|
287
306
|
end
|
|
288
307
|
end
|
|
289
308
|
|
|
309
|
+
# Log preserved packages
|
|
310
|
+
preserve.each do |package|
|
|
311
|
+
if dependencies[package] || dev_dependencies[package]
|
|
312
|
+
logger.info " - Preserved #{package} (needed for ESLint)"
|
|
313
|
+
end
|
|
314
|
+
end
|
|
315
|
+
|
|
290
316
|
if removed_packages.any?
|
|
291
317
|
package_json["dependencies"] = dependencies
|
|
292
318
|
package_json["devDependencies"] = dev_dependencies
|
data/lib/shakapacker/version.rb
CHANGED
data/lib/shakapacker.rb
CHANGED
data/package/env.ts
CHANGED
|
@@ -6,21 +6,32 @@ const { isFileNotFoundError } = require("./utils/errorHelpers")
|
|
|
6
6
|
const { sanitizeEnvValue } = require("./utils/pathValidation")
|
|
7
7
|
|
|
8
8
|
const NODE_ENVIRONMENTS = ["development", "production", "test"] as const
|
|
9
|
-
const DEFAULT = "production"
|
|
10
9
|
|
|
11
10
|
// Sanitize environment variables to prevent injection
|
|
12
11
|
const initialRailsEnv = sanitizeEnvValue(process.env.RAILS_ENV)
|
|
13
12
|
const rawNodeEnv = sanitizeEnvValue(process.env.NODE_ENV)
|
|
14
13
|
|
|
14
|
+
// Default NODE_ENV based on RAILS_ENV to match bin/shakapacker behavior (see lib/shakapacker/runner.rb:27)
|
|
15
|
+
// - RAILS_ENV=production → DEFAULT="production" (safe for production builds)
|
|
16
|
+
// - RAILS_ENV=development, test, staging, or unset → DEFAULT="development" (good DX for dev server)
|
|
17
|
+
// This ensures the dev server works out of the box without requiring NODE_ENV to be set explicitly
|
|
18
|
+
const DEFAULT = initialRailsEnv === "production" ? "production" : "development"
|
|
19
|
+
|
|
15
20
|
// Validate NODE_ENV strictly
|
|
16
21
|
const nodeEnv =
|
|
17
|
-
rawNodeEnv &&
|
|
22
|
+
rawNodeEnv &&
|
|
23
|
+
NODE_ENVIRONMENTS.includes(rawNodeEnv as (typeof NODE_ENVIRONMENTS)[number])
|
|
24
|
+
? rawNodeEnv
|
|
25
|
+
: DEFAULT
|
|
18
26
|
|
|
19
27
|
// Log warning if NODE_ENV was invalid
|
|
20
|
-
if (
|
|
28
|
+
if (
|
|
29
|
+
rawNodeEnv &&
|
|
30
|
+
!NODE_ENVIRONMENTS.includes(rawNodeEnv as (typeof NODE_ENVIRONMENTS)[number])
|
|
31
|
+
) {
|
|
21
32
|
console.warn(
|
|
22
33
|
`[SHAKAPACKER WARNING] Invalid NODE_ENV value: ${rawNodeEnv}. ` +
|
|
23
|
-
|
|
34
|
+
`Valid values are: ${NODE_ENVIRONMENTS.join(", ")}. Using default: ${DEFAULT}`
|
|
24
35
|
)
|
|
25
36
|
}
|
|
26
37
|
|
|
@@ -42,13 +53,13 @@ try {
|
|
|
42
53
|
} catch (defaultError) {
|
|
43
54
|
throw new Error(
|
|
44
55
|
`Failed to load Shakapacker configuration.\n` +
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
56
|
+
`Neither user config (${configPath}) nor default config (${defaultConfigPath}) could be loaded.\n\n` +
|
|
57
|
+
`To fix this issue:\n` +
|
|
58
|
+
`1. Create a config/shakapacker.yml file in your project\n` +
|
|
59
|
+
`2. Or set the SHAKAPACKER_CONFIG environment variable to point to your config file\n` +
|
|
60
|
+
`3. Or reinstall Shakapacker to restore the default configuration:\n` +
|
|
61
|
+
` npm install shakapacker --force\n` +
|
|
62
|
+
` yarn add shakapacker --force`
|
|
52
63
|
)
|
|
53
64
|
}
|
|
54
65
|
} else {
|
|
@@ -61,13 +72,14 @@ const regex = new RegExp(`^(${availableEnvironments})$`, "g")
|
|
|
61
72
|
|
|
62
73
|
const runningWebpackDevServer = process.env.WEBPACK_SERVE === "true"
|
|
63
74
|
|
|
64
|
-
const validatedRailsEnv =
|
|
75
|
+
const validatedRailsEnv =
|
|
76
|
+
initialRailsEnv && initialRailsEnv.match(regex) ? initialRailsEnv : DEFAULT
|
|
65
77
|
|
|
66
78
|
if (initialRailsEnv && validatedRailsEnv !== initialRailsEnv) {
|
|
67
79
|
/* eslint no-console:0 */
|
|
68
80
|
console.warn(
|
|
69
81
|
`[SHAKAPACKER WARNING] Environment '${initialRailsEnv}' not found in the configuration.\n` +
|
|
70
|
-
|
|
82
|
+
`Using '${DEFAULT}' configuration as a fallback.`
|
|
71
83
|
)
|
|
72
84
|
}
|
|
73
85
|
|
data/package.json
CHANGED
data/test/package/config.test.js
CHANGED
|
@@ -71,6 +71,7 @@ describe("Config", () => {
|
|
|
71
71
|
})
|
|
72
72
|
|
|
73
73
|
test("should allow enabling integrity", () => {
|
|
74
|
+
process.env.RAILS_ENV = "production"
|
|
74
75
|
process.env.SHAKAPACKER_CONFIG = "config/shakapacker_integrity.yml"
|
|
75
76
|
const config = require("../../package/config")
|
|
76
77
|
|
|
@@ -78,6 +79,7 @@ describe("Config", () => {
|
|
|
78
79
|
})
|
|
79
80
|
|
|
80
81
|
test("should allow configuring hash functions", () => {
|
|
82
|
+
process.env.RAILS_ENV = "production"
|
|
81
83
|
process.env.SHAKAPACKER_CONFIG = "config/shakapacker_integrity.yml"
|
|
82
84
|
const config = require("../../package/config")
|
|
83
85
|
|
|
@@ -89,6 +91,7 @@ describe("Config", () => {
|
|
|
89
91
|
})
|
|
90
92
|
|
|
91
93
|
test("should allow configuring crossorigin", () => {
|
|
94
|
+
process.env.RAILS_ENV = "production"
|
|
92
95
|
process.env.SHAKAPACKER_CONFIG = "config/shakapacker_integrity.yml"
|
|
93
96
|
const config = require("../../package/config")
|
|
94
97
|
|