shakapacker 10.3.0 → 10.3.2
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 +34 -3
- data/lib/install/bin/diff-bundler-config +3 -6
- data/lib/install/bin/shakapacker-config +3 -6
- data/lib/shakapacker/configuration.rb +16 -6
- data/lib/shakapacker/dev_server.rb +7 -2
- data/lib/shakapacker/dev_server_proxy.rb +4 -0
- data/lib/shakapacker/doctor.rb +200 -14
- data/lib/shakapacker/swc_migrator.rb +104 -5
- data/lib/shakapacker/utils/misc.rb +5 -1
- data/lib/shakapacker/version.rb +1 -1
- data/package.json +3 -3
- metadata +3 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d74b345013f03450e4cd5050bd22f2364e2acf8b00a750acf833b07eda6046c7
|
|
4
|
+
data.tar.gz: 4933ffb9d1feb7acc0bdcb2a06fb492b030ea347976da728dd83a7e4b7f3790f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1a286328ea129dc5e2c9baad6fae0aaeec4c886533a10489301e3396fd45ac3fb9b3db35455407de79eda6506d983c0a474ba7c69ea2e68eed99b715700ae274
|
|
7
|
+
data.tar.gz: 1411acd0a7475961d10fc0a8e99bfa76e235b1c9e83ff7e9a152f726c578e2ac0cb5654dced3a52a492e62d75fc741cf68f8a6cd0deabc23ed294229e87a874e
|
data/CHANGELOG.md
CHANGED
|
@@ -10,6 +10,35 @@
|
|
|
10
10
|
|
|
11
11
|
## [Unreleased]
|
|
12
12
|
|
|
13
|
+
## [v10.3.2] - August 28, 2026
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
|
|
17
|
+
- **Bumped the development and CI pin for Rspack from `2.0.1` to `2.2.0`.** [PR #1258](https://github.com/shakacode/shakapacker/pull/1258) by [justin808](https://github.com/justin808). The `@rspack/core`, `@rspack/cli`, `@rspack/dev-server`, and `@rspack/plugin-react-refresh` peer ranges are unchanged at `^2.0.0`, so applications may stay on any Rspack `2.x` release; only this repository's own development pins and dummy-app lockfiles move, so CI now exercises Rspack 2.2 against the range it already advertises. Annotated config exports (`bin/shakapacker-config --annotate`) also now list the complete `optimization.moduleIds` and `optimization.chunkIds` value sets for both bundlers, including `'compat-hashed'`, which requires Rspack 2.2 or newer and is documented as opt-in rather than made a default.
|
|
18
|
+
|
|
19
|
+
### Fixed
|
|
20
|
+
|
|
21
|
+
- **Fixed `shakapacker:doctor` not telling Rspack apps that a `.swcrc` is ignored outright.** [PR #1276](https://github.com/shakacode/shakapacker/pull/1276) by [justin808](https://github.com/justin808). Doctor previously told Rspack apps only that moving `.swcrc` settings into `config/swc.config.js` would not help, while deliberately making no claim about the `.swcrc` itself, because the behavior had never been verified. It has now been verified against `@rspack/core` 2.0.1 and 2.2.0: Rspack's `builtin:swc-loader` never reads `.swcrc`. A `.swcrc` setting `jsc.target` and injecting an optimizer global produced byte-identical output to no `.swcrc` at all, while the same options passed inline as loader options did change the output. A `.swcrc` enabling decorator syntax likewise failed to unblock a decorator source, including with empty loader options and with `swcrc`/`configFile` set, so this is not merely inline options taking precedence. Doctor now states that a `.swcrc` is not read on Rspack and that every setting in it is silently inert - the mirror image of the `config/swc.config.js` case in [#1259](https://github.com/shakacode/shakapacker/issues/1259) - and continues to point at overriding the built-in `builtin:swc-loader` rule. Webpack messaging is unchanged. Fixes [#1263](https://github.com/shakacode/shakapacker/issues/1263).
|
|
22
|
+
- **Fixed `shakapacker:doctor` staying silent about SWC configuration on Rspack apps that do not set `javascript_transpiler: swc`.** [PR #1269](https://github.com/shakacode/shakapacker/pull/1269) by [justin808](https://github.com/justin808). Shakapacker's Rspack rules always transpile with `builtin:swc-loader` and never consult `javascript_transpiler`, so `config/swc.config.js` goes unread on an Rspack app configured for Babel or esbuild exactly as it does on one configured for SWC. Doctor's Rspack SWC-configuration warnings were gated on `javascript_transpiler: swc`, so those apps got no warning at all. Those warnings now reach any Rspack app: that `config/swc.config.js` is not read, and, for a `.swcrc`, that moving its settings into `config/swc.config.js` would not affect the build. The webpack-only SWC content checks and the "merged with Shakapacker's defaults" messaging stay gated on `javascript_transpiler: swc`, and apps with `javascript_transpiler: none` remain opted out. Fixes [#1265](https://github.com/shakacode/shakapacker/issues/1265).
|
|
23
|
+
- **Fixed `shakapacker:doctor` and `rake shakapacker:migrate_to_swc` telling Rspack apps that `config/swc.config.js` is merged into their build.** [PR #1260](https://github.com/shakacode/shakapacker/pull/1260) by [justin808](https://github.com/justin808). Rspack builds never read `config/swc.config.js`, because Shakapacker's Rspack rules set their `builtin:swc-loader` options inline. Doctor now warns that the file is unread on Rspack instead of reporting it as merged (and skips its content checks there), and no longer tells Rspack users with a `.swcrc` to migrate those settings into `config/swc.config.js`. The migrator's post-migration guidance and the generated file header instead show how to override the built-in `builtin:swc-loader` rule: apply `webpack-merge`'s `mergeWithRules` to the _output_ of `generateRspackConfig()`, since that function merges with plain `merge`, which concatenates `module.rules`, so an override passed into it is appended alongside the built-in rule rather than replacing it. Webpack apps keep the existing messaging. Fixes [#1259](https://github.com/shakacode/shakapacker/issues/1259).
|
|
24
|
+
- **Fixed post-publish GitHub release failures hiding successful package publication details.** The release task now prints its normal publication summary and the exact `sync_github_release` recovery command before exiting nonzero. [PR #1250](https://github.com/shakacode/shakapacker/pull/1250) by [justin808](https://github.com/justin808).
|
|
25
|
+
- **Fixed helper binstubs to fail closed when `PATH` is unset.** [PR #1240](https://github.com/shakacode/shakapacker/pull/1240) by [justin808](https://github.com/justin808). `bin/shakapacker-config` and `bin/diff-bundler-config` now report the missing-Node error without executing an app-root `node` binary when `PATH` is unset, while explicit `PATH` values retain their existing Node-resolution behavior. Fixes [#1234](https://github.com/shakacode/shakapacker/issues/1234).
|
|
26
|
+
- **Fixed the deprecation warning for the legacy `bundler` config key claiming the value was understood while it was ignored.** [PR #1270](https://github.com/shakacode/shakapacker/pull/1270) by [justin808](https://github.com/justin808). An app whose `config/shakapacker.yml` set only `bundler:` was told the key was deprecated and then built with a different bundler, because `assets_bundler` always resolves from the bundled defaults and the legacy key was never read. The warning now states that the value is ignored, names the bundler actually in use, and tells you to set `assets_bundler` instead. One resolution change accompanies it: a config that leaves `assets_bundler:` blank while setting `bundler:` previously resolved the legacy value in Ruby and now resolves `webpack`, matching what `package/config.ts` already built for it. Fixes [#1262](https://github.com/shakacode/shakapacker/issues/1262).
|
|
27
|
+
|
|
28
|
+
## [v10.3.1] - August 3, 2026
|
|
29
|
+
|
|
30
|
+
### Fixed
|
|
31
|
+
|
|
32
|
+
- **Fixed 502 responses for proxied dev server assets under `rack-proxy` v1.** [PR #1222](https://github.com/shakacode/shakapacker/pull/1222) by [jcbpl](https://github.com/jcbpl). Fixes [#1220](https://github.com/shakacode/shakapacker/issues/1220).
|
|
33
|
+
- **Fixed dev-server liveness checks treating refused macOS 27 connections as running.** The Ruby probe now verifies the connected socket's `SO_ERROR` result before proxying asset requests, avoiding false-positive dev-server detection and resulting 502 responses. [PR #1225](https://github.com/shakacode/shakapacker/pull/1225) by [justin808](https://github.com/justin808). Fixes [#1224](https://github.com/shakacode/shakapacker/issues/1224).
|
|
34
|
+
- **Fixed webpack Babel, SWC, and esbuild rules skipping explicitly included `.cjs` files.** [PR #1219](https://github.com/shakacode/shakapacker/pull/1219) by [oiahoon](https://github.com/oiahoon). Fixes [#1218](https://github.com/shakacode/shakapacker/issues/1218).
|
|
35
|
+
- **Added a `shakapacker:doctor` warning for Rspack React Refresh v2 configs that still use the v1 default-export constructor pattern.** [PR #1207](https://github.com/shakacode/shakapacker/pull/1207) by [justin808](https://github.com/justin808). Existing configs with `const ReactRefreshPlugin = require("@rspack/plugin-react-refresh")` followed by `new ReactRefreshPlugin()` can fail after upgrading to `@rspack/plugin-react-refresh` v2 with `ReactRefreshPlugin is not a constructor`; Doctor now points to the affected JS/TS config file and suggests the named-export/default/module compatibility form. Fixes [#1204](https://github.com/shakacode/shakapacker/issues/1204).
|
|
36
|
+
- **Fixed the missing-`@babel/core` failure to report an actionable install message.** [PR #1212](https://github.com/shakacode/shakapacker/pull/1212) by [justin808](https://github.com/justin808). Babel-transpiled builds whose app lacks `@babel/core` previously surfaced a raw module-resolution error from the Babel 8 compatibility check; the rule now explains which package to install and how to switch `javascript_transpiler` instead. Refs [#1163](https://github.com/shakacode/shakapacker/issues/1163).
|
|
37
|
+
|
|
38
|
+
### Documentation
|
|
39
|
+
|
|
40
|
+
- **Documented the required `css-loader@^7.1.4` in the v10 Rspack upgrade instructions.** [PR #1211](https://github.com/shakacode/shakapacker/pull/1211) by [justin808](https://github.com/justin808). The v10 upgrade guide's copy-paste Rspack v2 commands omitted `css-loader`, so apps following them could upgrade into an unsatisfied peer dependency.
|
|
41
|
+
|
|
13
42
|
## [v10.3.0] - July 5, 2026
|
|
14
43
|
|
|
15
44
|
### Added
|
|
@@ -20,7 +49,7 @@
|
|
|
20
49
|
|
|
21
50
|
- **Fixed implicit SWC defaults for existing webpack/Babel apps without `swc-loader`.** [PR #1206](https://github.com/shakacode/shakapacker/pull/1206) by [justin808](https://github.com/justin808). Webpack apps that omit both `javascript_transpiler` and the deprecated `webpack_loader` now fall back to Babel with a warning when Shakapacker's bundled SWC default is active, `swc-loader` is missing, and Babel is present. Explicit transpiler settings, webpack apps with `swc-loader`, and Rspack's built-in SWC path keep their existing behavior. Closes [#1203](https://github.com/shakacode/shakapacker/issues/1203).
|
|
22
51
|
- **Fixed JavaScript config loading for missing Rails environments to use the production fallback.** [PR #1206](https://github.com/shakacode/shakapacker/pull/1206) by [justin808](https://github.com/justin808). When `RAILS_ENV` has no matching section in `config/shakapacker.yml`, the Node package config now merges the `production` section instead of only bundled defaults, matching Ruby configuration loading and honoring explicit production `javascript_transpiler`, `source_path`, `dev_server`, and related settings for custom environments such as staging.
|
|
23
|
-
- **Fixed helper
|
|
52
|
+
- **Fixed helper binstub Node resolution after the `v10.2.0` Ruby-binstub regression.** [PR #1200](https://github.com/shakacode/shakapacker/pull/1200) and [PR #1201](https://github.com/shakacode/shakapacker/pull/1201) by [justin808](https://github.com/justin808). Restores shell-compatible Node lookup for `bin/shakapacker-config` and `bin/diff-bundler-config` when `PATH` is empty, while keeping friendly missing-Node errors for `ENOENT` and `EACCES`. For an unset `PATH`, PR #1200 deliberately delegates Node resolution to Ruby `exec`'s default-path behavior; PR #1240 later changed that case to fail closed.
|
|
24
53
|
|
|
25
54
|
## [v10.2.0] - July 3, 2026
|
|
26
55
|
|
|
@@ -63,7 +92,7 @@
|
|
|
63
92
|
- Optional peers (transpilers, `webpack-dev-server`, CSS preprocessors, react-refresh) stay only if your app uses those features.
|
|
64
93
|
- Adoption is opt-in: leaving your `package.json` untouched on v10.1 also continues to work.
|
|
65
94
|
|
|
66
|
-
- **Adopting `shakapacker-webpack` requires `webpack-assets-manifest@^6.0.0`**. Core `shakapacker` still accepts both v5 and v6 (`^5.0.6 || ^6.0.0`),
|
|
95
|
+
- **Adopting `shakapacker-webpack` requires `webpack-assets-manifest@^6.0.0`**. [PR #1096](https://github.com/shakacode/shakapacker/pull/1096) and [PR #1133](https://github.com/shakacode/shakapacker/pull/1133) by [justin808](https://github.com/justin808). Core `shakapacker` still accepts both v5 and v6 (`^5.0.6 || ^6.0.0`), and `shakapacker-webpack` requires `^6.0.0`. Apps still on `webpack-assets-manifest@5.x` must upgrade when switching to the supplemental package; v6 fixed an ENOENT crash on clean builds with `merge: true` and dropped a Node 14 install path. See [the v5→v6 release notes](https://github.com/webdeveric/webpack-assets-manifest/releases) and `packages/shakapacker-webpack/README.md` for details.
|
|
67
96
|
|
|
68
97
|
### ⚠️ Breaking Changes
|
|
69
98
|
|
|
@@ -986,7 +1015,9 @@ Note: [Rubygem is 6.3.0.pre.rc.1](https://rubygems.org/gems/shakapacker/versions
|
|
|
986
1015
|
|
|
987
1016
|
See [CHANGELOG.md in rails/webpacker (up to v5.4.3)](https://github.com/rails/webpacker/blob/master/CHANGELOG.md)
|
|
988
1017
|
|
|
989
|
-
[Unreleased]: https://github.com/shakacode/shakapacker/compare/v10.3.
|
|
1018
|
+
[Unreleased]: https://github.com/shakacode/shakapacker/compare/v10.3.2...main
|
|
1019
|
+
[v10.3.2]: https://github.com/shakacode/shakapacker/compare/v10.3.1...v10.3.2
|
|
1020
|
+
[v10.3.1]: https://github.com/shakacode/shakapacker/compare/v10.3.0...v10.3.1
|
|
990
1021
|
[v10.3.0]: https://github.com/shakacode/shakapacker/compare/v10.2.0...v10.3.0
|
|
991
1022
|
[v10.2.0]: https://github.com/shakacode/shakapacker/compare/v10.1.0...v10.2.0
|
|
992
1023
|
[v10.1.0]: https://github.com/shakacode/shakapacker/compare/v10.0.0...v10.1.0
|
|
@@ -24,7 +24,7 @@ def shakapacker_warn_missing_node
|
|
|
24
24
|
end
|
|
25
25
|
|
|
26
26
|
def shakapacker_exec_env(launch_dir)
|
|
27
|
-
return
|
|
27
|
+
return unless ENV.key?("PATH")
|
|
28
28
|
|
|
29
29
|
path_entries = ENV["PATH"].split(File::PATH_SEPARATOR, -1)
|
|
30
30
|
path_entries = [""] if path_entries.empty?
|
|
@@ -38,12 +38,9 @@ end
|
|
|
38
38
|
|
|
39
39
|
def shakapacker_exec_node(script_path, argv, launch_dir)
|
|
40
40
|
exec_env = shakapacker_exec_env(launch_dir)
|
|
41
|
+
shakapacker_warn_missing_node unless exec_env
|
|
41
42
|
|
|
42
|
-
|
|
43
|
-
exec shakapacker_node_binary, script_path, *argv
|
|
44
|
-
else
|
|
45
|
-
exec exec_env, shakapacker_node_binary, script_path, *argv
|
|
46
|
-
end
|
|
43
|
+
exec exec_env, shakapacker_node_binary, script_path, *argv
|
|
47
44
|
rescue Errno::ENOENT, Errno::EACCES
|
|
48
45
|
shakapacker_warn_missing_node
|
|
49
46
|
end
|
|
@@ -24,7 +24,7 @@ def shakapacker_warn_missing_node
|
|
|
24
24
|
end
|
|
25
25
|
|
|
26
26
|
def shakapacker_exec_env(launch_dir)
|
|
27
|
-
return
|
|
27
|
+
return unless ENV.key?("PATH")
|
|
28
28
|
|
|
29
29
|
path_entries = ENV["PATH"].split(File::PATH_SEPARATOR, -1)
|
|
30
30
|
path_entries = [""] if path_entries.empty?
|
|
@@ -38,12 +38,9 @@ end
|
|
|
38
38
|
|
|
39
39
|
def shakapacker_exec_node(script_path, argv, launch_dir)
|
|
40
40
|
exec_env = shakapacker_exec_env(launch_dir)
|
|
41
|
+
shakapacker_warn_missing_node unless exec_env
|
|
41
42
|
|
|
42
|
-
|
|
43
|
-
exec shakapacker_node_binary, script_path, *argv
|
|
44
|
-
else
|
|
45
|
-
exec exec_env, shakapacker_node_binary, script_path, *argv
|
|
46
|
-
end
|
|
43
|
+
exec exec_env, shakapacker_node_binary, script_path, *argv
|
|
47
44
|
rescue Errno::ENOENT, Errno::EACCES
|
|
48
45
|
shakapacker_warn_missing_node
|
|
49
46
|
end
|
|
@@ -303,20 +303,30 @@ class Shakapacker::Configuration
|
|
|
303
303
|
# Resolution order:
|
|
304
304
|
# 1. CLI --bundler flag (via bundler_override)
|
|
305
305
|
# 2. SHAKAPACKER_ASSETS_BUNDLER environment variable
|
|
306
|
-
# 3. assets_bundler setting in config file
|
|
307
|
-
# 4.
|
|
308
|
-
#
|
|
306
|
+
# 3. assets_bundler setting in config file (or the bundled default)
|
|
307
|
+
# 4. Defaults to "webpack"
|
|
308
|
+
#
|
|
309
|
+
# The legacy 'bundler' setting is not consulted; it is only used to warn that
|
|
310
|
+
# its value is ignored.
|
|
309
311
|
#
|
|
310
312
|
# @return [String] "webpack" or "rspack"
|
|
311
313
|
def assets_bundler
|
|
312
314
|
# CLI --bundler flag takes highest precedence
|
|
313
315
|
return @bundler_override if @bundler_override
|
|
314
316
|
|
|
315
|
-
|
|
317
|
+
resolved = ENV["SHAKAPACKER_ASSETS_BUNDLER"] || fetch(:assets_bundler) || "webpack"
|
|
318
|
+
|
|
319
|
+
# The legacy 'bundler' key is never read, so warn that its value is ignored
|
|
316
320
|
if data.has_key?(:bundler) && !data.has_key?(:assets_bundler)
|
|
317
|
-
|
|
321
|
+
legacy_value = data[:bundler].to_s.strip
|
|
322
|
+
described_value = legacy_value.empty? ? "empty" : legacy_value
|
|
323
|
+
# An empty SHAKAPACKER_ASSETS_BUNDLER resolves to an empty string; name that
|
|
324
|
+
# state rather than printing "using ''". Doctor reports it as its own issue.
|
|
325
|
+
described_resolved = resolved.to_s.empty? ? "no bundler (SHAKAPACKER_ASSETS_BUNDLER is set but empty)" : "'#{resolved}'"
|
|
326
|
+
$stderr.puts "⚠️ DEPRECATION WARNING: The 'bundler' configuration option is no longer supported and its value (#{described_value}) is IGNORED. Shakapacker is using #{described_resolved}. Set 'assets_bundler' in your shakapacker.yml instead — it was renamed to avoid confusion with Ruby's Bundler gem manager."
|
|
318
327
|
end
|
|
319
|
-
|
|
328
|
+
|
|
329
|
+
resolved
|
|
320
330
|
end
|
|
321
331
|
|
|
322
332
|
# Deprecated alias for {#assets_bundler}
|
|
@@ -47,8 +47,13 @@ class Shakapacker::DevServer
|
|
|
47
47
|
# @return [Boolean] true if the dev server is running
|
|
48
48
|
def running?
|
|
49
49
|
if config.dev_server.present?
|
|
50
|
-
Socket.tcp(host, port, connect_timeout: connect_timeout)
|
|
51
|
-
|
|
50
|
+
socket = Socket.tcp(host, port, connect_timeout: connect_timeout)
|
|
51
|
+
|
|
52
|
+
begin
|
|
53
|
+
socket.getsockopt(Socket::SOL_SOCKET, Socket::SO_ERROR).int.zero?
|
|
54
|
+
ensure
|
|
55
|
+
socket.close
|
|
56
|
+
end
|
|
52
57
|
else
|
|
53
58
|
false
|
|
54
59
|
end
|
|
@@ -11,6 +11,10 @@ class Shakapacker::DevServerProxy < Rack::Proxy
|
|
|
11
11
|
|
|
12
12
|
def perform_request(env)
|
|
13
13
|
if env["PATH_INFO"].start_with?("/#{public_output_uri_path}") && dev_server.running?
|
|
14
|
+
# rack-proxy v1 refuses to derive the backend from the Host header.
|
|
15
|
+
env["rack.backend"] = URI::Generic.build(
|
|
16
|
+
scheme: dev_server.protocol, host: dev_server.host, port: dev_server.port
|
|
17
|
+
)
|
|
14
18
|
env["HTTP_HOST"] = env["HTTP_X_FORWARDED_HOST"] = dev_server.host
|
|
15
19
|
env["HTTP_X_FORWARDED_SERVER"] = dev_server.host_with_port
|
|
16
20
|
env["HTTP_PORT"] = env["HTTP_X_FORWARDED_PORT"] = dev_server.port.to_s
|
data/lib/shakapacker/doctor.rb
CHANGED
|
@@ -59,6 +59,9 @@ module Shakapacker
|
|
|
59
59
|
"@rspack/plugin-react-refresh" => "^2.0.0"
|
|
60
60
|
}.freeze
|
|
61
61
|
|
|
62
|
+
RSPACK_REACT_REFRESH_PACKAGE = "@rspack/plugin-react-refresh".freeze
|
|
63
|
+
VERSION_UPPER_BOUND_OPERATORS = %w[< <=].freeze
|
|
64
|
+
|
|
62
65
|
CUSTOM_HYBRID_LOADER_DEPS = %w[
|
|
63
66
|
babel-loader
|
|
64
67
|
esbuild-loader
|
|
@@ -72,6 +75,25 @@ module Shakapacker
|
|
|
72
75
|
|
|
73
76
|
PACKAGE_ROOT_MARKERS = (["package.json"] + PACKAGE_MANAGER_LOCKFILES.keys + ["node_modules"]).freeze
|
|
74
77
|
|
|
78
|
+
# generateRspackConfig merges with plain webpack-merge `merge` (package/rspack/index.ts),
|
|
79
|
+
# which concatenates `module.rules`, so an override handed to it is appended next to the
|
|
80
|
+
# built-in rule rather than replacing it. mergeWithRules must be applied to its output.
|
|
81
|
+
RSPACK_SWC_OVERRIDE_HINT =
|
|
82
|
+
"Apply webpack-merge's 'mergeWithRules' to the output of generateRspackConfig() in your Rspack config, " \
|
|
83
|
+
"matching on both 'test' and 'use.loader', and using options: 'merge' (not 'replace', which swaps the whole " \
|
|
84
|
+
"options object and drops the built-in parser and transform.react defaults). " \
|
|
85
|
+
"Keep 'test' in the match: matching on 'use.loader' alone makes webpack-merge append 'builtin:swc-loader' to " \
|
|
86
|
+
"every rule's 'use' chain, including the CSS and Sass rules. " \
|
|
87
|
+
"Override the JS (/\\.(js|jsx|mjs)$/) and TypeScript (/\\.(ts|tsx)$/) rules separately, since Shakapacker " \
|
|
88
|
+
"registers a 'builtin:swc-loader' rule for each. " \
|
|
89
|
+
"Passing an override into generateRspackConfig() cannot replace the built-in rule, because it merges with " \
|
|
90
|
+
"plain 'merge', which concatenates 'module.rules' and leaves the built-in 'builtin:swc-loader' rule in place " \
|
|
91
|
+
"alongside yours. Shakapacker re-exports 'mergeWithRules'. " \
|
|
92
|
+
"See: https://github.com/shakacode/shakapacker/blob/main/docs/rspack.md".freeze
|
|
93
|
+
|
|
94
|
+
RSPACK_SWC_OVERRIDE_HINT_BACKREF =
|
|
95
|
+
"See the Rspack 'builtin:swc-loader' override guidance above.".freeze
|
|
96
|
+
|
|
75
97
|
def initialize(config = nil, root_path = nil, options = {})
|
|
76
98
|
@config = config || Shakapacker.config
|
|
77
99
|
@root_path = root_path || (defined?(Rails) ? Rails.root : Pathname.new(Dir.pwd))
|
|
@@ -170,6 +192,7 @@ module Shakapacker
|
|
|
170
192
|
check_css_modules_configuration
|
|
171
193
|
check_bundler_dependencies if config_exists?
|
|
172
194
|
check_rspack_cache_configuration if config_exists?
|
|
195
|
+
check_rspack_react_refresh_plugin_constructor if config_exists?
|
|
173
196
|
check_file_type_dependencies if config_exists?
|
|
174
197
|
check_sri_dependencies if config_exists?
|
|
175
198
|
check_peer_dependencies
|
|
@@ -661,8 +684,11 @@ module Shakapacker
|
|
|
661
684
|
add_warning("Both esbuild and Babel dependencies are installed. Consider removing Babel dependencies to reduce node_modules size")
|
|
662
685
|
end
|
|
663
686
|
|
|
664
|
-
# Check for SWC configuration conflicts
|
|
665
|
-
|
|
687
|
+
# Check for SWC configuration conflicts. Rspack always transpiles with
|
|
688
|
+
# builtin:swc-loader, so SWC config files go unread there regardless of
|
|
689
|
+
# javascript_transpiler; the webpack-only content checks stay SWC-gated
|
|
690
|
+
# inside check_swc_config_conflicts.
|
|
691
|
+
if transpiler == "swc" || assets_bundler == "rspack"
|
|
666
692
|
check_swc_config_conflicts
|
|
667
693
|
end
|
|
668
694
|
end
|
|
@@ -714,16 +740,48 @@ module Shakapacker
|
|
|
714
740
|
swcrc_path = root_path.join(".swcrc")
|
|
715
741
|
swc_config_path = root_path.join("config/swc.config.js")
|
|
716
742
|
|
|
743
|
+
rspack = assets_bundler == "rspack"
|
|
744
|
+
|
|
717
745
|
if swcrc_path.exist?
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
746
|
+
if rspack
|
|
747
|
+
# Verified against @rspack/core 2.0.1 and 2.2.0: 'builtin:swc-loader' never reads .swcrc.
|
|
748
|
+
# A .swcrc setting jsc.target and an optimizer global produced byte-identical output to
|
|
749
|
+
# no .swcrc, and the same options passed inline did change the output. A .swcrc enabling
|
|
750
|
+
# decorator syntax also failed to unblock a decorator source, including with empty loader
|
|
751
|
+
# options and with swcrc/configFile set, so this is not just inline options winning.
|
|
752
|
+
add_warning("SWC configuration: .swcrc is present but is NOT read when assets_bundler is 'rspack'. " \
|
|
753
|
+
"Rspack transpiles with 'builtin:swc-loader', which ignores .swcrc entirely, so every setting in it is silently inert. " \
|
|
754
|
+
"Moving these settings to config/swc.config.js would not help either - Shakapacker's Rspack build does not read that file.")
|
|
755
|
+
add_rspack_swc_override_hint("To apply custom SWC options on Rspack, override the built-in 'builtin:swc-loader' rule.")
|
|
756
|
+
else
|
|
757
|
+
add_warning("SWC configuration: .swcrc file detected. This file completely overrides Shakapacker's default SWC settings and may cause build failures. " \
|
|
758
|
+
"Please migrate to config/swc.config.js which properly merges with Shakapacker defaults. " \
|
|
759
|
+
"To migrate: Move your custom settings from .swcrc to config/swc.config.js (see docs for format). " \
|
|
760
|
+
"See: https://github.com/shakacode/shakapacker/blob/main/docs/using_swc_loader.md")
|
|
761
|
+
end
|
|
722
762
|
end
|
|
723
763
|
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
764
|
+
return unless swc_config_path.exist?
|
|
765
|
+
|
|
766
|
+
if rspack
|
|
767
|
+
add_warning("SWC configuration: config/swc.config.js is present but is NOT read when assets_bundler is 'rspack'. " \
|
|
768
|
+
"Shakapacker's Rspack config sets its 'builtin:swc-loader' options inline, so nothing in this file reaches your build.")
|
|
769
|
+
add_rspack_swc_override_hint("Customize SWC for Rspack by overriding the built-in 'builtin:swc-loader' rule instead.")
|
|
770
|
+
return
|
|
771
|
+
end
|
|
772
|
+
|
|
773
|
+
@info << "SWC configuration: Using config/swc.config.js (recommended). This config is merged with Shakapacker's defaults."
|
|
774
|
+
check_swc_config_settings(swc_config_path)
|
|
775
|
+
end
|
|
776
|
+
|
|
777
|
+
# The full hint is ~700 characters, and an Rspack app with both .swcrc and
|
|
778
|
+
# config/swc.config.js hits both call sites, so emit it once and refer back after that.
|
|
779
|
+
def add_rspack_swc_override_hint(lead)
|
|
780
|
+
if @rspack_swc_override_hint_emitted
|
|
781
|
+
add_fix_hint("#{lead} #{RSPACK_SWC_OVERRIDE_HINT_BACKREF}")
|
|
782
|
+
else
|
|
783
|
+
@rspack_swc_override_hint_emitted = true
|
|
784
|
+
add_fix_hint("#{lead} #{RSPACK_SWC_OVERRIDE_HINT}")
|
|
727
785
|
end
|
|
728
786
|
end
|
|
729
787
|
|
|
@@ -878,14 +936,89 @@ module Shakapacker
|
|
|
878
936
|
"See https://rspack.rs/config/cache for options.")
|
|
879
937
|
end
|
|
880
938
|
|
|
939
|
+
def check_rspack_react_refresh_plugin_constructor
|
|
940
|
+
return unless rspack_react_refresh_check_applicable?
|
|
941
|
+
return unless rspack_react_refresh_plugin_v2_or_newer?
|
|
942
|
+
|
|
943
|
+
rspack_react_refresh_config_paths.each do |path|
|
|
944
|
+
content = File.read(path)
|
|
945
|
+
next unless legacy_rspack_react_refresh_constructor?(content)
|
|
946
|
+
|
|
947
|
+
relative = config_path_for_warning(path)
|
|
948
|
+
add_action_required("Rspack React Refresh config #{relative} uses the " \
|
|
949
|
+
"#{RSPACK_REACT_REFRESH_PACKAGE} v1 default-export constructor pattern. " \
|
|
950
|
+
"With #{RSPACK_REACT_REFRESH_PACKAGE} v2, rspack may fail with " \
|
|
951
|
+
"'ReactRefreshPlugin is not a constructor'.")
|
|
952
|
+
add_fix_hint("Use a compat constructor: const ReactRefresh = require(\"#{RSPACK_REACT_REFRESH_PACKAGE}\"); " \
|
|
953
|
+
"const ReactRefreshRspackPlugin = ReactRefresh.ReactRefreshRspackPlugin || " \
|
|
954
|
+
"ReactRefresh.default || ReactRefresh; then call new ReactRefreshRspackPlugin().")
|
|
955
|
+
rescue SystemCallError => e
|
|
956
|
+
add_info_warning("Unable to validate Rspack React Refresh config #{config_path_for_warning(path)}: #{e.message}")
|
|
957
|
+
end
|
|
958
|
+
end
|
|
959
|
+
|
|
960
|
+
def rspack_react_refresh_check_applicable?
|
|
961
|
+
assets_bundler == "rspack" || unconfigured_hybrid_loader_graph?
|
|
962
|
+
end
|
|
963
|
+
|
|
964
|
+
def rspack_react_refresh_plugin_v2_or_newer?
|
|
965
|
+
version = installed_package_version(RSPACK_REACT_REFRESH_PACKAGE)
|
|
966
|
+
return version >= Gem::Version.new("2.0.0") if version
|
|
967
|
+
|
|
968
|
+
package_specifier_allows_version_or_newer?(
|
|
969
|
+
package_json_dependency_version(RSPACK_REACT_REFRESH_PACKAGE),
|
|
970
|
+
Gem::Version.new("2.0.0")
|
|
971
|
+
)
|
|
972
|
+
end
|
|
973
|
+
|
|
974
|
+
def rspack_react_refresh_config_paths
|
|
975
|
+
config_dir = rspack_react_refresh_config_dir
|
|
976
|
+
config_dir_path = Pathname.new(File.join(root_path.to_s, config_dir))
|
|
977
|
+
return [] unless config_dir_path.directory?
|
|
978
|
+
|
|
979
|
+
path = active_bundler_config_path_in(config_dir)
|
|
980
|
+
path ? [path] : []
|
|
981
|
+
end
|
|
982
|
+
|
|
983
|
+
def rspack_react_refresh_config_dir
|
|
984
|
+
config_dir = config.assets_bundler_config_path.to_s
|
|
985
|
+
|
|
986
|
+
if assets_bundler == "rspack" || same_directory_hybrid_config_present?(config_dir)
|
|
987
|
+
config_dir
|
|
988
|
+
else
|
|
989
|
+
"config/rspack"
|
|
990
|
+
end
|
|
991
|
+
end
|
|
992
|
+
|
|
993
|
+
def legacy_rspack_react_refresh_constructor?(content)
|
|
994
|
+
stripped = strip_rspack_config_comments_and_literals(content, preserve_literals: [RSPACK_REACT_REFRESH_PACKAGE])
|
|
995
|
+
constructor_names = []
|
|
996
|
+
|
|
997
|
+
constructor_names.concat(stripped.scan(
|
|
998
|
+
/\b(?:const|let|var)\s+([A-Za-z_$][\w$]*)\s*=\s*require\(\s*["']#{Regexp.escape(RSPACK_REACT_REFRESH_PACKAGE)}["']\s*\)(?=\s*(?:[;,\)]|$))/
|
|
999
|
+
).flatten)
|
|
1000
|
+
constructor_names.concat(stripped.scan(
|
|
1001
|
+
/\bimport\s+([A-Za-z_$][\w$]*)\s*(?:,\s*\{[^}]*\}\s*)?\s+from\s*["']#{Regexp.escape(RSPACK_REACT_REFRESH_PACKAGE)}["']/
|
|
1002
|
+
).flatten)
|
|
1003
|
+
constructor_names.concat(stripped.scan(
|
|
1004
|
+
/\bimport\s+\*\s+as\s+([A-Za-z_$][\w$]*)\s+from\s*["']#{Regexp.escape(RSPACK_REACT_REFRESH_PACKAGE)}["']/
|
|
1005
|
+
).flatten)
|
|
1006
|
+
|
|
1007
|
+
constructor_names.uniq.any? do |constructor_name|
|
|
1008
|
+
stripped.match?(/\bnew\s+#{Regexp.escape(constructor_name)}\s*\(/)
|
|
1009
|
+
end
|
|
1010
|
+
end
|
|
1011
|
+
|
|
881
1012
|
# Returns the single active config path the runner would load, or nil. Mirrors the
|
|
882
1013
|
# resolution order in Shakapacker::Runner#find_rspack_config_with_fallback so the
|
|
883
1014
|
# doctor inspects the same file the build will actually use (and so unused sibling
|
|
884
1015
|
# configs in the same directory don't trigger spurious warnings).
|
|
885
1016
|
# NOTE: keep this candidate list in sync with Runner#find_rspack_config_with_fallback.
|
|
886
1017
|
def active_assets_bundler_config_path
|
|
887
|
-
|
|
1018
|
+
active_bundler_config_path_in(config.assets_bundler_config_path.to_s)
|
|
1019
|
+
end
|
|
888
1020
|
|
|
1021
|
+
def active_bundler_config_path_in(config_dir)
|
|
889
1022
|
candidates = %w[ts js].map { |ext| Pathname.new(File.join(root_path.to_s, config_dir, "rspack.config.#{ext}")) }
|
|
890
1023
|
candidates += %w[ts js].map { |ext| Pathname.new(File.join(root_path.to_s, config_dir, "webpack.config.#{ext}")) }
|
|
891
1024
|
if default_rspack_config_dir?(config_dir)
|
|
@@ -944,7 +1077,7 @@ module Shakapacker
|
|
|
944
1077
|
stripped.gsub(%r{/(?:\\.|\[[^\]\n]*\]|[^/\n\\\[])+?/[gimsuy]*}, "")
|
|
945
1078
|
end
|
|
946
1079
|
|
|
947
|
-
def strip_rspack_config_comments_and_literals(content)
|
|
1080
|
+
def strip_rspack_config_comments_and_literals(content, preserve_literals: [])
|
|
948
1081
|
stripped = +""
|
|
949
1082
|
index = 0
|
|
950
1083
|
|
|
@@ -987,8 +1120,12 @@ module Shakapacker
|
|
|
987
1120
|
end
|
|
988
1121
|
|
|
989
1122
|
literal = content[index...literal_end]
|
|
990
|
-
|
|
991
|
-
|
|
1123
|
+
if preserved_js_string_literal?(literal, char, preserve_literals)
|
|
1124
|
+
stripped << literal
|
|
1125
|
+
else
|
|
1126
|
+
stripped << '""'
|
|
1127
|
+
stripped << literal.gsub(/[^\n]/, "")
|
|
1128
|
+
end
|
|
992
1129
|
index = literal_end
|
|
993
1130
|
elsif char == "`"
|
|
994
1131
|
literal_end = index + 1
|
|
@@ -1029,6 +1166,12 @@ module Shakapacker
|
|
|
1029
1166
|
stripped
|
|
1030
1167
|
end
|
|
1031
1168
|
|
|
1169
|
+
def preserved_js_string_literal?(literal, quote, preserve_literals)
|
|
1170
|
+
return false unless literal.end_with?(quote)
|
|
1171
|
+
|
|
1172
|
+
preserve_literals.include?(literal[1...-1])
|
|
1173
|
+
end
|
|
1174
|
+
|
|
1032
1175
|
def direct_export_cache_disabled?(stripped)
|
|
1033
1176
|
# Match `cache: false` only near an exported config object at brace depth
|
|
1034
1177
|
# 1. This avoids warning on local base config objects while still
|
|
@@ -1183,8 +1326,9 @@ module Shakapacker
|
|
|
1183
1326
|
return versions.min
|
|
1184
1327
|
end
|
|
1185
1328
|
|
|
1329
|
+
return package_version_from_range_specifier(cleaned) if cleaned.match?(/[<>=]/)
|
|
1186
1330
|
return nil unless cleaned.match?(/\A[\^~]?\d/)
|
|
1187
|
-
return nil if cleaned.match?(/(\s
|
|
1331
|
+
return nil if cleaned.match?(/(\s|\|\||:|\A(?:git|file|link|workspace|npm):)/)
|
|
1188
1332
|
|
|
1189
1333
|
match = cleaned.sub(/\A[\^~]/, "").match(/\A(\d+(?:\.\d+){0,2})(?:-[0-9A-Za-z.-]+)?\z/)
|
|
1190
1334
|
match && Gem::Version.new(match[1])
|
|
@@ -1192,6 +1336,48 @@ module Shakapacker
|
|
|
1192
1336
|
nil
|
|
1193
1337
|
end
|
|
1194
1338
|
|
|
1339
|
+
def package_version_from_range_specifier(specifier)
|
|
1340
|
+
lower_bounds = specifier.scan(/(?:\A|\s)(?:>=|>)\s*(\d+(?:\.\d+){0,2})(?:-[0-9A-Za-z.-]+)?/)
|
|
1341
|
+
versions = lower_bounds.flatten.map { |version| Gem::Version.new(version) }
|
|
1342
|
+
|
|
1343
|
+
versions.max
|
|
1344
|
+
rescue ArgumentError
|
|
1345
|
+
nil
|
|
1346
|
+
end
|
|
1347
|
+
|
|
1348
|
+
def package_specifier_allows_version_or_newer?(specifier, minimum)
|
|
1349
|
+
return false unless specifier
|
|
1350
|
+
|
|
1351
|
+
cleaned = specifier.strip
|
|
1352
|
+
if cleaned.include?("||")
|
|
1353
|
+
return cleaned.split("||").any? { |part| package_specifier_allows_version_or_newer?(part, minimum) }
|
|
1354
|
+
end
|
|
1355
|
+
return false if cleaned.match?(/(:|\A(?:git|file|link|workspace|npm):)/)
|
|
1356
|
+
|
|
1357
|
+
if cleaned.match?(/[<>=]/)
|
|
1358
|
+
return package_range_specifier_allows_version_or_newer?(cleaned, minimum)
|
|
1359
|
+
end
|
|
1360
|
+
|
|
1361
|
+
version = package_version_from_specifier(cleaned)
|
|
1362
|
+
version && version >= minimum
|
|
1363
|
+
end
|
|
1364
|
+
|
|
1365
|
+
def package_range_specifier_allows_version_or_newer?(specifier, minimum)
|
|
1366
|
+
comparators = specifier.scan(/(?:\A|\s)(<=|<|>=|>|=)\s*(\d+(?:\.\d+){0,2})(?:-[0-9A-Za-z.-]+)?/)
|
|
1367
|
+
return false if comparators.empty?
|
|
1368
|
+
|
|
1369
|
+
equalities = comparators.select { |operator, _version| operator == "=" }
|
|
1370
|
+
return equalities.any? { |_operator, version| Gem::Version.new(version) >= minimum } if equalities.any?
|
|
1371
|
+
|
|
1372
|
+
upper_bounds = comparators.select { |operator, _version| VERSION_UPPER_BOUND_OPERATORS.include?(operator) }
|
|
1373
|
+
upper_bounds.all? do |operator, version|
|
|
1374
|
+
parsed = Gem::Version.new(version)
|
|
1375
|
+
operator == "<" ? parsed > minimum : parsed >= minimum
|
|
1376
|
+
end
|
|
1377
|
+
rescue ArgumentError
|
|
1378
|
+
false
|
|
1379
|
+
end
|
|
1380
|
+
|
|
1195
1381
|
def declared_package_dependencies
|
|
1196
1382
|
@declared_package_dependencies ||= begin
|
|
1197
1383
|
package_json_paths.reverse_each.each_with_object({}) do |path, dependencies|
|
|
@@ -46,11 +46,65 @@ module Shakapacker
|
|
|
46
46
|
.eslintrc.json
|
|
47
47
|
].freeze
|
|
48
48
|
|
|
49
|
-
|
|
49
|
+
SWC_CONFIG_WEBPACK_HEADER = <<~JS.freeze
|
|
50
50
|
// config/swc.config.js
|
|
51
51
|
// This file is merged with Shakapacker's default SWC configuration
|
|
52
52
|
// See: https://swc.rs/docs/configuration/compilation
|
|
53
|
+
JS
|
|
54
|
+
|
|
55
|
+
# Rspack never reads config/swc.config.js: package/rules/rspack.ts sets its
|
|
56
|
+
# builtin:swc-loader options inline, so the file is generated with a header that says so.
|
|
57
|
+
#
|
|
58
|
+
# The example keeps `test: 'match'` and overrides the JS and TS rules separately on
|
|
59
|
+
# purpose. Matching on `use.loader` alone (a single override with no `test`) looks tidier
|
|
60
|
+
# but is wrong: webpack-merge cannot pair such an override with a specific rule, so it
|
|
61
|
+
# appends builtin:swc-loader onto EVERY rule's `use` chain, including the CSS and Sass
|
|
62
|
+
# rules. Verified at webpack-merge 5.10.0 and 6.0.1.
|
|
63
|
+
SWC_CONFIG_RSPACK_HEADER = <<~JS.freeze
|
|
64
|
+
// config/swc.config.js
|
|
65
|
+
// NOTE: This file is NOT read when assets_bundler is 'rspack'.
|
|
66
|
+
// Shakapacker's Rspack config sets its 'builtin:swc-loader' options inline, so nothing
|
|
67
|
+
// here reaches your build. To customize SWC for Rspack, apply webpack-merge's
|
|
68
|
+
// mergeWithRules to the OUTPUT of generateRspackConfig(). Passing an override into
|
|
69
|
+
// generateRspackConfig() cannot replace the built-in rule: it merges with plain merge,
|
|
70
|
+
// which concatenates module.rules and leaves the built-in rule in place alongside yours.
|
|
71
|
+
//
|
|
72
|
+
// Use options: 'merge', not 'replace'. 'merge' deep-merges into the built-in options so
|
|
73
|
+
// parser.jsx (JS), parser.syntax/tsx (TS), and transform.react.runtime survive.
|
|
74
|
+
// 'replace' swaps the whole options object and silently drops them, breaking JSX and
|
|
75
|
+
// TypeScript compilation.
|
|
76
|
+
//
|
|
77
|
+
// Keep test: 'match' in the merge spec. Matching on use.loader alone appends
|
|
78
|
+
// builtin:swc-loader to every rule's use chain, CSS and Sass included.
|
|
79
|
+
//
|
|
80
|
+
// const { mergeWithRules } = require('shakapacker');
|
|
81
|
+
// const { generateRspackConfig } = require('shakapacker/rspack');
|
|
82
|
+
//
|
|
83
|
+
// const swcOptions = { jsc: { keepClassNames: true } }; // your SWC options
|
|
84
|
+
//
|
|
85
|
+
// module.exports = mergeWithRules({
|
|
86
|
+
// module: { rules: { test: 'match', use: { loader: 'match', options: 'merge' } } },
|
|
87
|
+
// })(generateRspackConfig(), {
|
|
88
|
+
// module: {
|
|
89
|
+
// rules: [
|
|
90
|
+
// // Shakapacker registers separate builtin:swc-loader rules for JS and TS.
|
|
91
|
+
// // Override both: a JS-only override never reaches .ts/.tsx files.
|
|
92
|
+
// {
|
|
93
|
+
// test: /\\.(js|jsx|mjs)$/,
|
|
94
|
+
// use: [{ loader: 'builtin:swc-loader', options: swcOptions }],
|
|
95
|
+
// },
|
|
96
|
+
// {
|
|
97
|
+
// test: /\\.(ts|tsx)$/,
|
|
98
|
+
// use: [{ loader: 'builtin:swc-loader', options: swcOptions }],
|
|
99
|
+
// },
|
|
100
|
+
// ],
|
|
101
|
+
// },
|
|
102
|
+
// });
|
|
103
|
+
//
|
|
104
|
+
// See: https://github.com/shakacode/shakapacker/blob/main/docs/rspack.md
|
|
105
|
+
JS
|
|
53
106
|
|
|
107
|
+
SWC_CONFIG_BODY = <<~JS.freeze
|
|
54
108
|
const { env } = require('shakapacker');
|
|
55
109
|
|
|
56
110
|
module.exports = {
|
|
@@ -70,6 +124,11 @@ module Shakapacker
|
|
|
70
124
|
};
|
|
71
125
|
JS
|
|
72
126
|
|
|
127
|
+
# Kept for backward compatibility: same value as before, and still the webpack variant.
|
|
128
|
+
DEFAULT_SWC_CONFIG = "#{SWC_CONFIG_WEBPACK_HEADER}\n#{SWC_CONFIG_BODY}".freeze
|
|
129
|
+
|
|
130
|
+
RSPACK_SWC_CONFIG = "#{SWC_CONFIG_RSPACK_HEADER}\n#{SWC_CONFIG_BODY}".freeze
|
|
131
|
+
|
|
73
132
|
def initialize(root_path, logger: nil)
|
|
74
133
|
@root_path = Pathname.new(root_path)
|
|
75
134
|
@logger = logger || Logger.new($stdout)
|
|
@@ -89,9 +148,7 @@ module Shakapacker
|
|
|
89
148
|
logger.info " Note: SWC is approximately 20x faster than Babel for transpilation."
|
|
90
149
|
logger.info " Please test your application thoroughly after migration."
|
|
91
150
|
logger.info "\n📝 Configuration Info:"
|
|
92
|
-
|
|
93
|
-
logger.info " - You can customize config/swc.config.js to add additional options"
|
|
94
|
-
logger.info " - Avoid using .swcrc as it overrides Shakapacker defaults completely"
|
|
151
|
+
log_swc_config_guidance
|
|
95
152
|
|
|
96
153
|
# Show cleanup recommendations if babel packages found
|
|
97
154
|
if results[:babel_packages_found].any?
|
|
@@ -275,6 +332,48 @@ module Shakapacker
|
|
|
275
332
|
{}
|
|
276
333
|
end
|
|
277
334
|
|
|
335
|
+
def log_swc_config_guidance
|
|
336
|
+
if rspack?
|
|
337
|
+
logger.info " - config/swc.config.js is NOT read when assets_bundler is 'rspack'"
|
|
338
|
+
logger.info " Shakapacker's Rspack config sets its 'builtin:swc-loader' options inline"
|
|
339
|
+
logger.info " - To customize SWC for Rspack, apply webpack-merge's 'mergeWithRules' to the"
|
|
340
|
+
logger.info " OUTPUT of generateRspackConfig(), matching on both 'test' and 'use.loader'"
|
|
341
|
+
logger.info " and merging 'use.options'. Matching on 'use.loader' alone would append"
|
|
342
|
+
logger.info " 'builtin:swc-loader' to every rule's 'use' chain, CSS and Sass included."
|
|
343
|
+
logger.info " Passing an override into generateRspackConfig() cannot replace"
|
|
344
|
+
logger.info " the built-in rule, because it merges with plain 'merge', which concatenates"
|
|
345
|
+
logger.info " 'module.rules' and leaves the built-in rule in place alongside yours"
|
|
346
|
+
logger.info " - Use options: 'merge', not 'replace', so the built-in parser and"
|
|
347
|
+
logger.info " transform.react defaults survive, and override the JS and TS rules separately"
|
|
348
|
+
logger.info " - The generated config/swc.config.js header contains a copy-pasteable example"
|
|
349
|
+
logger.info " - See: https://github.com/shakacode/shakapacker/blob/main/docs/rspack.md"
|
|
350
|
+
else
|
|
351
|
+
logger.info " - config/swc.config.js is merged with Shakapacker's default SWC configuration"
|
|
352
|
+
logger.info " - You can customize config/swc.config.js to add additional options"
|
|
353
|
+
logger.info " - Avoid using .swcrc as it overrides Shakapacker defaults completely"
|
|
354
|
+
end
|
|
355
|
+
end
|
|
356
|
+
|
|
357
|
+
def rspack?
|
|
358
|
+
assets_bundler == "rspack"
|
|
359
|
+
end
|
|
360
|
+
|
|
361
|
+
# Resolves through Shakapacker's own configuration rather than re-reading
|
|
362
|
+
# config/shakapacker.yml here, so this guidance can never disagree with the bundler the
|
|
363
|
+
# build actually uses. Instance handles SHAKAPACKER_CONFIG, Env.inquire (Rails.env plus
|
|
364
|
+
# the production fallback), and Configuration's own precedence. Falls back to webpack
|
|
365
|
+
# when the config is missing or unparseable, since migration must not crash on it.
|
|
366
|
+
def assets_bundler
|
|
367
|
+
return @assets_bundler if defined?(@assets_bundler)
|
|
368
|
+
|
|
369
|
+
@assets_bundler = begin
|
|
370
|
+
require "shakapacker"
|
|
371
|
+
Shakapacker::Instance.new(root_path: root_path).config.assets_bundler
|
|
372
|
+
rescue StandardError, LoadError
|
|
373
|
+
"webpack"
|
|
374
|
+
end
|
|
375
|
+
end
|
|
376
|
+
|
|
278
377
|
def create_swc_config
|
|
279
378
|
config_dir = root_path.join("config")
|
|
280
379
|
swc_config_path = config_dir.join("swc.config.js")
|
|
@@ -287,7 +386,7 @@ module Shakapacker
|
|
|
287
386
|
FileUtils.mkdir_p(config_dir) unless config_dir.exist?
|
|
288
387
|
|
|
289
388
|
logger.info "📄 Creating config/swc.config.js..."
|
|
290
|
-
File.write(swc_config_path, DEFAULT_SWC_CONFIG)
|
|
389
|
+
File.write(swc_config_path, rspack? ? RSPACK_SWC_CONFIG : DEFAULT_SWC_CONFIG)
|
|
291
390
|
logger.info "✅ config/swc.config.js created"
|
|
292
391
|
true
|
|
293
392
|
rescue StandardError => e
|
|
@@ -33,7 +33,11 @@ module Shakapacker
|
|
|
33
33
|
[true, "true", "yes", 1, "1", "t"].include?(value.instance_of?(String) ? value.downcase : value)
|
|
34
34
|
end
|
|
35
35
|
|
|
36
|
-
# Executes a string or an array of strings in a shell in the given directory
|
|
36
|
+
# Executes a string or an array of strings in a shell in the given directory.
|
|
37
|
+
# NOTE: this does NOT unbundle. The caller's Bundler environment (BUNDLE_GEMFILE,
|
|
38
|
+
# RUBYOPT, ...) is inherited, so a `bundle` command run here against a different
|
|
39
|
+
# directory's Gemfile still resolves the caller's Gemfile. Wrap the call in
|
|
40
|
+
# Bundler.with_unbundled_env when that matters.
|
|
37
41
|
def self.sh_in_dir(dir, *shell_commands)
|
|
38
42
|
shell_commands.flatten.each { |shell_command| sh %(cd '#{dir}' && #{shell_command.strip}) }
|
|
39
43
|
end
|
data/lib/shakapacker/version.rb
CHANGED
data/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "shakapacker",
|
|
3
|
-
"version": "10.3.
|
|
3
|
+
"version": "10.3.2",
|
|
4
4
|
"description": "Use webpack to manage app-like JavaScript modules in Rails",
|
|
5
5
|
"homepage": "https://github.com/shakacode/shakapacker",
|
|
6
6
|
"bugs": {
|
|
@@ -58,8 +58,8 @@
|
|
|
58
58
|
"@babel/core": "7.29.0",
|
|
59
59
|
"@eslint/eslintrc": "^3.2.0",
|
|
60
60
|
"@eslint/js": "^9.37.0",
|
|
61
|
-
"@rspack/cli": "2.0
|
|
62
|
-
"@rspack/core": "2.0
|
|
61
|
+
"@rspack/cli": "2.2.0",
|
|
62
|
+
"@rspack/core": "2.2.0",
|
|
63
63
|
"@swc/core": "1.15.33",
|
|
64
64
|
"@types/babel__core": "^7.20.5",
|
|
65
65
|
"@types/js-yaml": "^4.0.9",
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: shakapacker
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 10.3.
|
|
4
|
+
version: 10.3.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- David Heinemeier Hansson
|
|
@@ -225,7 +225,7 @@ homepage: https://github.com/shakacode/shakapacker
|
|
|
225
225
|
licenses:
|
|
226
226
|
- MIT
|
|
227
227
|
metadata:
|
|
228
|
-
source_code_uri: https://github.com/shakacode/shakapacker/tree/v10.3.
|
|
228
|
+
source_code_uri: https://github.com/shakacode/shakapacker/tree/v10.3.2
|
|
229
229
|
rdoc_options: []
|
|
230
230
|
require_paths:
|
|
231
231
|
- lib
|
|
@@ -240,7 +240,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
240
240
|
- !ruby/object:Gem::Version
|
|
241
241
|
version: '0'
|
|
242
242
|
requirements: []
|
|
243
|
-
rubygems_version:
|
|
243
|
+
rubygems_version: 4.0.18
|
|
244
244
|
specification_version: 4
|
|
245
245
|
summary: Use webpack to manage app-like JavaScript modules in Rails
|
|
246
246
|
test_files: []
|