shakapacker 9.2.0 → 9.3.0.beta.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.
Files changed (115) hide show
  1. checksums.yaml +4 -4
  2. data/.github/ISSUE_TEMPLATE/bug_report.md +6 -9
  3. data/.github/ISSUE_TEMPLATE/feature_request.md +6 -8
  4. data/.github/workflows/claude-code-review.yml +4 -5
  5. data/.github/workflows/claude.yml +1 -2
  6. data/.github/workflows/dummy.yml +4 -4
  7. data/.github/workflows/generator.yml +9 -9
  8. data/.github/workflows/node.yml +11 -2
  9. data/.github/workflows/ruby.yml +16 -16
  10. data/.github/workflows/test-bundlers.yml +9 -9
  11. data/.gitignore +4 -0
  12. data/CHANGELOG.md +19 -4
  13. data/CLAUDE.md +6 -1
  14. data/CONTRIBUTING.md +0 -1
  15. data/Gemfile.lock +1 -1
  16. data/README.md +14 -14
  17. data/TODO.md +10 -2
  18. data/TODO_v9.md +13 -3
  19. data/bin/export-bundler-config +1 -1
  20. data/conductor-setup.sh +1 -1
  21. data/conductor.json +1 -1
  22. data/docs/cdn_setup.md +13 -8
  23. data/docs/common-upgrades.md +2 -1
  24. data/docs/configuration.md +630 -0
  25. data/docs/css-modules-export-mode.md +120 -100
  26. data/docs/customizing_babel_config.md +16 -16
  27. data/docs/deployment.md +18 -0
  28. data/docs/developing_shakapacker.md +6 -0
  29. data/docs/optional-peer-dependencies.md +9 -4
  30. data/docs/peer-dependencies.md +17 -6
  31. data/docs/precompile_hook.md +342 -0
  32. data/docs/react.md +57 -47
  33. data/docs/releasing.md +0 -2
  34. data/docs/rspack.md +25 -21
  35. data/docs/rspack_migration_guide.md +335 -8
  36. data/docs/sprockets.md +1 -0
  37. data/docs/style_loader_vs_mini_css.md +12 -12
  38. data/docs/subresource_integrity.md +13 -7
  39. data/docs/transpiler-performance.md +40 -19
  40. data/docs/troubleshooting.md +0 -2
  41. data/docs/typescript-migration.md +48 -39
  42. data/docs/typescript.md +12 -8
  43. data/docs/using_esbuild_loader.md +10 -10
  44. data/docs/v6_upgrade.md +33 -20
  45. data/docs/v7_upgrade.md +8 -6
  46. data/docs/v8_upgrade.md +13 -12
  47. data/docs/v9_upgrade.md +2 -1
  48. data/eslint.config.fast.js +134 -0
  49. data/eslint.config.js +140 -0
  50. data/knip.ts +54 -0
  51. data/lib/install/bin/export-bundler-config +1 -1
  52. data/lib/install/config/shakapacker.yml +16 -5
  53. data/lib/shakapacker/compiler.rb +80 -0
  54. data/lib/shakapacker/configuration.rb +33 -5
  55. data/lib/shakapacker/dev_server_runner.rb +140 -1
  56. data/lib/shakapacker/doctor.rb +294 -65
  57. data/lib/shakapacker/instance.rb +8 -3
  58. data/lib/shakapacker/runner.rb +244 -8
  59. data/lib/shakapacker/version.rb +1 -1
  60. data/lib/tasks/shakapacker/doctor.rake +42 -2
  61. data/package/babel/preset.ts +7 -4
  62. data/package/config.ts +42 -30
  63. data/package/configExporter/cli.ts +799 -208
  64. data/package/configExporter/configFile.ts +520 -0
  65. data/package/configExporter/fileWriter.ts +12 -8
  66. data/package/configExporter/index.ts +9 -1
  67. data/package/configExporter/types.ts +36 -2
  68. data/package/configExporter/yamlSerializer.ts +22 -8
  69. data/package/dev_server.ts +1 -1
  70. data/package/environments/__type-tests__/rspack-plugin-compatibility.ts +11 -5
  71. data/package/environments/base.ts +18 -13
  72. data/package/environments/development.ts +1 -1
  73. data/package/environments/production.ts +4 -1
  74. data/package/index.d.ts +50 -3
  75. data/package/index.d.ts.template +50 -0
  76. data/package/index.ts +7 -7
  77. data/package/loaders.d.ts +2 -2
  78. data/package/optimization/rspack.ts +1 -1
  79. data/package/plugins/rspack.ts +15 -4
  80. data/package/plugins/webpack.ts +7 -3
  81. data/package/rspack/index.ts +10 -2
  82. data/package/rules/raw.ts +3 -2
  83. data/package/rules/sass.ts +1 -1
  84. data/package/types/README.md +15 -13
  85. data/package/types/index.ts +5 -5
  86. data/package/types.ts +0 -1
  87. data/package/utils/defaultConfigPath.ts +4 -1
  88. data/package/utils/errorCodes.ts +129 -100
  89. data/package/utils/errorHelpers.ts +34 -29
  90. data/package/utils/getStyleRule.ts +5 -2
  91. data/package/utils/helpers.ts +21 -11
  92. data/package/utils/pathValidation.ts +43 -35
  93. data/package/utils/requireOrError.ts +1 -1
  94. data/package/utils/snakeToCamelCase.ts +1 -1
  95. data/package/utils/typeGuards.ts +132 -83
  96. data/package/utils/validateDependencies.ts +1 -1
  97. data/package/webpack-types.d.ts +3 -3
  98. data/package/webpackDevServerConfig.ts +22 -10
  99. data/package-lock.json +2 -2
  100. data/package.json +36 -28
  101. data/scripts/type-check-no-emit.js +1 -1
  102. data/test/configExporter/configFile.test.js +392 -0
  103. data/test/configExporter/integration.test.js +275 -0
  104. data/test/helpers.js +1 -1
  105. data/test/package/configExporter.test.js +154 -0
  106. data/test/package/helpers.test.js +2 -2
  107. data/test/package/rules/sass-version-parsing.test.js +71 -0
  108. data/test/package/rules/sass.test.js +2 -4
  109. data/test/package/rules/sass1.test.js +1 -3
  110. data/test/package/rules/sass16.test.js +23 -0
  111. data/tools/README.md +15 -5
  112. data/tsconfig.eslint.json +2 -9
  113. data/yarn.lock +1894 -1492
  114. metadata +19 -3
  115. data/.eslintignore +0 -5
@@ -1,4 +1,5 @@
1
1
  # Shakapacker's Peer Dependencies
2
+
2
3
  ## Last updated for our 9.0.0 version — see lib/install/package.json
3
4
 
4
5
  To simplify peer dependencies while supporting both webpack & rspack, we decided to document the dependencies here instead of creating two separate npm packages.
@@ -6,13 +7,16 @@ To simplify peer dependencies while supporting both webpack & rspack, we decided
6
7
  **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
8
 
8
9
  ## Essential for Rspack
9
- ```
10
+
11
+ ```text
10
12
  "@rspack/cli": "^1.0.0",
11
13
  "@rspack/core": "^1.0.0",
12
14
  "rspack-manifest-plugin": "^5.0.0",
13
15
  ```
16
+
14
17
  ## Essential for Webpack
15
- ```
18
+
19
+ ```text
16
20
  "mini-css-extract-plugin": "^2.0.0",
17
21
  "terser-webpack-plugin": "^5.3.1",
18
22
  "webpack": "^5.76.0",
@@ -24,7 +28,8 @@ To simplify peer dependencies while supporting both webpack & rspack, we decided
24
28
  ```
25
29
 
26
30
  ## Highly recommended
27
- ```
31
+
32
+ ```text
28
33
  "compression-webpack-plugin": "^9.0.0 || ^10.0.0|| ^11.0.0",
29
34
  "css-loader": "^6.0.0 || ^7.0.0",
30
35
  "sass-loader": "^13.0.0 || ^14.0.0 || ^15.0.0 || ^16.0.0",
@@ -34,27 +39,33 @@ To simplify peer dependencies while supporting both webpack & rspack, we decided
34
39
  ## Optional JavaScript Transpilers
35
40
 
36
41
  ### Babel (installed automatically when `javascript_transpiler: 'babel'`)
37
- ```
42
+
43
+ ```text
38
44
  "@babel/core": "^7.17.9",
39
45
  "@babel/plugin-transform-runtime": "^7.17.0",
40
46
  "@babel/preset-env": "^7.16.11",
41
47
  "@babel/runtime": "^7.17.9",
42
48
  "babel-loader": "^8.2.4 || ^9.0.0 || ^10.0.0",
43
49
  ```
50
+
44
51
  Note: These dependencies are only installed if you're using Babel as your JavaScript transpiler. Consider using SWC or esbuild for better performance.
45
52
 
46
53
  ### SWC (default - 20x faster than Babel)
47
- ```
54
+
55
+ ```text
48
56
  "@swc/core": "latest",
49
57
  "swc-loader": "latest"
50
58
  ```
59
+
51
60
  - **For webpack**: Installed automatically when using default configuration
52
61
  - **For rspack**: Built-in, no additional installation needed (rspack includes SWC natively)
53
62
  - Manual install: `npm install @swc/core swc-loader`
54
63
 
55
64
  ### esbuild
56
- ```
65
+
66
+ ```text
57
67
  "esbuild": "latest",
58
68
  "esbuild-loader": "latest"
59
69
  ```
70
+
60
71
  Install manually with: `npm install esbuild esbuild-loader`
@@ -0,0 +1,342 @@
1
+ # Precompile Hook
2
+
3
+ The `precompile_hook` configuration option allows you to run a custom command before asset compilation.
4
+
5
+ **📖 For other configuration options, see the [Configuration Guide](./configuration.md)**
6
+
7
+ This is useful for:
8
+
9
+ - Dynamically generating entry points (e.g., from database records)
10
+ - Running preparatory tasks before bundling
11
+ - Integrating with tools like React on Rails that need to generate packs
12
+
13
+ ## When to Use
14
+
15
+ The precompile hook is especially useful when you need to run commands like:
16
+
17
+ - `bin/rails react_on_rails:generate_packs` - Generate dynamic entry points
18
+ - `bin/rails react_on_rails:locale` - Generate locale files
19
+ - Any custom script that prepares files before asset compilation
20
+
21
+ **Important:** The hook runs in **both development and production**:
22
+
23
+ - **Development**: Runs before `bin/shakapacker --watch` or dev server starts
24
+ - **Production**: Runs before `rails assets:precompile`
25
+
26
+ ## Configuration
27
+
28
+ Add the `precompile_hook` option to your `config/shakapacker.yml`:
29
+
30
+ ```yaml
31
+ # For all environments
32
+ default: &default
33
+ precompile_hook: "bin/shakapacker-precompile-hook"
34
+
35
+ # Or environment-specific
36
+ development:
37
+ <<: *default
38
+ precompile_hook: "bin/dev-setup"
39
+
40
+ production:
41
+ <<: *default
42
+ precompile_hook: "bin/rails react_on_rails:generate_packs"
43
+ ```
44
+
45
+ ## Creating a Precompile Hook Script
46
+
47
+ ### Simple Shell Script
48
+
49
+ ```bash
50
+ #!/usr/bin/env bash
51
+ # bin/shakapacker-precompile-hook
52
+
53
+ echo "Preparing assets..."
54
+ bin/rails react_on_rails:generate_packs
55
+ bin/rails react_on_rails:locale
56
+ echo "Assets prepared successfully"
57
+ ```
58
+
59
+ ### Ruby Script with Database Access
60
+
61
+ ```ruby
62
+ #!/usr/bin/env ruby
63
+ # bin/shakapacker-precompile-hook
64
+
65
+ require_relative "../config/environment"
66
+
67
+ puts "Generating dynamic entry points..."
68
+
69
+ # Generate entry points from database
70
+ Theme.find_each do |theme|
71
+ entry_point = Rails.root.join("app/javascript/packs/theme_#{theme.id}.js")
72
+ File.write(entry_point, "import '../themes/#{theme.identifier}';")
73
+ puts " Created #{entry_point}"
74
+ end
75
+
76
+ puts "Entry points generated successfully"
77
+ exit 0
78
+ ```
79
+
80
+ Make the script executable:
81
+
82
+ ```bash
83
+ chmod +x bin/shakapacker-precompile-hook
84
+ ```
85
+
86
+ ## How It Works
87
+
88
+ ### Execution Flow
89
+
90
+ 1. **Triggered** when asset compilation starts
91
+ 2. **Hook runs** in your project root directory
92
+ 3. **Environment variables** are passed through (including `NODE_ENV`, `RAILS_ENV`, `SHAKAPACKER_ASSET_HOST`)
93
+ 4. **On success** (exit code 0): Compilation proceeds
94
+ 5. **On failure** (non-zero exit code): Compilation stops with error
95
+
96
+ **Migration Note:** If you're migrating from custom `assets:precompile` enhancements (e.g., in `lib/tasks/assets.rake`), ensure you don't run the same commands twice. React on Rails versions before 16.1.1 automatically prepend `react_on_rails:generate_packs` to `assets:precompile`. Versions 16.1.1+ detect `precompile_hook` and skip automatic task enhancement to avoid duplicate execution. For custom Rake task enhancements, remove manual invocations when adding `precompile_hook`.
97
+
98
+ To verify correct migration, run `rake assets:precompile` and check the logs. Commands like `react_on_rails:generate_packs` should appear **only once** in the output. If you see duplicate execution, either upgrade React on Rails to 16.1.1+ or remove your custom task enhancements.
99
+
100
+ ### Logging
101
+
102
+ The hook's stdout and stderr are logged:
103
+
104
+ ```
105
+ Running precompile hook: bin/shakapacker-precompile-hook
106
+ Preparing assets...
107
+ Entry points generated successfully
108
+ Precompile hook completed successfully
109
+ Compiling...
110
+ ```
111
+
112
+ ## React on Rails Integration
113
+
114
+ For React on Rails projects, the hook replaces manual steps in your workflow:
115
+
116
+ ### Before (Manual)
117
+
118
+ ```bash
119
+ # Development
120
+ bin/rails react_on_rails:generate_packs
121
+ bin/rails react_on_rails:locale
122
+ bin/shakapacker-dev-server
123
+
124
+ # Production
125
+ bin/rails react_on_rails:generate_packs
126
+ bin/rails react_on_rails:locale
127
+ RAILS_ENV=production bin/rails assets:precompile
128
+ ```
129
+
130
+ ### After (Automatic)
131
+
132
+ ```yaml
133
+ # config/shakapacker.yml
134
+ default: &default
135
+ precompile_hook: "bin/react-on-rails-hook"
136
+ ```
137
+
138
+ ```bash
139
+ #!/usr/bin/env bash
140
+ # bin/react-on-rails-hook
141
+ bin/rails react_on_rails:generate_packs
142
+ bin/rails react_on_rails:locale
143
+ ```
144
+
145
+ Now simply run:
146
+
147
+ ```bash
148
+ # Development
149
+ bin/shakapacker-dev-server
150
+
151
+ # Production
152
+ RAILS_ENV=production bin/rails assets:precompile
153
+ ```
154
+
155
+ ## Security
156
+
157
+ For security reasons, the precompile hook is validated to ensure:
158
+
159
+ ### 1. Project Root Restriction
160
+
161
+ The hook **must** reference a script within your project root:
162
+
163
+ ```yaml
164
+ # ✅ Valid - within project
165
+ precompile_hook: 'bin/shakapacker-precompile-hook'
166
+ precompile_hook: 'script/prepare-assets'
167
+ precompile_hook: 'bin/hook --arg1 --arg2'
168
+
169
+ # ❌ Invalid - outside project
170
+ precompile_hook: '/usr/bin/malicious-script'
171
+ precompile_hook: '../../../etc/passwd'
172
+ ```
173
+
174
+ ### 2. Symlink Resolution
175
+
176
+ Symlinks are resolved to their real paths before validation:
177
+
178
+ ```bash
179
+ # If bin/hook is a symlink to /usr/bin/evil
180
+ # The validation will detect and reject it
181
+ ```
182
+
183
+ ### 3. Path Traversal Protection
184
+
185
+ Path traversal attempts are blocked:
186
+
187
+ ```yaml
188
+ # ❌ These will be rejected
189
+ precompile_hook: 'bin/../../etc/passwd'
190
+ precompile_hook: '../outside-project/script'
191
+ ```
192
+
193
+ ### 4. Proper Path Boundary Checking
194
+
195
+ Partial path matches are prevented:
196
+
197
+ ```
198
+ # /project won't match /project-evil
199
+ # Uses File::SEPARATOR for proper validation
200
+ ```
201
+
202
+ ## Error Handling
203
+
204
+ ### Hook Failure
205
+
206
+ If the hook fails, you'll see a detailed error:
207
+
208
+ ```
209
+ PRECOMPILE HOOK FAILED:
210
+ EXIT STATUS: 1
211
+ COMMAND: bin/shakapacker-precompile-hook
212
+ OUTPUTS:
213
+ Error: Theme not found
214
+
215
+ To fix this:
216
+ 1. Check that the hook script exists and is executable
217
+ 2. Test the hook command manually: bin/shakapacker-precompile-hook
218
+ 3. Review the error output above for details
219
+ 4. You can disable the hook temporarily by commenting out 'precompile_hook' in shakapacker.yml
220
+ ```
221
+
222
+ ### Missing Executable
223
+
224
+ If the script doesn't exist, you'll see a warning:
225
+
226
+ ```
227
+ ⚠️ Warning: precompile_hook executable not found: /path/to/project/bin/hook
228
+ The hook command is configured but the script does not exist within the project root.
229
+ Please ensure the script exists or remove 'precompile_hook' from your shakapacker.yml configuration.
230
+ ```
231
+
232
+ ## Troubleshooting
233
+
234
+ ### Test the Hook Manually
235
+
236
+ Run the hook directly to see what happens:
237
+
238
+ ```bash
239
+ bin/shakapacker-precompile-hook
240
+ echo $? # Should output 0 for success
241
+ ```
242
+
243
+ ### Check Permissions
244
+
245
+ Ensure the script is executable:
246
+
247
+ ```bash
248
+ ls -la bin/shakapacker-precompile-hook
249
+ # Should show: -rwxr-xr-x (executable)
250
+
251
+ # If not executable:
252
+ chmod +x bin/shakapacker-precompile-hook
253
+ ```
254
+
255
+ ### Debug with Verbose Output
256
+
257
+ Add debug output to your hook:
258
+
259
+ ```bash
260
+ #!/usr/bin/env bash
261
+ set -x # Enable verbose mode
262
+ echo "Current directory: $(pwd)"
263
+ echo "Environment: $RAILS_ENV"
264
+ # Your commands here
265
+ ```
266
+
267
+ ### Temporarily Disable
268
+
269
+ To disable the hook for testing:
270
+
271
+ ```yaml
272
+ # config/shakapacker.yml
273
+ default:
274
+ # precompile_hook: 'bin/shakapacker-precompile-hook'
275
+ ```
276
+
277
+ ### Common Issues
278
+
279
+ **Issue:** Hook fails in production but works in development - Verify all dependencies are available (database, commands, gems)
280
+
281
+ **Issue:** Generated files not found - Check `source_path` and `source_entry_path` in `shakapacker.yml`
282
+
283
+ **Issue:** Permission denied - Run `chmod +x bin/shakapacker-precompile-hook`
284
+
285
+ ## Advanced Usage
286
+
287
+ ### Conditional Execution
288
+
289
+ ```bash
290
+ #!/usr/bin/env bash
291
+ # bin/shakapacker-precompile-hook
292
+
293
+ if [ "$RAILS_ENV" = "production" ]; then
294
+ echo "Running production-specific setup..."
295
+ bin/rails react_on_rails:generate_packs
296
+ else
297
+ echo "Running development setup..."
298
+ # Lighter-weight setup for development
299
+ fi
300
+ ```
301
+
302
+ ### Hook with Arguments
303
+
304
+ ```yaml
305
+ precompile_hook: "bin/prepare-assets --verbose --cache-bust"
306
+ ```
307
+
308
+ ```bash
309
+ #!/usr/bin/env bash
310
+ # bin/prepare-assets
311
+
312
+ VERBOSE=false
313
+ CACHE_BUST=false
314
+
315
+ while [[ $# -gt 0 ]]; do
316
+ case $1 in
317
+ --verbose) VERBOSE=true ;;
318
+ --cache-bust) CACHE_BUST=true ;;
319
+ esac
320
+ shift
321
+ done
322
+
323
+ if [ "$VERBOSE" = true ]; then
324
+ echo "Preparing assets..."
325
+ fi
326
+ ```
327
+
328
+ ### Handling Spaces in Paths
329
+
330
+ Use quotes for paths with spaces:
331
+
332
+ ```yaml
333
+ precompile_hook: "'bin/my hook script' --arg1"
334
+ ```
335
+
336
+ The hook system uses `Shellwords` to properly parse quoted arguments.
337
+
338
+ ## See Also
339
+
340
+ - [Deployment Guide](deployment.md) - Production deployment considerations
341
+ - [React on Rails Integration](https://github.com/shakacode/react_on_rails) - Main use case documentation
342
+ - [Configuration](../README.md#configuration-and-code) - General shakapacker configuration
data/docs/react.md CHANGED
@@ -53,19 +53,17 @@ npm install --dev react-refresh @pmmmwh/react-refresh-webpack-plugin
53
53
  Alter `config/webpack/webpack.config.js` like so:
54
54
 
55
55
  ```js
56
- const { generateWebpackConfig, inliningCss } = require('shakapacker');
57
- const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin');
58
- const isDevelopment = process.env.NODE_ENV !== 'production';
56
+ const { generateWebpackConfig, inliningCss } = require("shakapacker")
57
+ const ReactRefreshWebpackPlugin = require("@pmmmwh/react-refresh-webpack-plugin")
58
+ const isDevelopment = process.env.NODE_ENV !== "production"
59
59
 
60
- const webpackConfig = generateWebpackConfig();
60
+ const webpackConfig = generateWebpackConfig()
61
61
 
62
62
  if (isDevelopment && inliningCss) {
63
- webpackConfig.plugins.push(
64
- new ReactRefreshWebpackPlugin()
65
- );
63
+ webpackConfig.plugins.push(new ReactRefreshWebpackPlugin())
66
64
  }
67
65
 
68
- module.exports = webpackConfig;
66
+ module.exports = webpackConfig
69
67
  ```
70
68
 
71
69
  This applies the plugin to the webpack configuration.
@@ -85,16 +83,16 @@ Then create a `babel.config.js` file in the root of project and add the followin
85
83
 
86
84
  ```js
87
85
  module.exports = function (api) {
88
- const defaultConfigFunc = require('shakapacker/package/babel/preset.js')
86
+ const defaultConfigFunc = require("shakapacker/package/babel/preset.js")
89
87
  const resultConfig = defaultConfigFunc(api)
90
- const isDevelopmentEnv = api.env('development')
91
- const isProductionEnv = api.env('production')
92
- const isTestEnv = api.env('test')
88
+ const isDevelopmentEnv = api.env("development")
89
+ const isProductionEnv = api.env("production")
90
+ const isTestEnv = api.env("test")
93
91
 
94
92
  const changesOnDefault = {
95
93
  presets: [
96
94
  [
97
- '@babel/preset-react',
95
+ "@babel/preset-react",
98
96
  {
99
97
  development: isDevelopmentEnv || isTestEnv,
100
98
  useBuiltIns: true
@@ -102,17 +100,18 @@ module.exports = function (api) {
102
100
  ]
103
101
  ].filter(Boolean),
104
102
  plugins: [
105
- isProductionEnv && ['babel-plugin-transform-react-remove-prop-types',
103
+ isProductionEnv && [
104
+ "babel-plugin-transform-react-remove-prop-types",
106
105
  {
107
106
  removeImport: true
108
107
  }
109
108
  ],
110
- process.env.WEBPACK_SERVE && 'react-refresh/babel'
111
- ].filter(Boolean),
109
+ process.env.WEBPACK_SERVE && "react-refresh/babel"
110
+ ].filter(Boolean)
112
111
  }
113
112
 
114
113
  resultConfig.presets = [...resultConfig.presets, ...changesOnDefault.presets]
115
- resultConfig.plugins = [...resultConfig.plugins, ...changesOnDefault.plugins ]
114
+ resultConfig.plugins = [...resultConfig.plugins, ...changesOnDefault.plugins]
116
115
 
117
116
  return resultConfig
118
117
  }
@@ -127,6 +126,7 @@ HMR for your React app is now enabled. 🚀
127
126
  To test that all of the above is working, you can follow these instructions to create a basic React app using Shakapacker.
128
127
 
129
128
  1. Create a new Rails app:
129
+
130
130
  ```shell
131
131
  rails new myapp --skip-javascript
132
132
  cd myapp
@@ -138,44 +138,52 @@ npm install css-loader style-loader mini-css-extract-plugin css-minimizer-webpac
138
138
  ```
139
139
 
140
140
  2. Generate a controller
141
+
141
142
  ```shell
142
143
  rails g controller site index
143
144
  echo '<div id="root"></div>' > app/views/site/index.html.erb
144
145
  ```
145
146
 
146
147
  3. Create a CSS file and a React component:
148
+
147
149
  ```shell
148
150
  touch app/javascript/App.css app/javascript/App.js
149
151
  ```
150
152
 
151
153
  4. Edit `app/javascript/packs/application.js` like so:
154
+
152
155
  ```jsx
153
- import React from 'react';
154
- import { createRoot } from 'react-dom/client';
155
- import HelloMessage from '../App';
156
+ import React from "react"
157
+ import { createRoot } from "react-dom/client"
158
+ import HelloMessage from "../App"
156
159
 
157
- const container = document.getElementById('root');
158
- const root = createRoot(container);
160
+ const container = document.getElementById("root")
161
+ const root = createRoot(container)
159
162
 
160
- document.addEventListener('DOMContentLoaded', () => {
161
- root.render(<HelloMessage name="World" />);
162
- });
163
+ document.addEventListener("DOMContentLoaded", () => {
164
+ root.render(<HelloMessage name="World" />)
165
+ })
163
166
  ```
164
167
 
165
168
  5. Add the following to `app/javascript/App.js`:
169
+
166
170
  ```jsx
167
- import React from 'react';
168
- import 'App.css';
169
- const HelloMessage = ({ name }) => <h1>Hello, {name}!</h1>;
170
- export default HelloMessage;
171
+ import React from "react"
172
+ import "App.css"
173
+ const HelloMessage = ({ name }) => <h1>Hello, {name}!</h1>
174
+ export default HelloMessage
171
175
  ```
172
176
 
173
177
  6. Add the following to `app/javascript/App.css`:
178
+
174
179
  ```css
175
- h1 { color: blue; }
180
+ h1 {
181
+ color: blue;
182
+ }
176
183
  ```
177
184
 
178
185
  7. Enable HMR in config/shakapacker.yml:
186
+
179
187
  ```shell
180
188
  hmr: true
181
189
  ```
@@ -189,22 +197,21 @@ npm install --dev react-refresh @pmmmwh/react-refresh-webpack-plugin
189
197
  9. Alter `config/webpack/webpack.config.js` like so:
190
198
 
191
199
  ```js
192
- const { generateWebpackConfig, inliningCss } = require('shakapacker');
193
- const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin');
194
- const isDevelopment = process.env.NODE_ENV !== 'production';
200
+ const { generateWebpackConfig, inliningCss } = require("shakapacker")
201
+ const ReactRefreshWebpackPlugin = require("@pmmmwh/react-refresh-webpack-plugin")
202
+ const isDevelopment = process.env.NODE_ENV !== "production"
195
203
 
196
- const webpackConfig = generateWebpackConfig();
204
+ const webpackConfig = generateWebpackConfig()
197
205
 
198
206
  if (isDevelopment && inliningCss) {
199
- webpackConfig.plugins.push(
200
- new ReactRefreshWebpackPlugin()
201
- );
207
+ webpackConfig.plugins.push(new ReactRefreshWebpackPlugin())
202
208
  }
203
209
 
204
- module.exports = webpackConfig;
210
+ module.exports = webpackConfig
205
211
  ```
206
212
 
207
213
  10. Remove the Babel configuration from `package.json`
214
+
208
215
  ```diff
209
216
  - "babel": {
210
217
  - "presets": [
@@ -214,18 +221,19 @@ module.exports = webpackConfig;
214
221
  ```
215
222
 
216
223
  11. Create a `babel.config.js` file in the project root and add the following [sample code](https://github.com/shakacode/shakapacker/blob/main/docs/customizing_babel_config.md#react-configuration):
224
+
217
225
  ```js
218
226
  module.exports = function (api) {
219
- const defaultConfigFunc = require('shakapacker/package/babel/preset.js')
227
+ const defaultConfigFunc = require("shakapacker/package/babel/preset.js")
220
228
  const resultConfig = defaultConfigFunc(api)
221
- const isDevelopmentEnv = api.env('development')
222
- const isProductionEnv = api.env('production')
223
- const isTestEnv = api.env('test')
229
+ const isDevelopmentEnv = api.env("development")
230
+ const isProductionEnv = api.env("production")
231
+ const isTestEnv = api.env("test")
224
232
 
225
233
  const changesOnDefault = {
226
234
  presets: [
227
235
  [
228
- '@babel/preset-react',
236
+ "@babel/preset-react",
229
237
  {
230
238
  development: isDevelopmentEnv || isTestEnv,
231
239
  useBuiltIns: true
@@ -233,23 +241,25 @@ module.exports = function (api) {
233
241
  ]
234
242
  ].filter(Boolean),
235
243
  plugins: [
236
- isProductionEnv && ['babel-plugin-transform-react-remove-prop-types',
244
+ isProductionEnv && [
245
+ "babel-plugin-transform-react-remove-prop-types",
237
246
  {
238
247
  removeImport: true
239
248
  }
240
249
  ],
241
- process.env.WEBPACK_SERVE && 'react-refresh/babel'
242
- ].filter(Boolean),
250
+ process.env.WEBPACK_SERVE && "react-refresh/babel"
251
+ ].filter(Boolean)
243
252
  }
244
253
 
245
254
  resultConfig.presets = [...resultConfig.presets, ...changesOnDefault.presets]
246
- resultConfig.plugins = [...resultConfig.plugins, ...changesOnDefault.plugins ]
255
+ resultConfig.plugins = [...resultConfig.plugins, ...changesOnDefault.plugins]
247
256
 
248
257
  return resultConfig
249
258
  }
250
259
  ```
251
260
 
252
261
  9. Start the Rails server and the `shakapacker-dev-server` in separate console windows:
262
+
253
263
  ```shell
254
264
  rails s
255
265
  ./bin/shakapacker-dev-server
data/docs/releasing.md CHANGED
@@ -12,7 +12,6 @@ This guide is for Shakapacker maintainers who need to publish a new release.
12
12
  ```
13
13
 
14
14
  2. **Ensure you have publishing access:**
15
-
16
15
  - npm: You must be a collaborator on the [shakapacker npm package](https://www.npmjs.com/package/shakapacker)
17
16
  - RubyGems: You must be an owner of the [shakapacker gem](https://rubygems.org/gems/shakapacker)
18
17
 
@@ -103,7 +102,6 @@ rake create_release[10.0.0.rc.1] # Gem: 10.0.0.rc.1, npm: 10.0.0-rc.1
103
102
  ### 6. After Release
104
103
 
105
104
  1. Verify the release on:
106
-
107
105
  - [npm](https://www.npmjs.com/package/shakapacker)
108
106
  - [RubyGems](https://rubygems.org/gems/shakapacker)
109
107
  - [GitHub releases](https://github.com/shakacode/shakapacker/releases)