shakapacker 9.0.0.beta.5 → 9.0.0.beta.7
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/.eslintignore +1 -0
- data/.github/workflows/claude-code-review.yml +1 -1
- data/.github/workflows/generator.yml +6 -0
- data/.github/workflows/test-bundlers.yml +9 -9
- data/.gitignore +0 -1
- data/.npmignore +55 -0
- data/CONTRIBUTING.md +64 -0
- data/Gemfile.lock +1 -1
- data/README.md +81 -0
- data/docs/optional-peer-dependencies.md +198 -0
- data/docs/transpiler-migration.md +191 -0
- data/docs/typescript-migration.md +378 -0
- data/docs/v9_upgrade.md +65 -1
- data/lib/install/template.rb +54 -7
- data/lib/shakapacker/doctor.rb +1 -2
- data/lib/shakapacker/version.rb +1 -1
- data/package/.npmignore +4 -0
- data/package/config.ts +23 -10
- data/package/env.ts +15 -2
- data/package/environments/base.ts +2 -1
- data/package/environments/{development.js → development.ts} +30 -8
- data/package/environments/{production.js → production.ts} +18 -4
- data/package/environments/test.ts +53 -0
- data/package/environments/types.ts +90 -0
- data/package/index.ts +2 -1
- data/package/loaders.d.ts +1 -0
- data/package/types/README.md +87 -0
- data/package/types/index.ts +60 -0
- data/package/utils/errorCodes.ts +219 -0
- data/package/utils/errorHelpers.ts +68 -2
- data/package/utils/pathValidation.ts +139 -0
- data/package/utils/typeGuards.ts +161 -47
- data/package/webpack-types.d.ts +1 -0
- data/package.json +111 -5
- data/scripts/remove-use-strict.js +45 -0
- data/test/package/transpiler-defaults.test.js +127 -0
- data/test/peer-dependencies.sh +85 -0
- data/test/scripts/remove-use-strict.test.js +125 -0
- data/test/typescript/build.test.js +3 -2
- data/test/typescript/environments.test.js +107 -0
- data/test/typescript/pathValidation.test.js +142 -0
- data/test/typescript/securityValidation.test.js +182 -0
- metadata +28 -6
- data/package/environments/base.js +0 -116
- data/package/environments/test.js +0 -19
@@ -0,0 +1,191 @@
|
|
1
|
+
# JavaScript Transpiler Configuration
|
2
|
+
|
3
|
+
## Default Transpilers
|
4
|
+
|
5
|
+
Shakapacker uses different default JavaScript transpilers based on the bundler:
|
6
|
+
|
7
|
+
- **Webpack**: `babel` (default) - Maintains backward compatibility
|
8
|
+
- **Rspack**: `swc` (default) - Modern, faster transpiler for new bundler
|
9
|
+
|
10
|
+
## Available Transpilers
|
11
|
+
|
12
|
+
- `babel` - Traditional JavaScript transpiler with wide ecosystem support
|
13
|
+
- `swc` - Rust-based transpiler, 20-70x faster than Babel
|
14
|
+
- `esbuild` - Go-based transpiler, extremely fast
|
15
|
+
- `none` - No transpilation (use native JavaScript)
|
16
|
+
|
17
|
+
## Configuration
|
18
|
+
|
19
|
+
Set the transpiler in your `config/shakapacker.yml`:
|
20
|
+
|
21
|
+
```yaml
|
22
|
+
default: &default
|
23
|
+
# For webpack users (babel is default, no change needed)
|
24
|
+
javascript_transpiler: babel
|
25
|
+
|
26
|
+
# To opt-in to SWC for better performance
|
27
|
+
javascript_transpiler: swc
|
28
|
+
|
29
|
+
# For rspack users (swc is default, no change needed)
|
30
|
+
assets_bundler: rspack
|
31
|
+
javascript_transpiler: swc
|
32
|
+
```
|
33
|
+
|
34
|
+
## Migration Guide
|
35
|
+
|
36
|
+
### Migrating from Babel to SWC
|
37
|
+
|
38
|
+
SWC offers significant performance improvements while maintaining high compatibility with Babel.
|
39
|
+
|
40
|
+
#### 1. Install SWC dependencies
|
41
|
+
|
42
|
+
```bash
|
43
|
+
yarn add --dev @swc/core swc-loader
|
44
|
+
```
|
45
|
+
|
46
|
+
#### 2. Update your configuration
|
47
|
+
|
48
|
+
```yaml
|
49
|
+
# config/shakapacker.yml
|
50
|
+
default: &default
|
51
|
+
javascript_transpiler: swc
|
52
|
+
```
|
53
|
+
|
54
|
+
#### 3. Create SWC configuration (optional)
|
55
|
+
|
56
|
+
If you need custom transpilation settings, create `.swcrc`:
|
57
|
+
|
58
|
+
```json
|
59
|
+
{
|
60
|
+
"$schema": "https://json.schemastore.org/swcrc",
|
61
|
+
"jsc": {
|
62
|
+
"parser": {
|
63
|
+
"syntax": "ecmascript",
|
64
|
+
"jsx": true,
|
65
|
+
"dynamicImport": true
|
66
|
+
},
|
67
|
+
"transform": {
|
68
|
+
"react": {
|
69
|
+
"runtime": "automatic"
|
70
|
+
}
|
71
|
+
},
|
72
|
+
"target": "es2015"
|
73
|
+
},
|
74
|
+
"module": {
|
75
|
+
"type": "es6"
|
76
|
+
}
|
77
|
+
}
|
78
|
+
```
|
79
|
+
|
80
|
+
#### 4. Update React configuration (if using React)
|
81
|
+
|
82
|
+
For React projects, ensure you have the correct refresh plugin:
|
83
|
+
|
84
|
+
```bash
|
85
|
+
# For webpack
|
86
|
+
yarn add --dev @pmmmwh/react-refresh-webpack-plugin
|
87
|
+
|
88
|
+
# For rspack
|
89
|
+
yarn add --dev @rspack/plugin-react-refresh
|
90
|
+
```
|
91
|
+
|
92
|
+
### Performance Comparison
|
93
|
+
|
94
|
+
Typical build time improvements when migrating from Babel to SWC:
|
95
|
+
|
96
|
+
| Project Size | Babel | SWC | Improvement |
|
97
|
+
|-------------|-------|-----|-------------|
|
98
|
+
| Small (<100 files) | 5s | 1s | 5x faster |
|
99
|
+
| Medium (100-500 files) | 20s | 3s | 6.7x faster |
|
100
|
+
| Large (500+ files) | 60s | 8s | 7.5x faster |
|
101
|
+
|
102
|
+
### Compatibility Notes
|
103
|
+
|
104
|
+
#### Babel Features Not Yet in SWC
|
105
|
+
|
106
|
+
- Some experimental/stage-0 proposals
|
107
|
+
- Custom Babel plugins (need SWC equivalents)
|
108
|
+
- Babel macros
|
109
|
+
|
110
|
+
#### Migration Checklist
|
111
|
+
|
112
|
+
- [ ] Back up your current configuration
|
113
|
+
- [ ] Install SWC dependencies
|
114
|
+
- [ ] Update `shakapacker.yml`
|
115
|
+
- [ ] Test your build locally
|
116
|
+
- [ ] Run your test suite
|
117
|
+
- [ ] Check browser compatibility
|
118
|
+
- [ ] Deploy to staging environment
|
119
|
+
- [ ] Monitor for any runtime issues
|
120
|
+
|
121
|
+
### Rollback Plan
|
122
|
+
|
123
|
+
If you encounter issues, rolling back is simple:
|
124
|
+
|
125
|
+
```yaml
|
126
|
+
# config/shakapacker.yml
|
127
|
+
default: &default
|
128
|
+
javascript_transpiler: babel # Revert to babel
|
129
|
+
```
|
130
|
+
|
131
|
+
Then rebuild your application:
|
132
|
+
|
133
|
+
```bash
|
134
|
+
bin/shakapacker clobber
|
135
|
+
bin/shakapacker compile
|
136
|
+
```
|
137
|
+
|
138
|
+
## Environment Variables
|
139
|
+
|
140
|
+
You can also control the transpiler via environment variables:
|
141
|
+
|
142
|
+
```bash
|
143
|
+
# Override config file setting
|
144
|
+
SHAKAPACKER_JAVASCRIPT_TRANSPILER=swc bin/shakapacker compile
|
145
|
+
|
146
|
+
# For debugging
|
147
|
+
SHAKAPACKER_DEBUG_CACHE=true bin/shakapacker compile
|
148
|
+
```
|
149
|
+
|
150
|
+
## Troubleshooting
|
151
|
+
|
152
|
+
### Issue: Build fails after switching to SWC
|
153
|
+
|
154
|
+
**Solution**: Ensure all SWC dependencies are installed:
|
155
|
+
|
156
|
+
```bash
|
157
|
+
yarn add --dev @swc/core swc-loader
|
158
|
+
```
|
159
|
+
|
160
|
+
### Issue: React Fast Refresh not working
|
161
|
+
|
162
|
+
**Solution**: Install the correct refresh plugin for your bundler:
|
163
|
+
|
164
|
+
```bash
|
165
|
+
# Webpack
|
166
|
+
yarn add --dev @pmmmwh/react-refresh-webpack-plugin
|
167
|
+
|
168
|
+
# Rspack
|
169
|
+
yarn add --dev @rspack/plugin-react-refresh
|
170
|
+
```
|
171
|
+
|
172
|
+
### Issue: Decorators not working
|
173
|
+
|
174
|
+
**Solution**: Enable decorator support in `.swcrc`:
|
175
|
+
|
176
|
+
```json
|
177
|
+
{
|
178
|
+
"jsc": {
|
179
|
+
"parser": {
|
180
|
+
"decorators": true,
|
181
|
+
"decoratorsBeforeExport": true
|
182
|
+
}
|
183
|
+
}
|
184
|
+
}
|
185
|
+
```
|
186
|
+
|
187
|
+
## Further Reading
|
188
|
+
|
189
|
+
- [SWC Documentation](https://swc.rs/docs/getting-started)
|
190
|
+
- [Babel to SWC Migration Guide](https://swc.rs/docs/migrating-from-babel)
|
191
|
+
- [Rspack Configuration](https://www.rspack.dev/config/index)
|
@@ -0,0 +1,378 @@
|
|
1
|
+
# TypeScript Migration Guide for Shakapacker
|
2
|
+
|
3
|
+
This guide helps you adopt TypeScript types in your Shakapacker configuration files for better type safety and IDE support.
|
4
|
+
|
5
|
+
## Table of Contents
|
6
|
+
- [Benefits](#benefits)
|
7
|
+
- [Quick Start](#quick-start)
|
8
|
+
- [Migration Steps](#migration-steps)
|
9
|
+
- [Common Patterns](#common-patterns)
|
10
|
+
- [Troubleshooting](#troubleshooting)
|
11
|
+
|
12
|
+
## Benefits
|
13
|
+
|
14
|
+
Using TypeScript with Shakapacker provides:
|
15
|
+
- **Type Safety**: Catch configuration errors at compile time
|
16
|
+
- **IDE Support**: Get autocompletion and inline documentation
|
17
|
+
- **Better Refactoring**: Safely rename and restructure configurations
|
18
|
+
- **Self-documenting**: Types serve as inline documentation
|
19
|
+
|
20
|
+
## Quick Start
|
21
|
+
|
22
|
+
### 1. Install TypeScript Dependencies
|
23
|
+
|
24
|
+
```bash
|
25
|
+
yarn add --dev typescript @types/node @types/webpack
|
26
|
+
# or
|
27
|
+
npm install --save-dev typescript @types/node @types/webpack
|
28
|
+
```
|
29
|
+
|
30
|
+
### 2. Create a tsconfig.json
|
31
|
+
|
32
|
+
```json
|
33
|
+
{
|
34
|
+
"compilerOptions": {
|
35
|
+
"target": "ES2020",
|
36
|
+
"module": "commonjs",
|
37
|
+
"lib": ["ES2020"],
|
38
|
+
"strict": true,
|
39
|
+
"esModuleInterop": true,
|
40
|
+
"skipLibCheck": true,
|
41
|
+
"forceConsistentCasingInFileNames": true,
|
42
|
+
"resolveJsonModule": true,
|
43
|
+
"moduleResolution": "node",
|
44
|
+
"allowJs": true,
|
45
|
+
"checkJs": false,
|
46
|
+
"noEmit": true
|
47
|
+
},
|
48
|
+
"include": ["config/webpack/**/*"],
|
49
|
+
"exclude": ["node_modules"]
|
50
|
+
}
|
51
|
+
```
|
52
|
+
|
53
|
+
### 3. Convert Your Webpack Config to TypeScript
|
54
|
+
|
55
|
+
Rename `config/webpack/webpack.config.js` to `config/webpack/webpack.config.ts`:
|
56
|
+
|
57
|
+
```typescript
|
58
|
+
// config/webpack/webpack.config.ts
|
59
|
+
import { generateWebpackConfig, merge } from 'shakapacker'
|
60
|
+
import type { WebpackConfigWithDevServer } from 'shakapacker/types'
|
61
|
+
import type { Configuration } from 'webpack'
|
62
|
+
|
63
|
+
const customConfig: Configuration = {
|
64
|
+
resolve: {
|
65
|
+
extensions: ['.css', '.ts', '.tsx']
|
66
|
+
}
|
67
|
+
}
|
68
|
+
|
69
|
+
const config: Configuration = generateWebpackConfig(customConfig)
|
70
|
+
|
71
|
+
export default config
|
72
|
+
```
|
73
|
+
|
74
|
+
## Migration Steps
|
75
|
+
|
76
|
+
### Step 1: Import Types
|
77
|
+
|
78
|
+
Start by importing the types you need:
|
79
|
+
|
80
|
+
```typescript
|
81
|
+
import type {
|
82
|
+
Config,
|
83
|
+
WebpackConfigWithDevServer,
|
84
|
+
RspackConfigWithDevServer,
|
85
|
+
CompressionPluginOptions
|
86
|
+
} from 'shakapacker/types'
|
87
|
+
```
|
88
|
+
|
89
|
+
### Step 2: Type Your Configuration Objects
|
90
|
+
|
91
|
+
Add type annotations to your configuration objects:
|
92
|
+
|
93
|
+
```typescript
|
94
|
+
// Before (JavaScript)
|
95
|
+
const customConfig = {
|
96
|
+
resolve: {
|
97
|
+
extensions: ['.css', '.ts', '.tsx']
|
98
|
+
}
|
99
|
+
}
|
100
|
+
|
101
|
+
// After (TypeScript)
|
102
|
+
import type { Configuration } from 'webpack'
|
103
|
+
|
104
|
+
const customConfig: Configuration = {
|
105
|
+
resolve: {
|
106
|
+
extensions: ['.css', '.ts', '.tsx']
|
107
|
+
}
|
108
|
+
}
|
109
|
+
```
|
110
|
+
|
111
|
+
### Step 3: Type Your Custom Functions
|
112
|
+
|
113
|
+
If you have custom configuration functions, add type annotations:
|
114
|
+
|
115
|
+
```typescript
|
116
|
+
// Before (JavaScript)
|
117
|
+
function modifyConfig(config) {
|
118
|
+
config.plugins.push(new MyPlugin())
|
119
|
+
return config
|
120
|
+
}
|
121
|
+
|
122
|
+
// After (TypeScript)
|
123
|
+
import type { Configuration } from 'webpack'
|
124
|
+
import type { WebpackPluginInstance } from 'shakapacker/types'
|
125
|
+
|
126
|
+
function modifyConfig(config: Configuration): Configuration {
|
127
|
+
const plugins = config.plugins as WebpackPluginInstance[]
|
128
|
+
plugins.push(new MyPlugin())
|
129
|
+
return config
|
130
|
+
}
|
131
|
+
```
|
132
|
+
|
133
|
+
### Step 4: Handle Environment-Specific Configurations
|
134
|
+
|
135
|
+
```typescript
|
136
|
+
// config/webpack/development.ts
|
137
|
+
import { generateWebpackConfig } from 'shakapacker'
|
138
|
+
import type { WebpackConfigWithDevServer } from 'shakapacker/types'
|
139
|
+
|
140
|
+
const developmentConfig: WebpackConfigWithDevServer = generateWebpackConfig({
|
141
|
+
devtool: 'eval-cheap-module-source-map',
|
142
|
+
devServer: {
|
143
|
+
hot: true,
|
144
|
+
port: 3035
|
145
|
+
}
|
146
|
+
})
|
147
|
+
|
148
|
+
export default developmentConfig
|
149
|
+
```
|
150
|
+
|
151
|
+
## Common Patterns
|
152
|
+
|
153
|
+
### Pattern 1: Custom Loaders
|
154
|
+
|
155
|
+
```typescript
|
156
|
+
import type { RuleSetRule } from 'webpack'
|
157
|
+
|
158
|
+
const customLoader: RuleSetRule = {
|
159
|
+
test: /\.svg$/,
|
160
|
+
use: ['@svgr/webpack']
|
161
|
+
}
|
162
|
+
|
163
|
+
const config: Configuration = generateWebpackConfig({
|
164
|
+
module: {
|
165
|
+
rules: [customLoader]
|
166
|
+
}
|
167
|
+
})
|
168
|
+
```
|
169
|
+
|
170
|
+
### Pattern 2: Plugin Configuration
|
171
|
+
|
172
|
+
```typescript
|
173
|
+
import CompressionPlugin from 'compression-webpack-plugin'
|
174
|
+
import type { CompressionPluginOptions } from 'shakapacker/types'
|
175
|
+
|
176
|
+
const compressionOptions: CompressionPluginOptions = {
|
177
|
+
filename: '[path][base].gz',
|
178
|
+
algorithm: 'gzip',
|
179
|
+
test: /\.(js|css|html|json|ico|svg|eot|otf|ttf)$/
|
180
|
+
}
|
181
|
+
|
182
|
+
const config: Configuration = generateWebpackConfig({
|
183
|
+
plugins: [new CompressionPlugin(compressionOptions)]
|
184
|
+
})
|
185
|
+
```
|
186
|
+
|
187
|
+
### Pattern 3: Conditional Configuration
|
188
|
+
|
189
|
+
```typescript
|
190
|
+
import type { Configuration } from 'webpack'
|
191
|
+
import { env } from 'shakapacker'
|
192
|
+
|
193
|
+
const config: Configuration = generateWebpackConfig()
|
194
|
+
|
195
|
+
if (env.isProduction) {
|
196
|
+
// TypeScript knows config.optimization exists
|
197
|
+
config.optimization = {
|
198
|
+
...config.optimization,
|
199
|
+
minimize: true,
|
200
|
+
sideEffects: false
|
201
|
+
}
|
202
|
+
}
|
203
|
+
|
204
|
+
export default config
|
205
|
+
```
|
206
|
+
|
207
|
+
### Pattern 4: Rspack Configuration
|
208
|
+
|
209
|
+
```typescript
|
210
|
+
// config/rspack/rspack.config.ts
|
211
|
+
import type { RspackConfigWithDevServer } from 'shakapacker/types'
|
212
|
+
import { generateWebpackConfig } from 'shakapacker'
|
213
|
+
|
214
|
+
const rspackConfig: RspackConfigWithDevServer = generateWebpackConfig({
|
215
|
+
mode: 'development',
|
216
|
+
devServer: {
|
217
|
+
hot: true,
|
218
|
+
port: 3036
|
219
|
+
}
|
220
|
+
})
|
221
|
+
|
222
|
+
export default rspackConfig
|
223
|
+
```
|
224
|
+
|
225
|
+
## Type-checking Your Configuration
|
226
|
+
|
227
|
+
Add a script to your package.json to type-check your configuration:
|
228
|
+
|
229
|
+
```json
|
230
|
+
{
|
231
|
+
"scripts": {
|
232
|
+
"type-check": "tsc --noEmit",
|
233
|
+
"webpack:type-check": "tsc --noEmit config/webpack/*.ts"
|
234
|
+
}
|
235
|
+
}
|
236
|
+
```
|
237
|
+
|
238
|
+
Run type checking:
|
239
|
+
|
240
|
+
```bash
|
241
|
+
yarn type-check
|
242
|
+
# or
|
243
|
+
npm run type-check
|
244
|
+
```
|
245
|
+
|
246
|
+
## Available Types Reference
|
247
|
+
|
248
|
+
### Core Types
|
249
|
+
- `Config` - Shakapacker configuration from shakapacker.yml
|
250
|
+
- `Env` - Environment variables and helpers
|
251
|
+
- `DevServerConfig` - Development server configuration
|
252
|
+
|
253
|
+
### Webpack/Rspack Types
|
254
|
+
- `WebpackConfigWithDevServer` - Webpack configuration with dev server
|
255
|
+
- `RspackConfigWithDevServer` - Rspack configuration with dev server
|
256
|
+
- `WebpackPluginInstance` - Webpack plugin instance type
|
257
|
+
- `RspackPlugin` - Rspack plugin interface
|
258
|
+
|
259
|
+
### Helper Types
|
260
|
+
- `CompressionPluginOptions` - Compression plugin configuration
|
261
|
+
- `ReactRefreshWebpackPlugin` - React refresh for Webpack
|
262
|
+
- `ReactRefreshRspackPlugin` - React refresh for Rspack
|
263
|
+
|
264
|
+
## Troubleshooting
|
265
|
+
|
266
|
+
### Issue: "Cannot find module 'shakapacker/types'"
|
267
|
+
|
268
|
+
**Solution**: Make sure you're using Shakapacker v9.0.0 or later:
|
269
|
+
|
270
|
+
```bash
|
271
|
+
yarn upgrade shakapacker
|
272
|
+
```
|
273
|
+
|
274
|
+
### Issue: Type errors with plugins
|
275
|
+
|
276
|
+
**Solution**: Cast plugin arrays when needed:
|
277
|
+
|
278
|
+
```typescript
|
279
|
+
const plugins = (config.plugins || []) as WebpackPluginInstance[]
|
280
|
+
plugins.push(new MyPlugin())
|
281
|
+
```
|
282
|
+
|
283
|
+
### Issue: Missing types for custom loaders
|
284
|
+
|
285
|
+
**Solution**: Install type definitions or declare them:
|
286
|
+
|
287
|
+
```typescript
|
288
|
+
// If types aren't available, declare them
|
289
|
+
declare module 'my-custom-loader' {
|
290
|
+
const loader: any
|
291
|
+
export default loader
|
292
|
+
}
|
293
|
+
```
|
294
|
+
|
295
|
+
### Issue: Conflicting types between webpack versions
|
296
|
+
|
297
|
+
**Solution**: Ensure your webpack types match your webpack version:
|
298
|
+
|
299
|
+
```bash
|
300
|
+
yarn add --dev @types/webpack@^5
|
301
|
+
```
|
302
|
+
|
303
|
+
## Gradual Migration
|
304
|
+
|
305
|
+
You don't need to convert everything at once. Start with:
|
306
|
+
|
307
|
+
1. Convert your main webpack.config.js to TypeScript
|
308
|
+
2. Add types to the most complex configurations
|
309
|
+
3. Gradually type other configuration files
|
310
|
+
4. Add type checking to your CI pipeline
|
311
|
+
|
312
|
+
## Example: Full Configuration
|
313
|
+
|
314
|
+
Here's a complete example of a typed webpack configuration:
|
315
|
+
|
316
|
+
```typescript
|
317
|
+
// config/webpack/webpack.config.ts
|
318
|
+
import { generateWebpackConfig, merge, config as shakapackerConfig } from 'shakapacker'
|
319
|
+
import type { Configuration } from 'webpack'
|
320
|
+
import type { WebpackConfigWithDevServer } from 'shakapacker/types'
|
321
|
+
import CompressionPlugin from 'compression-webpack-plugin'
|
322
|
+
import { resolve } from 'path'
|
323
|
+
|
324
|
+
// Type-safe custom configuration
|
325
|
+
const customConfig: Configuration = {
|
326
|
+
resolve: {
|
327
|
+
extensions: ['.css', '.ts', '.tsx'],
|
328
|
+
alias: {
|
329
|
+
'@': resolve(__dirname, '../../app/javascript'),
|
330
|
+
'components': resolve(__dirname, '../../app/javascript/components'),
|
331
|
+
'utils': resolve(__dirname, '../../app/javascript/utils')
|
332
|
+
}
|
333
|
+
},
|
334
|
+
module: {
|
335
|
+
rules: [
|
336
|
+
{
|
337
|
+
test: /\.svg$/,
|
338
|
+
use: ['@svgr/webpack'],
|
339
|
+
issuer: /\.(tsx?|jsx?)$/
|
340
|
+
}
|
341
|
+
]
|
342
|
+
}
|
343
|
+
}
|
344
|
+
|
345
|
+
// Generate the final configuration
|
346
|
+
const webpackConfig: Configuration = generateWebpackConfig(customConfig)
|
347
|
+
|
348
|
+
// Type-safe modifications based on environment
|
349
|
+
if (shakapackerConfig.env === 'production') {
|
350
|
+
const plugins = (webpackConfig.plugins || []) as WebpackPluginInstance[]
|
351
|
+
|
352
|
+
plugins.push(
|
353
|
+
new CompressionPlugin({
|
354
|
+
filename: '[path][base].br',
|
355
|
+
algorithm: 'brotliCompress',
|
356
|
+
test: /\.(js|css|html|json|ico|svg|eot|otf|ttf)$/
|
357
|
+
})
|
358
|
+
)
|
359
|
+
}
|
360
|
+
|
361
|
+
export default webpackConfig
|
362
|
+
```
|
363
|
+
|
364
|
+
## Next Steps
|
365
|
+
|
366
|
+
After migrating to TypeScript:
|
367
|
+
|
368
|
+
1. **Enable strict checks**: Gradually enable stricter TypeScript options
|
369
|
+
2. **Add custom types**: Create type definitions for your application-specific configurations
|
370
|
+
3. **Share types**: Export reusable configuration types for your team
|
371
|
+
4. **Document with types**: Use JSDoc comments with your types for better documentation
|
372
|
+
|
373
|
+
## Resources
|
374
|
+
|
375
|
+
- [TypeScript Handbook](https://www.typescriptlang.org/docs/handbook/intro.html)
|
376
|
+
- [Webpack TypeScript Configuration](https://webpack.js.org/configuration/configuration-languages/#typescript)
|
377
|
+
- [Shakapacker Types Documentation](./types/README.md)
|
378
|
+
- [Migration Examples](https://github.com/shakacode/shakapacker/tree/main/examples/typescript-config)
|
data/docs/v9_upgrade.md
CHANGED
@@ -130,6 +130,35 @@ npm install esbuild esbuild-loader
|
|
130
130
|
assets_bundler: 'rspack' # or 'webpack' (default)
|
131
131
|
```
|
132
132
|
|
133
|
+
### 5. All Peer Dependencies Now Optional
|
134
|
+
|
135
|
+
**What changed:** All peer dependencies are now marked as optional via `peerDependenciesMeta`.
|
136
|
+
|
137
|
+
**Benefits:**
|
138
|
+
- **No installation warnings** - You won't see peer dependency warnings for packages you don't use
|
139
|
+
- **Install only what you need** - Using webpack? Don't install rspack. Using SWC? Don't install Babel.
|
140
|
+
- **Clear version constraints** - When you do install a package, version compatibility is still enforced
|
141
|
+
|
142
|
+
**What this means for you:**
|
143
|
+
- **Existing projects:** No changes needed. Your existing dependencies will continue to work.
|
144
|
+
- **New projects:** The installer only adds the packages you actually need based on your configuration.
|
145
|
+
- **Package manager behavior:** npm, yarn, and pnpm will no longer warn about missing peer dependencies.
|
146
|
+
|
147
|
+
**Example:** If you're using SWC with webpack, you only need:
|
148
|
+
```json
|
149
|
+
{
|
150
|
+
"dependencies": {
|
151
|
+
"shakapacker": "^9.0.0",
|
152
|
+
"@swc/core": "^1.3.0",
|
153
|
+
"swc-loader": "^0.2.0",
|
154
|
+
"webpack": "^5.76.0",
|
155
|
+
"webpack-cli": "^5.0.0",
|
156
|
+
"webpack-dev-server": "^5.0.0"
|
157
|
+
}
|
158
|
+
}
|
159
|
+
```
|
160
|
+
You won't get warnings about missing Babel, Rspack, or esbuild packages.
|
161
|
+
|
133
162
|
## Migration Steps
|
134
163
|
|
135
164
|
### Step 1: Update Dependencies
|
@@ -224,6 +253,41 @@ Update your global type definitions as shown in Step 2.
|
|
224
253
|
|
225
254
|
If you see warnings about CSS module exports, ensure you've updated all imports to use named exports or have properly configured the override.
|
226
255
|
|
256
|
+
### Unexpected Peer Dependency Warnings After Upgrade
|
257
|
+
|
258
|
+
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.
|
259
|
+
|
260
|
+
**For npm:**
|
261
|
+
```bash
|
262
|
+
rm -rf node_modules package-lock.json
|
263
|
+
npm install
|
264
|
+
```
|
265
|
+
|
266
|
+
**For Yarn:**
|
267
|
+
```bash
|
268
|
+
rm -rf node_modules yarn.lock
|
269
|
+
yarn install
|
270
|
+
```
|
271
|
+
|
272
|
+
**For pnpm:**
|
273
|
+
```bash
|
274
|
+
rm -rf node_modules pnpm-lock.yaml
|
275
|
+
pnpm install
|
276
|
+
```
|
277
|
+
|
278
|
+
**For Bun:**
|
279
|
+
```bash
|
280
|
+
rm -rf node_modules bun.lockb
|
281
|
+
bun install
|
282
|
+
```
|
283
|
+
|
284
|
+
**When is this necessary?**
|
285
|
+
- If you see peer dependency warnings for packages you don't use (e.g., warnings about Babel when using SWC)
|
286
|
+
- If your package manager cached the old dependency resolution from v8
|
287
|
+
- After switching transpilers or bundlers (e.g., from Babel to SWC, or webpack to rspack)
|
288
|
+
|
289
|
+
**Note:** This is typically only needed once after the v8 → v9 upgrade. Subsequent installs will use the correct dependency resolution.
|
290
|
+
|
227
291
|
## Need Help?
|
228
292
|
|
229
293
|
- See [CSS Modules Export Mode documentation](./css-modules-export-mode.md) for detailed configuration options
|
@@ -238,4 +302,4 @@ If you have a large codebase and need to migrate gradually:
|
|
238
302
|
2. Migrate files incrementally
|
239
303
|
3. Remove the override once migration is complete
|
240
304
|
|
241
|
-
This allows you to upgrade to v9 immediately while taking time to update your CSS module imports.
|
305
|
+
This allows you to upgrade to v9 immediately while taking time to update your CSS module imports.
|
data/lib/install/template.rb
CHANGED
@@ -125,13 +125,60 @@ if (setup_path = Rails.root.join("bin/setup")).exist?
|
|
125
125
|
end
|
126
126
|
|
127
127
|
Dir.chdir(Rails.root) do
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
128
|
+
# In CI, use the pre-packed tarball if available
|
129
|
+
if ENV["SHAKAPACKER_NPM_PACKAGE"]
|
130
|
+
package_path = ENV["SHAKAPACKER_NPM_PACKAGE"]
|
131
|
+
|
132
|
+
# Validate package path to prevent directory traversal and invalid file types
|
133
|
+
begin
|
134
|
+
# Resolve to absolute path
|
135
|
+
absolute_path = File.expand_path(package_path)
|
136
|
+
|
137
|
+
# Reject paths containing directory traversal
|
138
|
+
if package_path.include?("..") || absolute_path.include?("..")
|
139
|
+
say "❌ Security Error: Package path contains directory traversal: #{package_path}", :red
|
140
|
+
exit 1
|
141
|
+
end
|
142
|
+
|
143
|
+
# Ensure filename ends with .tgz or .tar.gz
|
144
|
+
unless absolute_path.end_with?(".tgz", ".tar.gz")
|
145
|
+
say "❌ Security Error: Package must be a .tgz or .tar.gz file: #{package_path}", :red
|
146
|
+
exit 1
|
147
|
+
end
|
148
|
+
|
149
|
+
# Check existence only after validation
|
150
|
+
if File.exist?(absolute_path)
|
151
|
+
say "📦 Installing shakapacker from local package: #{absolute_path}", :cyan
|
152
|
+
begin
|
153
|
+
@package_json.manager.add!([absolute_path], type: :production)
|
154
|
+
rescue PackageJson::Error
|
155
|
+
say "Shakapacker installation failed 😭 See above for details.", :red
|
156
|
+
exit 1
|
157
|
+
end
|
158
|
+
else
|
159
|
+
say "⚠️ SHAKAPACKER_NPM_PACKAGE set but file not found: #{absolute_path}", :yellow
|
160
|
+
say "Falling back to npm registry...", :yellow
|
161
|
+
npm_version = Shakapacker::Utils::VersionSyntaxConverter.new.rubygem_to_npm(Shakapacker::VERSION)
|
162
|
+
begin
|
163
|
+
@package_json.manager.add!(["shakapacker@#{npm_version}"], type: :production)
|
164
|
+
rescue PackageJson::Error
|
165
|
+
say "Shakapacker installation failed 😭 See above for details.", :red
|
166
|
+
exit 1
|
167
|
+
end
|
168
|
+
end
|
169
|
+
rescue => e
|
170
|
+
say "❌ Error validating package path: #{e.message}", :red
|
171
|
+
exit 1
|
172
|
+
end
|
173
|
+
else
|
174
|
+
npm_version = Shakapacker::Utils::VersionSyntaxConverter.new.rubygem_to_npm(Shakapacker::VERSION)
|
175
|
+
say "Installing shakapacker@#{npm_version}"
|
176
|
+
begin
|
177
|
+
@package_json.manager.add!(["shakapacker@#{npm_version}"], type: :production)
|
178
|
+
rescue PackageJson::Error
|
179
|
+
say "Shakapacker installation failed 😭 See above for details.", :red
|
180
|
+
exit 1
|
181
|
+
end
|
135
182
|
end
|
136
183
|
|
137
184
|
@package_json.merge! do |pj|
|