shakapacker 8.0.2 → 9.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.eslintignore +1 -0
- data/.eslintrc.fast.js +40 -0
- data/.eslintrc.js +48 -0
- data/.github/STATUS.md +1 -0
- data/.github/workflows/claude-code-review.yml +54 -0
- data/.github/workflows/claude.yml +50 -0
- data/.github/workflows/dummy.yml +9 -4
- data/.github/workflows/generator.yml +32 -10
- data/.github/workflows/node.yml +23 -1
- data/.github/workflows/ruby.yml +33 -2
- data/.github/workflows/test-bundlers.yml +170 -0
- data/.gitignore +20 -0
- data/.husky/pre-commit +2 -0
- data/.npmignore +56 -0
- data/.prettierignore +3 -0
- data/.rubocop.yml +1 -0
- data/.yalcignore +26 -0
- data/CHANGELOG.md +302 -16
- data/CLAUDE.md +29 -0
- data/CONTRIBUTING.md +138 -20
- data/Gemfile.lock +83 -89
- data/README.md +343 -105
- data/Rakefile +39 -4
- data/TODO.md +50 -0
- data/TODO_v9.md +87 -0
- data/bin/export-bundler-config +11 -0
- data/conductor-setup.sh +70 -0
- data/conductor.json +7 -0
- data/docs/cdn_setup.md +379 -0
- data/docs/common-upgrades.md +615 -0
- data/docs/css-modules-export-mode.md +512 -0
- data/docs/deployment.md +62 -9
- data/docs/optional-peer-dependencies.md +198 -0
- data/docs/peer-dependencies.md +60 -0
- data/docs/react.md +6 -14
- data/docs/releasing.md +197 -0
- data/docs/rspack.md +190 -0
- data/docs/rspack_migration_guide.md +305 -0
- data/docs/subresource_integrity.md +54 -0
- data/docs/transpiler-migration.md +209 -0
- data/docs/transpiler-performance.md +179 -0
- data/docs/troubleshooting.md +157 -22
- data/docs/typescript-migration.md +379 -0
- data/docs/typescript.md +99 -0
- data/docs/using_esbuild_loader.md +3 -3
- data/docs/using_swc_loader.md +112 -10
- data/docs/v6_upgrade.md +10 -0
- data/docs/v8_upgrade.md +3 -5
- data/docs/v9_upgrade.md +458 -0
- data/gemfiles/Gemfile-rails.6.0.x +2 -1
- data/gemfiles/Gemfile-rails.6.1.x +1 -1
- data/gemfiles/Gemfile-rails.7.0.x +2 -2
- data/gemfiles/Gemfile-rails.7.1.x +1 -2
- data/gemfiles/Gemfile-rails.7.2.x +11 -0
- data/gemfiles/Gemfile-rails.8.0.x +11 -0
- data/lib/install/bin/export-bundler-config +11 -0
- data/lib/install/bin/shakapacker +4 -6
- data/lib/install/bin/shakapacker-dev-server +1 -1
- data/lib/install/config/rspack/rspack.config.js +6 -0
- data/lib/install/config/rspack/rspack.config.ts +7 -0
- data/lib/install/config/shakapacker.yml +25 -5
- data/lib/install/config/webpack/webpack.config.ts +7 -0
- data/lib/install/package.json +38 -0
- data/lib/install/template.rb +194 -44
- data/lib/shakapacker/bundler_switcher.rb +329 -0
- data/lib/shakapacker/compiler.rb +2 -1
- data/lib/shakapacker/compiler_strategy.rb +2 -2
- data/lib/shakapacker/configuration.rb +173 -2
- data/lib/shakapacker/dev_server_runner.rb +29 -8
- data/lib/shakapacker/digest_strategy.rb +2 -1
- data/lib/shakapacker/doctor.rb +905 -0
- data/lib/shakapacker/helper.rb +64 -16
- data/lib/shakapacker/manifest.rb +10 -3
- data/lib/shakapacker/mtime_strategy.rb +1 -1
- data/lib/shakapacker/railtie.rb +4 -4
- data/lib/shakapacker/rspack_runner.rb +19 -0
- data/lib/shakapacker/runner.rb +159 -10
- data/lib/shakapacker/swc_migrator.rb +384 -0
- data/lib/shakapacker/utils/manager.rb +15 -2
- data/lib/shakapacker/version.rb +1 -1
- data/lib/shakapacker/version_checker.rb +2 -2
- data/lib/shakapacker/webpack_runner.rb +6 -43
- data/lib/shakapacker.rb +22 -11
- data/lib/tasks/shakapacker/doctor.rake +8 -0
- data/lib/tasks/shakapacker/export_bundler_config.rake +72 -0
- data/lib/tasks/shakapacker/install.rake +12 -2
- data/lib/tasks/shakapacker/migrate_to_swc.rake +13 -0
- data/lib/tasks/shakapacker/switch_bundler.rake +82 -0
- data/lib/tasks/shakapacker.rake +2 -0
- data/package/.npmignore +4 -0
- data/package/babel/preset.ts +56 -0
- data/package/config.ts +175 -0
- data/package/configExporter/cli.ts +683 -0
- data/package/configExporter/configDocs.ts +102 -0
- data/package/configExporter/fileWriter.ts +92 -0
- data/package/configExporter/index.ts +5 -0
- data/package/configExporter/types.ts +36 -0
- data/package/configExporter/yamlSerializer.ts +266 -0
- data/package/{dev_server.js → dev_server.ts} +8 -5
- data/package/env.ts +92 -0
- data/package/environments/__type-tests__/rspack-plugin-compatibility.ts +30 -0
- data/package/environments/{base.js → base.ts} +56 -60
- data/package/environments/development.ts +90 -0
- data/package/environments/production.ts +80 -0
- data/package/environments/test.ts +53 -0
- data/package/environments/types.ts +98 -0
- data/package/esbuild/index.ts +42 -0
- data/package/index.d.ts +3 -60
- data/package/index.ts +55 -0
- data/package/loaders.d.ts +28 -0
- data/package/optimization/rspack.ts +36 -0
- data/package/optimization/webpack.ts +57 -0
- data/package/plugins/rspack.ts +103 -0
- data/package/plugins/webpack.ts +62 -0
- data/package/rspack/index.ts +64 -0
- data/package/rules/{babel.js → babel.ts} +2 -2
- data/package/rules/{coffee.js → coffee.ts} +1 -1
- data/package/rules/css.ts +3 -0
- data/package/rules/{erb.js → erb.ts} +1 -1
- data/package/rules/esbuild.ts +10 -0
- data/package/rules/file.ts +40 -0
- data/package/rules/{jscommon.js → jscommon.ts} +4 -4
- data/package/rules/{less.js → less.ts} +4 -4
- data/package/rules/raw.ts +25 -0
- data/package/rules/rspack.ts +176 -0
- data/package/rules/{sass.js → sass.ts} +7 -3
- data/package/rules/{stylus.js → stylus.ts} +4 -8
- data/package/rules/swc.ts +10 -0
- data/package/rules/webpack.ts +16 -0
- data/package/swc/index.ts +56 -0
- data/package/types/README.md +88 -0
- data/package/types/index.ts +61 -0
- data/package/types.ts +108 -0
- data/package/utils/configPath.ts +6 -0
- data/package/utils/debug.ts +49 -0
- data/package/utils/defaultConfigPath.ts +4 -0
- data/package/utils/errorCodes.ts +219 -0
- data/package/utils/errorHelpers.ts +143 -0
- data/package/utils/getStyleRule.ts +64 -0
- data/package/utils/helpers.ts +85 -0
- data/package/utils/{inliningCss.js → inliningCss.ts} +3 -3
- data/package/utils/pathValidation.ts +139 -0
- data/package/utils/requireOrError.ts +15 -0
- data/package/utils/snakeToCamelCase.ts +5 -0
- data/package/utils/typeGuards.ts +342 -0
- data/package/utils/validateDependencies.ts +61 -0
- data/package/webpack-types.d.ts +33 -0
- data/package/webpackDevServerConfig.ts +117 -0
- data/package-lock.json +13047 -0
- data/package.json +154 -18
- data/scripts/remove-use-strict.js +45 -0
- data/scripts/type-check-no-emit.js +27 -0
- data/test/helpers.js +1 -1
- data/test/package/config.test.js +43 -0
- data/test/package/env.test.js +42 -7
- data/test/package/environments/base.test.js +5 -1
- data/test/package/rules/babel.test.js +16 -0
- data/test/package/rules/esbuild.test.js +1 -1
- data/test/package/rules/raw.test.js +40 -7
- data/test/package/rules/swc.test.js +1 -1
- data/test/package/rules/webpack.test.js +35 -0
- data/test/package/staging.test.js +4 -3
- 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 +118 -0
- data/test/typescript/environments.test.js +107 -0
- data/test/typescript/pathValidation.test.js +142 -0
- data/test/typescript/securityValidation.test.js +182 -0
- data/tools/README.md +124 -0
- data/tools/css-modules-v9-codemod.js +179 -0
- data/tsconfig.eslint.json +16 -0
- data/tsconfig.json +38 -0
- data/yarn.lock +4165 -2706
- metadata +129 -41
- data/package/babel/preset.js +0 -37
- data/package/config.js +0 -54
- data/package/env.js +0 -48
- data/package/environments/development.js +0 -13
- data/package/environments/production.js +0 -88
- data/package/environments/test.js +0 -3
- data/package/esbuild/index.js +0 -40
- data/package/index.js +0 -40
- data/package/rules/css.js +0 -3
- data/package/rules/esbuild.js +0 -10
- data/package/rules/file.js +0 -29
- data/package/rules/index.js +0 -20
- data/package/rules/raw.js +0 -5
- data/package/rules/swc.js +0 -10
- data/package/swc/index.js +0 -50
- data/package/utils/configPath.js +0 -4
- data/package/utils/defaultConfigPath.js +0 -2
- data/package/utils/getStyleRule.js +0 -40
- data/package/utils/helpers.js +0 -58
- data/package/utils/snakeToCamelCase.js +0 -5
- data/package/webpackDevServerConfig.js +0 -71
- data/test/package/rules/index.test.js +0 -16
|
@@ -0,0 +1,379 @@
|
|
|
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
|
+
- `RspackPluginInstance` - Rspack plugin instance type
|
|
258
|
+
- `RspackPlugin` - **⚠️ Deprecated:** Use `RspackPluginInstance` instead
|
|
259
|
+
|
|
260
|
+
### Helper Types
|
|
261
|
+
- `CompressionPluginOptions` - Compression plugin configuration
|
|
262
|
+
- `ReactRefreshWebpackPlugin` - React refresh for Webpack
|
|
263
|
+
- `ReactRefreshRspackPlugin` - React refresh for Rspack
|
|
264
|
+
|
|
265
|
+
## Troubleshooting
|
|
266
|
+
|
|
267
|
+
### Issue: "Cannot find module 'shakapacker/types'"
|
|
268
|
+
|
|
269
|
+
**Solution**: Make sure you're using Shakapacker v9.0.0 or later:
|
|
270
|
+
|
|
271
|
+
```bash
|
|
272
|
+
yarn upgrade shakapacker
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
### Issue: Type errors with plugins
|
|
276
|
+
|
|
277
|
+
**Solution**: Cast plugin arrays when needed:
|
|
278
|
+
|
|
279
|
+
```typescript
|
|
280
|
+
const plugins = (config.plugins || []) as WebpackPluginInstance[]
|
|
281
|
+
plugins.push(new MyPlugin())
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
### Issue: Missing types for custom loaders
|
|
285
|
+
|
|
286
|
+
**Solution**: Install type definitions or declare them:
|
|
287
|
+
|
|
288
|
+
```typescript
|
|
289
|
+
// If types aren't available, declare them
|
|
290
|
+
declare module 'my-custom-loader' {
|
|
291
|
+
const loader: any
|
|
292
|
+
export default loader
|
|
293
|
+
}
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
### Issue: Conflicting types between webpack versions
|
|
297
|
+
|
|
298
|
+
**Solution**: Ensure your webpack types match your webpack version:
|
|
299
|
+
|
|
300
|
+
```bash
|
|
301
|
+
yarn add --dev @types/webpack@^5
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
## Gradual Migration
|
|
305
|
+
|
|
306
|
+
You don't need to convert everything at once. Start with:
|
|
307
|
+
|
|
308
|
+
1. Convert your main webpack.config.js to TypeScript
|
|
309
|
+
2. Add types to the most complex configurations
|
|
310
|
+
3. Gradually type other configuration files
|
|
311
|
+
4. Add type checking to your CI pipeline
|
|
312
|
+
|
|
313
|
+
## Example: Full Configuration
|
|
314
|
+
|
|
315
|
+
Here's a complete example of a typed webpack configuration:
|
|
316
|
+
|
|
317
|
+
```typescript
|
|
318
|
+
// config/webpack/webpack.config.ts
|
|
319
|
+
import { generateWebpackConfig, merge, config as shakapackerConfig } from 'shakapacker'
|
|
320
|
+
import type { Configuration } from 'webpack'
|
|
321
|
+
import type { WebpackConfigWithDevServer } from 'shakapacker/types'
|
|
322
|
+
import CompressionPlugin from 'compression-webpack-plugin'
|
|
323
|
+
import { resolve } from 'path'
|
|
324
|
+
|
|
325
|
+
// Type-safe custom configuration
|
|
326
|
+
const customConfig: Configuration = {
|
|
327
|
+
resolve: {
|
|
328
|
+
extensions: ['.css', '.ts', '.tsx'],
|
|
329
|
+
alias: {
|
|
330
|
+
'@': resolve(__dirname, '../../app/javascript'),
|
|
331
|
+
'components': resolve(__dirname, '../../app/javascript/components'),
|
|
332
|
+
'utils': resolve(__dirname, '../../app/javascript/utils')
|
|
333
|
+
}
|
|
334
|
+
},
|
|
335
|
+
module: {
|
|
336
|
+
rules: [
|
|
337
|
+
{
|
|
338
|
+
test: /\.svg$/,
|
|
339
|
+
use: ['@svgr/webpack'],
|
|
340
|
+
issuer: /\.(tsx?|jsx?)$/
|
|
341
|
+
}
|
|
342
|
+
]
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
// Generate the final configuration
|
|
347
|
+
const webpackConfig: Configuration = generateWebpackConfig(customConfig)
|
|
348
|
+
|
|
349
|
+
// Type-safe modifications based on environment
|
|
350
|
+
if (shakapackerConfig.env === 'production') {
|
|
351
|
+
const plugins = (webpackConfig.plugins || []) as WebpackPluginInstance[]
|
|
352
|
+
|
|
353
|
+
plugins.push(
|
|
354
|
+
new CompressionPlugin({
|
|
355
|
+
filename: '[path][base].br',
|
|
356
|
+
algorithm: 'brotliCompress',
|
|
357
|
+
test: /\.(js|css|html|json|ico|svg|eot|otf|ttf)$/
|
|
358
|
+
})
|
|
359
|
+
)
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
export default webpackConfig
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
## Next Steps
|
|
366
|
+
|
|
367
|
+
After migrating to TypeScript:
|
|
368
|
+
|
|
369
|
+
1. **Enable strict checks**: Gradually enable stricter TypeScript options
|
|
370
|
+
2. **Add custom types**: Create type definitions for your application-specific configurations
|
|
371
|
+
3. **Share types**: Export reusable configuration types for your team
|
|
372
|
+
4. **Document with types**: Use JSDoc comments with your types for better documentation
|
|
373
|
+
|
|
374
|
+
## Resources
|
|
375
|
+
|
|
376
|
+
- [TypeScript Handbook](https://www.typescriptlang.org/docs/handbook/intro.html)
|
|
377
|
+
- [Webpack TypeScript Configuration](https://webpack.js.org/configuration/configuration-languages/#typescript)
|
|
378
|
+
- [Shakapacker Types Documentation](./types/README.md)
|
|
379
|
+
- [Migration Examples](https://github.com/shakacode/shakapacker/tree/main/examples/typescript-config)
|
data/docs/typescript.md
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# TypeScript Support
|
|
2
|
+
|
|
3
|
+
Shakapacker v9 includes TypeScript support, providing type safety and better IDE experience for your webpack configurations.
|
|
4
|
+
|
|
5
|
+
## Quick Start
|
|
6
|
+
|
|
7
|
+
### Using TypeScript Config
|
|
8
|
+
|
|
9
|
+
```typescript
|
|
10
|
+
// webpack.config.ts
|
|
11
|
+
import { generateWebpackConfig } from 'shakapacker'
|
|
12
|
+
import type { Configuration } from 'webpack'
|
|
13
|
+
|
|
14
|
+
const config: Configuration = generateWebpackConfig({
|
|
15
|
+
// Your config with full type safety
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
export default config
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
### Using JSDoc (JavaScript)
|
|
22
|
+
|
|
23
|
+
```javascript
|
|
24
|
+
// webpack.config.js
|
|
25
|
+
const { generateWebpackConfig } = require('shakapacker')
|
|
26
|
+
|
|
27
|
+
/** @type {import('webpack').Configuration} */
|
|
28
|
+
const config = {
|
|
29
|
+
// Still get autocomplete in JS files!
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
module.exports = generateWebpackConfig(config)
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Benefits
|
|
36
|
+
|
|
37
|
+
- **Compile-time error detection** - Catch config errors before runtime
|
|
38
|
+
- **IDE autocomplete** - Full IntelliSense for all options
|
|
39
|
+
- **Type safety** - Prevents 85-100% of common configuration errors
|
|
40
|
+
- **No breaking changes** - Fully backward compatible
|
|
41
|
+
|
|
42
|
+
## Migration
|
|
43
|
+
|
|
44
|
+
1. **No migration required** - Existing JavaScript configs continue to work
|
|
45
|
+
2. **Optional TypeScript** - Use it only if you want the benefits
|
|
46
|
+
3. **Gradual adoption** - Start with JSDoc comments, move to TypeScript later
|
|
47
|
+
|
|
48
|
+
## IDE Setup
|
|
49
|
+
|
|
50
|
+
### VS Code
|
|
51
|
+
- Install TypeScript extension (built-in)
|
|
52
|
+
- Set `"typescript.tsdk": "node_modules/typescript/lib"` in settings
|
|
53
|
+
|
|
54
|
+
### WebStorm/IntelliJ
|
|
55
|
+
- Enable TypeScript service in Settings → Languages & Frameworks → TypeScript
|
|
56
|
+
|
|
57
|
+
## Common Patterns
|
|
58
|
+
|
|
59
|
+
### Environment-Specific Config
|
|
60
|
+
|
|
61
|
+
```typescript
|
|
62
|
+
import { generateWebpackConfig, env } from 'shakapacker'
|
|
63
|
+
|
|
64
|
+
const config = generateWebpackConfig({
|
|
65
|
+
optimization: {
|
|
66
|
+
minimize: env.isProduction
|
|
67
|
+
}
|
|
68
|
+
})
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Rspack Config
|
|
72
|
+
|
|
73
|
+
```typescript
|
|
74
|
+
import { generateRspackConfig } from 'shakapacker/rspack'
|
|
75
|
+
import type { RspackOptions } from '@rspack/core'
|
|
76
|
+
|
|
77
|
+
const config: RspackOptions = {
|
|
78
|
+
// Rspack-specific config
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export default generateRspackConfig(config)
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Troubleshooting
|
|
85
|
+
|
|
86
|
+
**Cannot find module 'shakapacker'**
|
|
87
|
+
```typescript
|
|
88
|
+
/// <reference types="shakapacker" />
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
**Type errors with custom loaders**
|
|
92
|
+
```typescript
|
|
93
|
+
use: [require.resolve('custom-loader') as any]
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Further Reading
|
|
97
|
+
|
|
98
|
+
- [Webpack TypeScript Documentation](https://webpack.js.org/configuration/configuration-languages/#typescript)
|
|
99
|
+
- [TypeScript Handbook](https://www.typescriptlang.org/docs/)
|
|
@@ -27,7 +27,7 @@ To use esbuild as your transpiler today. You need to do two things:
|
|
|
27
27
|
npm install esbuild esbuild-loader
|
|
28
28
|
```
|
|
29
29
|
|
|
30
|
-
2. Add or change `
|
|
30
|
+
2. Add or change `javascript_transpiler` value in your default `shakapacker.yml` config to `esbuild`
|
|
31
31
|
The default configuration of babel is done by using `package.json` to use the file within the `shakapacker` package.
|
|
32
32
|
|
|
33
33
|
```yml
|
|
@@ -46,8 +46,8 @@ default: &default
|
|
|
46
46
|
# Reload manifest.json on all requests so we reload latest compiled packs
|
|
47
47
|
cache_manifest: false
|
|
48
48
|
|
|
49
|
-
# Select
|
|
50
|
-
|
|
49
|
+
# Select JavaScript transpiler to use, available options are 'babel' (default), 'swc' or 'esbuild'
|
|
50
|
+
javascript_transpiler: 'esbuild'
|
|
51
51
|
```
|
|
52
52
|
|
|
53
53
|
### (Optional) Replace minification with esbuild
|
data/docs/using_swc_loader.md
CHANGED
|
@@ -12,6 +12,8 @@ It supports all ECMAScript features and it's designed to be a drop-in replacemen
|
|
|
12
12
|
|
|
13
13
|
For comparison between SWC and Babel, see the docs at https://swc.rs/docs/migrating-from-babel.
|
|
14
14
|
|
|
15
|
+
> **Note:** SWC is also natively built into RSpack bundler, providing even faster compilation speeds. When using RSpack (`assets_bundler: 'rspack'`), SWC is used automatically regardless of the `javascript_transpiler` setting.
|
|
16
|
+
|
|
15
17
|
## Switching your Shakapacker project to SWC
|
|
16
18
|
|
|
17
19
|
In order to use SWC as your compiler today. You need to do two things:
|
|
@@ -22,8 +24,8 @@ In order to use SWC as your compiler today. You need to do two things:
|
|
|
22
24
|
npm install @swc/core swc-loader
|
|
23
25
|
```
|
|
24
26
|
|
|
25
|
-
2. Add or change `
|
|
26
|
-
The default configuration of babel is done by using `package.json` to use the file within the `shakapacker` package.
|
|
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.
|
|
27
29
|
|
|
28
30
|
```yml
|
|
29
31
|
default: &default
|
|
@@ -41,8 +43,8 @@ default: &default
|
|
|
41
43
|
# Reload manifest.json on all requests so we reload latest compiled packs
|
|
42
44
|
cache_manifest: false
|
|
43
45
|
|
|
44
|
-
# Select
|
|
45
|
-
|
|
46
|
+
# Select JavaScript transpiler to use, available options are 'babel' (default) or 'swc'
|
|
47
|
+
javascript_transpiler: "swc"
|
|
46
48
|
```
|
|
47
49
|
|
|
48
50
|
## Usage
|
|
@@ -71,7 +73,6 @@ See some examples below of potential `config/swc.config.js`.
|
|
|
71
73
|
|
|
72
74
|
### Example: Enabling top level await and decorators
|
|
73
75
|
|
|
74
|
-
|
|
75
76
|
```js
|
|
76
77
|
const customConfig = {
|
|
77
78
|
options: {
|
|
@@ -90,7 +91,7 @@ module.exports = customConfig
|
|
|
90
91
|
### Example: Matching existing `@babel/present-env` config
|
|
91
92
|
|
|
92
93
|
```js
|
|
93
|
-
const { env } = require(
|
|
94
|
+
const { env } = require("shakapacker")
|
|
94
95
|
|
|
95
96
|
const customConfig = {
|
|
96
97
|
options: {
|
|
@@ -112,9 +113,8 @@ module.exports = customConfig
|
|
|
112
113
|
|
|
113
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.
|
|
114
115
|
|
|
115
|
-
|
|
116
116
|
```js
|
|
117
|
-
const { env } = require(
|
|
117
|
+
const { env } = require("shakapacker")
|
|
118
118
|
|
|
119
119
|
const customConfig = {
|
|
120
120
|
options: {
|
|
@@ -134,11 +134,10 @@ module.exports = customConfig
|
|
|
134
134
|
### Example: Adding browserslist config
|
|
135
135
|
|
|
136
136
|
```js
|
|
137
|
-
|
|
138
137
|
const customConfig = {
|
|
139
138
|
options: {
|
|
140
139
|
env: {
|
|
141
|
-
targets:
|
|
140
|
+
targets: "> 0.25%, not dead"
|
|
142
141
|
}
|
|
143
142
|
}
|
|
144
143
|
}
|
|
@@ -146,6 +145,109 @@ const customConfig = {
|
|
|
146
145
|
module.exports = customConfig
|
|
147
146
|
```
|
|
148
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`
|
|
149
251
|
|
|
150
252
|
## Known limitations
|
|
151
253
|
|
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.
|