shakapacker 10.2.0 → 10.3.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/CHANGELOG.md +15 -1
- data/README.md +2 -1
- data/lib/install/bin/diff-bundler-config +27 -25
- data/lib/install/bin/shakapacker-config +27 -25
- data/lib/install/config/shakapacker.yml +3 -1
- data/lib/install/package.json +1 -1
- data/lib/shakapacker/configuration.rb +157 -38
- data/lib/shakapacker/doctor.rb +65 -13
- data/lib/shakapacker/version.rb +1 -1
- data/package.json +2 -2
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 9066233e8c71edd7018db4b397e132013a8dcde79a111acbd6f3a79617fa9367
|
|
4
|
+
data.tar.gz: 1e7d899486f7bf0c43cebb923ba4a013bd5bdb7e4348193662872a5b77278208
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6becce7cfd7598aeb8b6cb734882e0dbd6668125e61c711608d81e242724c8b27d613efdf5cecff77e737ca46d8f8c5c727938c5bbb13551f3394f7149d495a0
|
|
7
|
+
data.tar.gz: f56d65242942ce8ce7b372af52b28a7a62dd6ce47c7fce5b4268bd638d22691276166796620179682b0b61ad2cc4028d951219d208652f84a99cb60bf0d8757a
|
data/CHANGELOG.md
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
- For the changelog of versions prior to v6, see the [5.x stable branch of rails/webpacker](https://github.com/rails/webpacker/tree/5-x-stable).
|
|
2
|
+
- **Please see the [v10 Upgrade Guide](./docs/v10_upgrade.md) for upgrading to version 10 and accounting for breaking changes.**
|
|
2
3
|
- **Please see the [v9 Upgrade Guide](./docs/v9_upgrade.md) for upgrading to version 9 and accounting for breaking changes.**
|
|
3
4
|
- Please see the [v8 Upgrade Guide](./docs/v8_upgrade.md) for upgrading to version 8 and accounting for breaking changes.
|
|
4
5
|
- Please see the [v7 Upgrade Guide](./docs/v7_upgrade.md) for upgrading to new spelling in version 7.
|
|
@@ -9,6 +10,18 @@
|
|
|
9
10
|
|
|
10
11
|
## [Unreleased]
|
|
11
12
|
|
|
13
|
+
## [v10.3.0] - July 5, 2026
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
|
|
17
|
+
- **Allowed `webpack-dev-server` v6**. [PR #1102](https://github.com/shakacode/shakapacker/pull/1102) by [G-Rath](https://github.com/G-Rath).
|
|
18
|
+
|
|
19
|
+
### Fixed
|
|
20
|
+
|
|
21
|
+
- **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
|
+
- **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 binstubs delegating Node resolution to Ruby `exec` in unset and empty `PATH` environments.** [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` after the `v10.2.0` Ruby-binstub regression, while keeping friendly missing-Node errors for `ENOENT` and `EACCES`.
|
|
24
|
+
|
|
12
25
|
## [v10.2.0] - July 3, 2026
|
|
13
26
|
|
|
14
27
|
### Added
|
|
@@ -973,7 +986,8 @@ Note: [Rubygem is 6.3.0.pre.rc.1](https://rubygems.org/gems/shakapacker/versions
|
|
|
973
986
|
|
|
974
987
|
See [CHANGELOG.md in rails/webpacker (up to v5.4.3)](https://github.com/rails/webpacker/blob/master/CHANGELOG.md)
|
|
975
988
|
|
|
976
|
-
[Unreleased]: https://github.com/shakacode/shakapacker/compare/v10.
|
|
989
|
+
[Unreleased]: https://github.com/shakacode/shakapacker/compare/v10.3.0...main
|
|
990
|
+
[v10.3.0]: https://github.com/shakacode/shakapacker/compare/v10.2.0...v10.3.0
|
|
977
991
|
[v10.2.0]: https://github.com/shakacode/shakapacker/compare/v10.1.0...v10.2.0
|
|
978
992
|
[v10.1.0]: https://github.com/shakacode/shakapacker/compare/v10.0.0...v10.1.0
|
|
979
993
|
[v10.0.0]: https://github.com/shakacode/shakapacker/compare/v9.7.0...v10.0.0
|
data/README.md
CHANGED
|
@@ -114,7 +114,8 @@ and release-to-release upgrade paths.
|
|
|
114
114
|
|
|
115
115
|
Older major-version docs:
|
|
116
116
|
|
|
117
|
-
- [v10
|
|
117
|
+
- [v10 upgrade guide](https://github.com/shakacode/shakapacker/blob/main/docs/v10_upgrade.md)
|
|
118
|
+
([docs site](https://shakapacker.com/docs/v10_upgrade/))
|
|
118
119
|
- [v9 upgrade guide](https://shakapacker.com/docs/v9_upgrade/)
|
|
119
120
|
- [v8 upgrade guide](https://shakapacker.com/docs/v8_upgrade/)
|
|
120
121
|
- [v7 upgrade guide](https://shakapacker.com/docs/v7_upgrade/)
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env ruby
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
|
-
require "rbconfig"
|
|
5
4
|
require "yaml"
|
|
6
5
|
|
|
7
6
|
# This binstub is managed by Shakapacker. Delete it and rerun the install or init command to regenerate it.
|
|
@@ -14,36 +13,39 @@ def shakapacker_app_root
|
|
|
14
13
|
Dir.pwd
|
|
15
14
|
end
|
|
16
15
|
|
|
17
|
-
def
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
*ENV.fetch("PATHEXT", "").split(File::PATH_SEPARATOR)
|
|
21
|
-
].compact.reject(&:empty?)
|
|
22
|
-
return [executable] if extensions.empty? || File.extname(executable) != ""
|
|
16
|
+
def shakapacker_node_binary
|
|
17
|
+
"node"
|
|
18
|
+
end
|
|
23
19
|
|
|
24
|
-
|
|
20
|
+
def shakapacker_warn_missing_node
|
|
21
|
+
warn '[Shakapacker] Could not find Node.js executable "node". ' \
|
|
22
|
+
"Install Node.js and try again."
|
|
23
|
+
exit 1
|
|
25
24
|
end
|
|
26
25
|
|
|
27
|
-
def
|
|
28
|
-
ENV.
|
|
29
|
-
search_path = path.empty? ? Dir.pwd : path
|
|
26
|
+
def shakapacker_exec_env(launch_dir)
|
|
27
|
+
return {} unless ENV.key?("PATH")
|
|
30
28
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
return executable_path if File.file?(executable_path) && File.executable?(executable_path)
|
|
34
|
-
end
|
|
35
|
-
end
|
|
29
|
+
path_entries = ENV["PATH"].split(File::PATH_SEPARATOR, -1)
|
|
30
|
+
path_entries = [""] if path_entries.empty?
|
|
36
31
|
|
|
37
|
-
|
|
32
|
+
normalized_path = path_entries.map do |entry|
|
|
33
|
+
entry.empty? ? launch_dir : File.absolute_path(entry, launch_dir)
|
|
34
|
+
end.join(File::PATH_SEPARATOR)
|
|
35
|
+
|
|
36
|
+
{ "PATH" => normalized_path }
|
|
38
37
|
end
|
|
39
38
|
|
|
40
|
-
def
|
|
41
|
-
|
|
42
|
-
return node_bin if node_bin
|
|
39
|
+
def shakapacker_exec_node(script_path, argv, launch_dir)
|
|
40
|
+
exec_env = shakapacker_exec_env(launch_dir)
|
|
43
41
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
42
|
+
if exec_env.empty?
|
|
43
|
+
exec shakapacker_node_binary, script_path, *argv
|
|
44
|
+
else
|
|
45
|
+
exec exec_env, shakapacker_node_binary, script_path, *argv
|
|
46
|
+
end
|
|
47
|
+
rescue Errno::ENOENT, Errno::EACCES
|
|
48
|
+
shakapacker_warn_missing_node
|
|
47
49
|
end
|
|
48
50
|
|
|
49
51
|
def shakapacker_node_env
|
|
@@ -130,9 +132,9 @@ end
|
|
|
130
132
|
ENV["RAILS_ENV"] ||= ENV["RACK_ENV"] || "development"
|
|
131
133
|
ENV["NODE_ENV"] ||= shakapacker_node_env
|
|
132
134
|
|
|
135
|
+
launch_dir = Dir.pwd
|
|
133
136
|
app_root = shakapacker_app_root
|
|
134
137
|
client_root = shakapacker_client_root(app_root)
|
|
135
|
-
node_bin = shakapacker_node_binary
|
|
136
138
|
script_paths = shakapacker_package_script_paths(app_root, client_root, "diff-bundler-config.cjs")
|
|
137
139
|
script_path = script_paths.find { |path| File.file?(path) }
|
|
138
140
|
|
|
@@ -142,5 +144,5 @@ unless script_path
|
|
|
142
144
|
end
|
|
143
145
|
|
|
144
146
|
Dir.chdir(app_root) do
|
|
145
|
-
|
|
147
|
+
shakapacker_exec_node(script_path, ARGV, launch_dir)
|
|
146
148
|
end
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env ruby
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
|
-
require "rbconfig"
|
|
5
4
|
require "yaml"
|
|
6
5
|
|
|
7
6
|
# This binstub is managed by Shakapacker. Delete it and rerun the install or init command to regenerate it.
|
|
@@ -14,36 +13,39 @@ def shakapacker_app_root
|
|
|
14
13
|
Dir.pwd
|
|
15
14
|
end
|
|
16
15
|
|
|
17
|
-
def
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
*ENV.fetch("PATHEXT", "").split(File::PATH_SEPARATOR)
|
|
21
|
-
].compact.reject(&:empty?)
|
|
22
|
-
return [executable] if extensions.empty? || File.extname(executable) != ""
|
|
16
|
+
def shakapacker_node_binary
|
|
17
|
+
"node"
|
|
18
|
+
end
|
|
23
19
|
|
|
24
|
-
|
|
20
|
+
def shakapacker_warn_missing_node
|
|
21
|
+
warn '[Shakapacker] Could not find Node.js executable "node". ' \
|
|
22
|
+
"Install Node.js and try again."
|
|
23
|
+
exit 1
|
|
25
24
|
end
|
|
26
25
|
|
|
27
|
-
def
|
|
28
|
-
ENV.
|
|
29
|
-
search_path = path.empty? ? Dir.pwd : path
|
|
26
|
+
def shakapacker_exec_env(launch_dir)
|
|
27
|
+
return {} unless ENV.key?("PATH")
|
|
30
28
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
return executable_path if File.file?(executable_path) && File.executable?(executable_path)
|
|
34
|
-
end
|
|
35
|
-
end
|
|
29
|
+
path_entries = ENV["PATH"].split(File::PATH_SEPARATOR, -1)
|
|
30
|
+
path_entries = [""] if path_entries.empty?
|
|
36
31
|
|
|
37
|
-
|
|
32
|
+
normalized_path = path_entries.map do |entry|
|
|
33
|
+
entry.empty? ? launch_dir : File.absolute_path(entry, launch_dir)
|
|
34
|
+
end.join(File::PATH_SEPARATOR)
|
|
35
|
+
|
|
36
|
+
{ "PATH" => normalized_path }
|
|
38
37
|
end
|
|
39
38
|
|
|
40
|
-
def
|
|
41
|
-
|
|
42
|
-
return node_bin if node_bin
|
|
39
|
+
def shakapacker_exec_node(script_path, argv, launch_dir)
|
|
40
|
+
exec_env = shakapacker_exec_env(launch_dir)
|
|
43
41
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
42
|
+
if exec_env.empty?
|
|
43
|
+
exec shakapacker_node_binary, script_path, *argv
|
|
44
|
+
else
|
|
45
|
+
exec exec_env, shakapacker_node_binary, script_path, *argv
|
|
46
|
+
end
|
|
47
|
+
rescue Errno::ENOENT, Errno::EACCES
|
|
48
|
+
shakapacker_warn_missing_node
|
|
47
49
|
end
|
|
48
50
|
|
|
49
51
|
def shakapacker_node_env
|
|
@@ -130,9 +132,9 @@ end
|
|
|
130
132
|
ENV["RAILS_ENV"] ||= ENV["RACK_ENV"] || "development"
|
|
131
133
|
ENV["NODE_ENV"] ||= shakapacker_node_env
|
|
132
134
|
|
|
135
|
+
launch_dir = Dir.pwd
|
|
133
136
|
app_root = shakapacker_app_root
|
|
134
137
|
client_root = shakapacker_client_root(app_root)
|
|
135
|
-
node_bin = shakapacker_node_binary
|
|
136
138
|
script_paths = shakapacker_package_script_paths(app_root, client_root, "shakapacker-config.cjs")
|
|
137
139
|
script_path = script_paths.find { |path| File.file?(path) }
|
|
138
140
|
|
|
@@ -142,5 +144,5 @@ unless script_path
|
|
|
142
144
|
end
|
|
143
145
|
|
|
144
146
|
Dir.chdir(app_root) do
|
|
145
|
-
|
|
147
|
+
shakapacker_exec_node(script_path, ARGV, launch_dir)
|
|
146
148
|
end
|
|
@@ -59,7 +59,9 @@ default: &default
|
|
|
59
59
|
cache_manifest: false
|
|
60
60
|
|
|
61
61
|
# Select JavaScript transpiler to use
|
|
62
|
-
# Available options: 'swc' (default
|
|
62
|
+
# Available options: 'swc' (bundled default), 'babel', 'esbuild', or 'none'
|
|
63
|
+
# Webpack apps that omit this setting use the bundled SWC default when swc-loader is
|
|
64
|
+
# installed, but fall back to Babel with a warning when only Babel tooling is present.
|
|
63
65
|
# Use 'none' when providing a completely custom webpack configuration
|
|
64
66
|
# Note: When using rspack, swc is used automatically regardless of this setting
|
|
65
67
|
javascript_transpiler: "swc"
|
data/lib/install/package.json
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"webpack": "^5.101.0",
|
|
12
12
|
"webpack-assets-manifest": "^5.0.6 || ^6.0.0",
|
|
13
13
|
"webpack-cli": "^4.9.2 || ^5.0.0 || ^6.0.0 || ^7.0.0",
|
|
14
|
-
"webpack-dev-server": "^5.2.2",
|
|
14
|
+
"webpack-dev-server": "^5.2.2 || ^6.0.0",
|
|
15
15
|
"webpack-merge": "^5.8.0 || ^6.0.0",
|
|
16
16
|
"webpack-subresource-integrity": "^5.1.0"
|
|
17
17
|
},
|
|
@@ -50,6 +50,13 @@ class Shakapacker::Configuration
|
|
|
50
50
|
/\A(?:--config|-c|--node-env|--nodeEnv|--bundler|--build|--init|--list-builds)(?:=.*)?\z/
|
|
51
51
|
private_constant :SHAKAPACKER_MANAGED_COMPILE_FLAG_PATTERN
|
|
52
52
|
|
|
53
|
+
IMPLICIT_SWC_BABEL_FALLBACK_WARNING =
|
|
54
|
+
"`javascript_transpiler` is not set in config/shakapacker.yml. " \
|
|
55
|
+
"Shakapacker defaults to SWC, but swc-loader is not installed and Babel was detected, so Babel will be used. " \
|
|
56
|
+
"Set `javascript_transpiler: babel` (or `swc`) explicitly to silence this message. " \
|
|
57
|
+
"See https://github.com/shakacode/shakapacker/blob/main/docs/transpiler-migration.md"
|
|
58
|
+
private_constant :IMPLICIT_SWC_BABEL_FALLBACK_WARNING
|
|
59
|
+
|
|
53
60
|
DISALLOWED_WEBPACK_COMPILE_FLAGS =
|
|
54
61
|
(SHAKAPACKER_NODE_FLAGS + SHAKAPACKER_RUNNER_COMMANDS + SHAKAPACKER_WATCH_FLAGS +
|
|
55
62
|
SHAKAPACKER_MANAGED_COMPILE_FLAGS).freeze
|
|
@@ -357,24 +364,54 @@ class Shakapacker::Configuration
|
|
|
357
364
|
# Resolution order:
|
|
358
365
|
# 1. javascript_transpiler setting in config file
|
|
359
366
|
# 2. webpack_loader setting in config file (deprecated)
|
|
360
|
-
# 3.
|
|
367
|
+
# 3. Bundled defaults
|
|
368
|
+
# 4. Babel fallback for implicit webpack/SWC defaults when swc-loader is missing
|
|
361
369
|
#
|
|
362
370
|
# Validates that the configured transpiler matches installed packages.
|
|
363
371
|
#
|
|
364
372
|
# @return [String] "babel", "swc", or "esbuild"
|
|
365
373
|
def javascript_transpiler
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
374
|
+
return @javascript_transpiler if defined?(@javascript_transpiler)
|
|
375
|
+
|
|
376
|
+
@javascript_transpiler =
|
|
377
|
+
begin
|
|
378
|
+
javascript_transpiler_configured = config_value_configured?(:javascript_transpiler)
|
|
379
|
+
webpack_loader_configured = config_value_present?(:webpack_loader)
|
|
380
|
+
|
|
381
|
+
# Show deprecation warning if using old 'webpack_loader' key
|
|
382
|
+
if webpack_loader_configured && !javascript_transpiler_configured
|
|
383
|
+
$stderr.puts "⚠️ DEPRECATION WARNING: The 'webpack_loader' configuration option is deprecated. Please use 'javascript_transpiler' instead as it better reflects its purpose of configuring JavaScript transpilation regardless of the bundler used."
|
|
384
|
+
end
|
|
385
|
+
|
|
386
|
+
# Use explicit config if set, otherwise default based on bundler
|
|
387
|
+
current_javascript_transpiler =
|
|
388
|
+
if javascript_transpiler_configured
|
|
389
|
+
fetch(:javascript_transpiler)
|
|
390
|
+
elsif data.has_key?(:javascript_transpiler)
|
|
391
|
+
defaults[:javascript_transpiler]
|
|
392
|
+
else
|
|
393
|
+
fetch(:javascript_transpiler)
|
|
394
|
+
end
|
|
395
|
+
|
|
396
|
+
transpiler =
|
|
397
|
+
if webpack_loader_configured && !javascript_transpiler_configured
|
|
398
|
+
fetch(:webpack_loader) || default_javascript_transpiler
|
|
399
|
+
else
|
|
400
|
+
current_javascript_transpiler || fetch(:webpack_loader) || default_javascript_transpiler
|
|
401
|
+
end
|
|
370
402
|
|
|
371
|
-
|
|
372
|
-
|
|
403
|
+
if !javascript_transpiler_configured &&
|
|
404
|
+
!webpack_loader_configured &&
|
|
405
|
+
implicit_swc_to_babel_fallback?(transpiler)
|
|
406
|
+
$stderr.puts IMPLICIT_SWC_BABEL_FALLBACK_WARNING
|
|
407
|
+
transpiler = "babel"
|
|
408
|
+
end
|
|
373
409
|
|
|
374
|
-
|
|
375
|
-
|
|
410
|
+
# Validate transpiler configuration
|
|
411
|
+
validate_transpiler_configuration(transpiler) unless self.class.installing
|
|
376
412
|
|
|
377
|
-
|
|
413
|
+
transpiler
|
|
414
|
+
end
|
|
378
415
|
end
|
|
379
416
|
|
|
380
417
|
# Deprecated alias for {#javascript_transpiler}
|
|
@@ -461,42 +498,124 @@ class Shakapacker::Configuration
|
|
|
461
498
|
rspack? ? "swc" : "babel"
|
|
462
499
|
end
|
|
463
500
|
|
|
501
|
+
def implicit_swc_to_babel_fallback?(transpiler)
|
|
502
|
+
webpack? &&
|
|
503
|
+
transpiler == "swc" &&
|
|
504
|
+
!package_dependency?("swc-loader") &&
|
|
505
|
+
package_dependency?("babel-loader")
|
|
506
|
+
end
|
|
507
|
+
|
|
508
|
+
def package_dependency?(package_name)
|
|
509
|
+
declared_package_dependencies.key?(package_name)
|
|
510
|
+
end
|
|
511
|
+
|
|
512
|
+
def config_value_present?(key)
|
|
513
|
+
return false unless data.has_key?(key)
|
|
514
|
+
|
|
515
|
+
value = data[key]
|
|
516
|
+
value.is_a?(String) && !value.strip.empty?
|
|
517
|
+
end
|
|
518
|
+
|
|
519
|
+
def config_value_configured?(key)
|
|
520
|
+
return false unless data.has_key?(key)
|
|
521
|
+
|
|
522
|
+
value = data[key]
|
|
523
|
+
return false if value.nil?
|
|
524
|
+
return false if value.is_a?(String) && value.strip.empty?
|
|
525
|
+
|
|
526
|
+
true
|
|
527
|
+
end
|
|
528
|
+
|
|
529
|
+
def declared_package_dependencies
|
|
530
|
+
return @declared_package_dependencies if defined?(@declared_package_dependencies)
|
|
531
|
+
|
|
532
|
+
@declared_package_dependencies =
|
|
533
|
+
package_json_paths.reverse_each.each_with_object({}) do |path, dependencies|
|
|
534
|
+
package_json = parse_package_json(path)
|
|
535
|
+
next unless package_json
|
|
536
|
+
|
|
537
|
+
dependencies.merge!(installable_package_dependencies(package_json))
|
|
538
|
+
end
|
|
539
|
+
end
|
|
540
|
+
|
|
541
|
+
def installable_package_dependencies(package_json)
|
|
542
|
+
(package_json["optionalDependencies"] || {})
|
|
543
|
+
.merge(package_json["devDependencies"] || {})
|
|
544
|
+
.merge(package_json["dependencies"] || {})
|
|
545
|
+
end
|
|
546
|
+
|
|
547
|
+
def package_json_paths
|
|
548
|
+
@package_json_paths ||= package_root_paths
|
|
549
|
+
.map { |path| path.join("package.json") }
|
|
550
|
+
.select(&:exist?)
|
|
551
|
+
end
|
|
552
|
+
|
|
553
|
+
def parse_package_json(path)
|
|
554
|
+
JSON.parse(File.read(path))
|
|
555
|
+
rescue JSON::ParserError, SystemCallError
|
|
556
|
+
nil
|
|
557
|
+
end
|
|
558
|
+
|
|
559
|
+
def package_root_paths
|
|
560
|
+
@package_root_paths ||= [javascript_package_root_path, root_path].uniq
|
|
561
|
+
end
|
|
562
|
+
|
|
563
|
+
def javascript_package_root_path
|
|
564
|
+
@javascript_package_root_path ||= begin
|
|
565
|
+
resolved_source_path = source_path.expand_path
|
|
566
|
+
app_root = root_path.expand_path
|
|
567
|
+
|
|
568
|
+
if path_within?(resolved_source_path, app_root)
|
|
569
|
+
current = resolved_source_path
|
|
570
|
+
loop do
|
|
571
|
+
break current if current.join("package.json").exist?
|
|
572
|
+
break root_path if current == app_root
|
|
573
|
+
|
|
574
|
+
parent = current.dirname
|
|
575
|
+
break root_path if parent == current
|
|
576
|
+
|
|
577
|
+
current = parent
|
|
578
|
+
end
|
|
579
|
+
else
|
|
580
|
+
root_path
|
|
581
|
+
end
|
|
582
|
+
rescue StandardError
|
|
583
|
+
root_path
|
|
584
|
+
end
|
|
585
|
+
end
|
|
586
|
+
|
|
587
|
+
def path_within?(path, parent)
|
|
588
|
+
path.to_s == parent.to_s || path.to_s.start_with?("#{parent}#{File::SEPARATOR}")
|
|
589
|
+
end
|
|
590
|
+
|
|
464
591
|
def validate_transpiler_configuration(transpiler)
|
|
465
592
|
return unless ENV["NODE_ENV"] != "test" # Skip validation in test environment
|
|
466
593
|
|
|
467
594
|
# Skip validation if transpiler is set to 'none' (custom webpack config)
|
|
468
595
|
return if transpiler == "none"
|
|
469
596
|
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
return unless package_json_path.exist?
|
|
597
|
+
all_deps = declared_package_dependencies
|
|
598
|
+
return if all_deps.empty?
|
|
473
599
|
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
when "esbuild"
|
|
493
|
-
if !has_esbuild && (has_babel || has_swc)
|
|
494
|
-
other = has_babel ? "Babel" : "SWC"
|
|
495
|
-
warn_transpiler_mismatch("esbuild", "#{other} packages found but esbuild is configured")
|
|
496
|
-
end
|
|
600
|
+
# Check for transpiler mismatch
|
|
601
|
+
has_babel = all_deps.keys.any? { |pkg| pkg.start_with?("@babel/", "babel-") }
|
|
602
|
+
has_swc = all_deps.keys.any? { |pkg| pkg.include?("swc") }
|
|
603
|
+
has_esbuild = all_deps.keys.any? { |pkg| pkg.include?("esbuild") }
|
|
604
|
+
|
|
605
|
+
case transpiler
|
|
606
|
+
when "babel"
|
|
607
|
+
if !has_babel && has_swc
|
|
608
|
+
warn_transpiler_mismatch("Babel", "SWC packages found but Babel is configured")
|
|
609
|
+
end
|
|
610
|
+
when "swc"
|
|
611
|
+
if !has_swc && has_babel
|
|
612
|
+
warn_transpiler_mismatch("SWC", "Babel packages found but SWC is configured")
|
|
613
|
+
end
|
|
614
|
+
when "esbuild"
|
|
615
|
+
if !has_esbuild && (has_babel || has_swc)
|
|
616
|
+
other = has_babel ? "Babel" : "SWC"
|
|
617
|
+
warn_transpiler_mismatch("esbuild", "#{other} packages found but esbuild is configured")
|
|
497
618
|
end
|
|
498
|
-
rescue JSON::ParserError
|
|
499
|
-
# Ignore if package.json is malformed
|
|
500
619
|
end
|
|
501
620
|
end
|
|
502
621
|
|
data/lib/shakapacker/doctor.rb
CHANGED
|
@@ -511,12 +511,14 @@ module Shakapacker
|
|
|
511
511
|
|
|
512
512
|
def check_javascript_transpiler_dependencies
|
|
513
513
|
transpiler = explicit_javascript_transpiler
|
|
514
|
+
implicit_babel_fallback = false
|
|
514
515
|
|
|
515
516
|
if transpiler.nil?
|
|
516
|
-
|
|
517
|
-
|
|
517
|
+
transpiler = javascript_transpiler
|
|
518
|
+
implicit_babel_fallback = transpiler == "babel"
|
|
518
519
|
end
|
|
519
520
|
|
|
521
|
+
@resolved_javascript_transpiler = transpiler
|
|
520
522
|
return if transpiler == "none"
|
|
521
523
|
|
|
522
524
|
bundler = assets_bundler
|
|
@@ -541,7 +543,7 @@ module Shakapacker
|
|
|
541
543
|
case transpiler
|
|
542
544
|
when "babel"
|
|
543
545
|
check_babel_dependencies
|
|
544
|
-
check_babel_performance_suggestion
|
|
546
|
+
check_babel_performance_suggestion unless implicit_babel_fallback
|
|
545
547
|
when "swc"
|
|
546
548
|
check_swc_dependencies(bundler) unless inferred_hybrid_graph
|
|
547
549
|
when "esbuild"
|
|
@@ -573,6 +575,20 @@ module Shakapacker
|
|
|
573
575
|
@info << "Consider switching to SWC for 20x faster compilation. Set javascript_transpiler: 'swc' in shakapacker.yml"
|
|
574
576
|
end
|
|
575
577
|
|
|
578
|
+
def implicit_javascript_transpiler
|
|
579
|
+
if assets_bundler == "webpack" && !package_installed?("swc-loader") && package_installed?("babel-loader")
|
|
580
|
+
@info << "`javascript_transpiler` is not set in config/shakapacker.yml. " \
|
|
581
|
+
"Shakapacker defaults to SWC, but swc-loader is not installed and Babel was detected, so Babel will be used. " \
|
|
582
|
+
"Set `javascript_transpiler: babel` (or `swc`) explicitly to silence this message. " \
|
|
583
|
+
"See https://github.com/shakacode/shakapacker/blob/main/docs/transpiler-migration.md"
|
|
584
|
+
"babel"
|
|
585
|
+
else
|
|
586
|
+
@info << "No javascript_transpiler configured - using bundled SWC default. " \
|
|
587
|
+
"Set javascript_transpiler: 'swc' or 'babel' explicitly in shakapacker.yml to silence this message."
|
|
588
|
+
"swc"
|
|
589
|
+
end
|
|
590
|
+
end
|
|
591
|
+
|
|
576
592
|
def check_swc_dependencies(bundler)
|
|
577
593
|
if bundler == "webpack"
|
|
578
594
|
unless package_installed?("@swc/core")
|
|
@@ -1271,13 +1287,20 @@ module Shakapacker
|
|
|
1271
1287
|
|
|
1272
1288
|
def javascript_transpiler_configured?
|
|
1273
1289
|
!javascript_transpiler_env_override.nil? ||
|
|
1274
|
-
|
|
1275
|
-
|
|
1290
|
+
config_key_configured?(:javascript_transpiler) ||
|
|
1291
|
+
config_key_present?(:webpack_loader)
|
|
1276
1292
|
end
|
|
1277
1293
|
|
|
1278
1294
|
def javascript_transpiler
|
|
1279
|
-
|
|
1280
|
-
|
|
1295
|
+
return @resolved_javascript_transpiler if defined?(@resolved_javascript_transpiler)
|
|
1296
|
+
|
|
1297
|
+
@resolved_javascript_transpiler =
|
|
1298
|
+
if javascript_transpiler_configured?
|
|
1299
|
+
transpiler = javascript_transpiler_env_override || config.javascript_transpiler
|
|
1300
|
+
blank_config_value?(transpiler) ? default_javascript_transpiler : transpiler
|
|
1301
|
+
else
|
|
1302
|
+
implicit_javascript_transpiler
|
|
1303
|
+
end
|
|
1281
1304
|
end
|
|
1282
1305
|
|
|
1283
1306
|
def explicit_javascript_transpiler
|
|
@@ -1329,7 +1352,7 @@ module Shakapacker
|
|
|
1329
1352
|
end
|
|
1330
1353
|
|
|
1331
1354
|
def blank_config_value?(value)
|
|
1332
|
-
value.nil? || (value.respond_to?(:empty?) && value.empty?)
|
|
1355
|
+
value.nil? || (value.is_a?(String) && value.strip.empty?) || (value.respond_to?(:empty?) && value.empty?)
|
|
1333
1356
|
end
|
|
1334
1357
|
|
|
1335
1358
|
def default_javascript_transpiler
|
|
@@ -1337,14 +1360,15 @@ module Shakapacker
|
|
|
1337
1360
|
end
|
|
1338
1361
|
|
|
1339
1362
|
def config_key_present?(key)
|
|
1340
|
-
|
|
1363
|
+
value = config_value(key)
|
|
1364
|
+
value.is_a?(String) && !value.strip.empty?
|
|
1341
1365
|
end
|
|
1342
1366
|
|
|
1343
|
-
def
|
|
1367
|
+
def config_key_configured?(key)
|
|
1344
1368
|
return false unless config.respond_to?(:data)
|
|
1345
1369
|
|
|
1346
1370
|
data = config.data
|
|
1347
|
-
data.respond_to?(:key?) && data.key?(key)
|
|
1371
|
+
data.respond_to?(:key?) && data.key?(key) && !blank_config_value?(data[key])
|
|
1348
1372
|
end
|
|
1349
1373
|
|
|
1350
1374
|
def config_value(key)
|
|
@@ -1383,7 +1407,7 @@ module Shakapacker
|
|
|
1383
1407
|
if path_within?(source_path, app_root)
|
|
1384
1408
|
current = source_path
|
|
1385
1409
|
loop do
|
|
1386
|
-
break current if
|
|
1410
|
+
break current if current.join("package.json").exist?
|
|
1387
1411
|
break root_path if current == app_root
|
|
1388
1412
|
|
|
1389
1413
|
parent = current.dirname
|
|
@@ -1458,7 +1482,7 @@ module Shakapacker
|
|
|
1458
1482
|
def detect_package_manager
|
|
1459
1483
|
root_package_manager = package_manager_for(root_path)
|
|
1460
1484
|
|
|
1461
|
-
|
|
1485
|
+
package_manager_root_paths.each do |package_root|
|
|
1462
1486
|
next if package_root == root_path
|
|
1463
1487
|
|
|
1464
1488
|
package_manager_name = package_manager_for(package_root)
|
|
@@ -1478,6 +1502,34 @@ module Shakapacker
|
|
|
1478
1502
|
nil
|
|
1479
1503
|
end
|
|
1480
1504
|
|
|
1505
|
+
def package_manager_root_paths
|
|
1506
|
+
@package_manager_root_paths ||= [javascript_package_manager_root_path, root_path].uniq
|
|
1507
|
+
end
|
|
1508
|
+
|
|
1509
|
+
def javascript_package_manager_root_path
|
|
1510
|
+
@javascript_package_manager_root_path ||= begin
|
|
1511
|
+
source_path = config.source_path.expand_path
|
|
1512
|
+
app_root = root_path.expand_path
|
|
1513
|
+
|
|
1514
|
+
if path_within?(source_path, app_root)
|
|
1515
|
+
current = source_path
|
|
1516
|
+
loop do
|
|
1517
|
+
break current if package_root_marker?(current)
|
|
1518
|
+
break root_path if current == app_root
|
|
1519
|
+
|
|
1520
|
+
parent = current.dirname
|
|
1521
|
+
break root_path if parent == current
|
|
1522
|
+
|
|
1523
|
+
current = parent
|
|
1524
|
+
end
|
|
1525
|
+
else
|
|
1526
|
+
root_path
|
|
1527
|
+
end
|
|
1528
|
+
rescue StandardError
|
|
1529
|
+
root_path
|
|
1530
|
+
end
|
|
1531
|
+
end
|
|
1532
|
+
|
|
1481
1533
|
def versions_compatible?(gem_version, npm_version)
|
|
1482
1534
|
# Handle pre-release versions and ranges properly
|
|
1483
1535
|
npm_clean = npm_version.gsub(/[\^~]/, "")
|
data/lib/shakapacker/version.rb
CHANGED
data/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "shakapacker",
|
|
3
|
-
"version": "10.
|
|
3
|
+
"version": "10.3.0",
|
|
4
4
|
"description": "Use webpack to manage app-like JavaScript modules in Rails",
|
|
5
5
|
"homepage": "https://github.com/shakacode/shakapacker",
|
|
6
6
|
"bugs": {
|
|
@@ -127,7 +127,7 @@
|
|
|
127
127
|
"webpack": "^5.101.0",
|
|
128
128
|
"webpack-assets-manifest": "^5.0.6 || ^6.0.0",
|
|
129
129
|
"webpack-cli": "^4.9.2 || ^5.0.0 || ^6.0.0 || ^7.0.0",
|
|
130
|
-
"webpack-dev-server": "^5.2.2",
|
|
130
|
+
"webpack-dev-server": "^5.2.2 || ^6.0.0",
|
|
131
131
|
"webpack-subresource-integrity": "^5.1.0"
|
|
132
132
|
},
|
|
133
133
|
"peerDependenciesMeta": {
|
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.
|
|
4
|
+
version: 10.3.0
|
|
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.
|
|
228
|
+
source_code_uri: https://github.com/shakacode/shakapacker/tree/v10.3.0
|
|
229
229
|
rdoc_options: []
|
|
230
230
|
require_paths:
|
|
231
231
|
- lib
|