shakapacker 9.3.0.beta.7 → 9.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 +46 -109
- data/Gemfile.lock +1 -1
- data/README.md +53 -2
- data/docs/configuration.md +28 -0
- data/docs/rspack_migration_guide.md +238 -2
- data/docs/troubleshooting.md +21 -21
- data/eslint.config.fast.js +8 -0
- data/eslint.config.js +47 -10
- data/knip.ts +8 -1
- data/lib/install/config/shakapacker.yml +6 -6
- data/lib/shakapacker/configuration.rb +227 -4
- data/lib/shakapacker/dev_server.rb +88 -1
- data/lib/shakapacker/doctor.rb +4 -4
- data/lib/shakapacker/instance.rb +85 -1
- data/lib/shakapacker/manifest.rb +85 -11
- data/lib/shakapacker/version.rb +1 -1
- data/lib/shakapacker.rb +143 -3
- data/lib/tasks/shakapacker/doctor.rake +1 -1
- data/lib/tasks/shakapacker/export_bundler_config.rake +4 -4
- data/package/config.ts +0 -1
- data/package/configExporter/buildValidator.ts +53 -29
- data/package/configExporter/cli.ts +81 -56
- data/package/configExporter/configFile.ts +33 -26
- data/package/configExporter/types.ts +64 -0
- data/package/configExporter/yamlSerializer.ts +118 -43
- data/package/dev_server.ts +2 -1
- data/package/env.ts +1 -1
- data/package/environments/base.ts +4 -4
- data/package/environments/development.ts +7 -6
- data/package/environments/production.ts +6 -7
- data/package/environments/test.ts +2 -1
- data/package/index.ts +28 -4
- data/package/loaders.d.ts +2 -2
- data/package/optimization/webpack.ts +29 -31
- data/package/rspack/index.ts +2 -1
- data/package/rules/file.ts +1 -0
- data/package/rules/jscommon.ts +1 -0
- data/package/utils/helpers.ts +0 -1
- data/package/utils/pathValidation.ts +68 -7
- data/package/utils/requireOrError.ts +10 -2
- data/package/utils/typeGuards.ts +43 -46
- data/package/webpack-types.d.ts +2 -2
- data/package/webpackDevServerConfig.ts +1 -0
- data/package.json +2 -3
- data/test/package/configExporter/cli.test.js +440 -0
- data/test/package/configExporter/types.test.js +163 -0
- data/test/package/configExporter.test.js +264 -0
- data/test/package/yamlSerializer.test.js +204 -0
- data/test/typescript/pathValidation.test.js +44 -0
- data/test/typescript/requireOrError.test.js +49 -0
- data/yarn.lock +0 -32
- metadata +11 -5
- data/.eslintrc.fast.js +0 -40
- data/.eslintrc.js +0 -84
|
@@ -1,16 +1,50 @@
|
|
|
1
|
+
# Development server status and configuration
|
|
2
|
+
#
|
|
3
|
+
# Provides methods to query the status and configuration of the webpack-dev-server
|
|
4
|
+
# or rspack-dev-server. This includes checking if the server is running, accessing
|
|
5
|
+
# its host/port, and querying features like HMR (Hot Module Replacement).
|
|
6
|
+
#
|
|
7
|
+
# The dev server runs during development to provide live reloading and hot module
|
|
8
|
+
# replacement. In production, the dev server is not used.
|
|
9
|
+
#
|
|
10
|
+
# @example Checking dev server status
|
|
11
|
+
# dev_server = Shakapacker.dev_server
|
|
12
|
+
# dev_server.running?
|
|
13
|
+
# #=> true
|
|
14
|
+
# dev_server.host_with_port
|
|
15
|
+
# #=> "localhost:3035"
|
|
16
|
+
# dev_server.hmr?
|
|
17
|
+
# #=> true
|
|
18
|
+
#
|
|
19
|
+
# @see Shakapacker::DevServerRunner
|
|
1
20
|
class Shakapacker::DevServer
|
|
21
|
+
# Default environment variable prefix for dev server settings
|
|
2
22
|
DEFAULT_ENV_PREFIX = "SHAKAPACKER_DEV_SERVER".freeze
|
|
3
23
|
|
|
4
24
|
# Configure dev server connection timeout (in seconds), default: 0.1
|
|
5
|
-
#
|
|
25
|
+
# @example
|
|
26
|
+
# Shakapacker::DevServer.connect_timeout = 1
|
|
27
|
+
# @return [Float] the connection timeout in seconds
|
|
6
28
|
cattr_accessor(:connect_timeout) { 0.1 }
|
|
7
29
|
|
|
30
|
+
# The Shakapacker configuration
|
|
31
|
+
# @return [Shakapacker::Configuration] the configuration
|
|
8
32
|
attr_reader :config
|
|
9
33
|
|
|
34
|
+
# Creates a new dev server instance
|
|
35
|
+
#
|
|
36
|
+
# @param config [Shakapacker::Configuration] the Shakapacker configuration
|
|
37
|
+
# @return [Shakapacker::DevServer] the new dev server instance
|
|
10
38
|
def initialize(config)
|
|
11
39
|
@config = config
|
|
12
40
|
end
|
|
13
41
|
|
|
42
|
+
# Returns whether the dev server is currently running
|
|
43
|
+
#
|
|
44
|
+
# Checks by attempting to open a TCP connection to the configured host and port.
|
|
45
|
+
# Returns false if the connection fails or if dev server is not configured.
|
|
46
|
+
#
|
|
47
|
+
# @return [Boolean] true if the dev server is running
|
|
14
48
|
def running?
|
|
15
49
|
if config.dev_server.present?
|
|
16
50
|
Socket.tcp(host, port, connect_timeout: connect_timeout).close
|
|
@@ -22,14 +56,30 @@ class Shakapacker::DevServer
|
|
|
22
56
|
false
|
|
23
57
|
end
|
|
24
58
|
|
|
59
|
+
# Returns the dev server host
|
|
60
|
+
#
|
|
61
|
+
# Can be overridden via SHAKAPACKER_DEV_SERVER_HOST environment variable.
|
|
62
|
+
#
|
|
63
|
+
# @return [String] the host (e.g., "localhost", "0.0.0.0")
|
|
25
64
|
def host
|
|
26
65
|
fetch(:host)
|
|
27
66
|
end
|
|
28
67
|
|
|
68
|
+
# Returns the dev server port
|
|
69
|
+
#
|
|
70
|
+
# Can be overridden via SHAKAPACKER_DEV_SERVER_PORT environment variable.
|
|
71
|
+
#
|
|
72
|
+
# @return [Integer] the port number (typically 3035)
|
|
29
73
|
def port
|
|
30
74
|
fetch(:port)
|
|
31
75
|
end
|
|
32
76
|
|
|
77
|
+
# Returns the server type (http or https)
|
|
78
|
+
#
|
|
79
|
+
# Can be overridden via SHAKAPACKER_DEV_SERVER_SERVER environment variable.
|
|
80
|
+
# Validates that the value is "http" or "https", falling back to "http" if invalid.
|
|
81
|
+
#
|
|
82
|
+
# @return [String] "http" or "https"
|
|
33
83
|
def server
|
|
34
84
|
server_value = fetch(:server)
|
|
35
85
|
server_type = server_value.is_a?(Hash) ? server_value[:type] : server_value
|
|
@@ -49,24 +99,55 @@ class Shakapacker::DevServer
|
|
|
49
99
|
"http"
|
|
50
100
|
end
|
|
51
101
|
|
|
102
|
+
# Returns the protocol for the dev server
|
|
103
|
+
#
|
|
104
|
+
# This is an alias that returns "https" if server is "https", otherwise "http".
|
|
105
|
+
#
|
|
106
|
+
# @return [String] "http" or "https"
|
|
52
107
|
def protocol
|
|
53
108
|
return "https" if server == "https"
|
|
54
109
|
|
|
55
110
|
"http"
|
|
56
111
|
end
|
|
57
112
|
|
|
113
|
+
# Returns the host and port as a single string
|
|
114
|
+
#
|
|
115
|
+
# @return [String] the host:port combination (e.g., "localhost:3035")
|
|
116
|
+
# @example
|
|
117
|
+
# dev_server.host_with_port
|
|
118
|
+
# #=> "localhost:3035"
|
|
58
119
|
def host_with_port
|
|
59
120
|
"#{host}:#{port}"
|
|
60
121
|
end
|
|
61
122
|
|
|
123
|
+
# Returns whether pretty output is enabled
|
|
124
|
+
#
|
|
125
|
+
# When true, the dev server produces prettier, more readable output.
|
|
126
|
+
# Can be overridden via SHAKAPACKER_DEV_SERVER_PRETTY environment variable.
|
|
127
|
+
#
|
|
128
|
+
# @return [Boolean] true if pretty output is enabled
|
|
62
129
|
def pretty?
|
|
63
130
|
fetch(:pretty)
|
|
64
131
|
end
|
|
65
132
|
|
|
133
|
+
# Returns whether Hot Module Replacement (HMR) is enabled
|
|
134
|
+
#
|
|
135
|
+
# When true, the dev server updates modules in the browser without a full
|
|
136
|
+
# page reload, preserving application state.
|
|
137
|
+
# Can be overridden via SHAKAPACKER_DEV_SERVER_HMR environment variable.
|
|
138
|
+
#
|
|
139
|
+
# @return [Boolean] true if HMR is enabled
|
|
66
140
|
def hmr?
|
|
67
141
|
fetch(:hmr)
|
|
68
142
|
end
|
|
69
143
|
|
|
144
|
+
# Returns whether CSS inlining is enabled
|
|
145
|
+
#
|
|
146
|
+
# When true, CSS is injected inline via JavaScript instead of being loaded
|
|
147
|
+
# as separate stylesheet files. This enables HMR for CSS.
|
|
148
|
+
# Can be overridden via SHAKAPACKER_DEV_SERVER_INLINE_CSS environment variable.
|
|
149
|
+
#
|
|
150
|
+
# @return [Boolean] true if CSS should be inlined
|
|
70
151
|
def inline_css?
|
|
71
152
|
case fetch(:inline_css)
|
|
72
153
|
when false, "false"
|
|
@@ -76,6 +157,12 @@ class Shakapacker::DevServer
|
|
|
76
157
|
end
|
|
77
158
|
end
|
|
78
159
|
|
|
160
|
+
# Returns the environment variable prefix for dev server settings
|
|
161
|
+
#
|
|
162
|
+
# Environment variables for dev server settings use this prefix (default: "SHAKAPACKER_DEV_SERVER").
|
|
163
|
+
# For example, SHAKAPACKER_DEV_SERVER_PORT sets the port.
|
|
164
|
+
#
|
|
165
|
+
# @return [String] the env var prefix (typically "SHAKAPACKER_DEV_SERVER")
|
|
79
166
|
def env_prefix
|
|
80
167
|
config.dev_server.fetch(:env_prefix, DEFAULT_ENV_PREFIX)
|
|
81
168
|
end
|
data/lib/shakapacker/doctor.rb
CHANGED
|
@@ -391,7 +391,7 @@ module Shakapacker
|
|
|
391
391
|
expected_binstubs = {
|
|
392
392
|
"bin/shakapacker" => "Main Shakapacker binstub",
|
|
393
393
|
"bin/shakapacker-dev-server" => "Development server binstub",
|
|
394
|
-
"bin/
|
|
394
|
+
"bin/shakapacker-config" => "Config export binstub"
|
|
395
395
|
}
|
|
396
396
|
|
|
397
397
|
expected_binstubs.each do |path, description|
|
|
@@ -1013,7 +1013,7 @@ module Shakapacker
|
|
|
1013
1013
|
binstubs = [
|
|
1014
1014
|
"bin/shakapacker",
|
|
1015
1015
|
"bin/shakapacker-dev-server",
|
|
1016
|
-
"bin/
|
|
1016
|
+
"bin/shakapacker-config"
|
|
1017
1017
|
]
|
|
1018
1018
|
|
|
1019
1019
|
existing_binstubs = binstubs.select { |b| doctor.root_path.join(b).exist? }
|
|
@@ -1171,10 +1171,10 @@ module Shakapacker
|
|
|
1171
1171
|
puts " #{package_manager_install_command(package_manager)}"
|
|
1172
1172
|
puts ""
|
|
1173
1173
|
puts "For debugging configuration issues, export your webpack/rspack config:"
|
|
1174
|
-
puts " bin/
|
|
1174
|
+
puts " bin/shakapacker-config --doctor"
|
|
1175
1175
|
puts " (Exports annotated YAML configs for dev and production - best for troubleshooting)"
|
|
1176
1176
|
puts ""
|
|
1177
|
-
puts " See 'bin/
|
|
1177
|
+
puts " See 'bin/shakapacker-config --help' for more options"
|
|
1178
1178
|
end
|
|
1179
1179
|
|
|
1180
1180
|
def package_manager_install_command(manager)
|
data/lib/shakapacker/instance.rb
CHANGED
|
@@ -1,10 +1,43 @@
|
|
|
1
1
|
require "pathname"
|
|
2
2
|
|
|
3
|
+
# Represents a single instance of Shakapacker configuration and state
|
|
4
|
+
#
|
|
5
|
+
# An instance encapsulates all the configuration, compilation, and manifest
|
|
6
|
+
# lookup functionality for a specific Rails application. Most applications
|
|
7
|
+
# will use the shared instance accessible via {Shakapacker.instance}, but
|
|
8
|
+
# multiple instances can be created for testing or advanced scenarios.
|
|
9
|
+
#
|
|
10
|
+
# @example Using the default instance
|
|
11
|
+
# instance = Shakapacker::Instance.new
|
|
12
|
+
# instance.config.source_path
|
|
13
|
+
# instance.manifest.lookup("application.js")
|
|
14
|
+
#
|
|
15
|
+
# @example Creating an instance with custom paths
|
|
16
|
+
# instance = Shakapacker::Instance.new(
|
|
17
|
+
# root_path: "/path/to/app",
|
|
18
|
+
# config_path: "/custom/config.yml"
|
|
19
|
+
# )
|
|
3
20
|
class Shakapacker::Instance
|
|
21
|
+
# The shared logger used by all Shakapacker instances
|
|
22
|
+
# @return [ActiveSupport::TaggedLogging] the logger
|
|
4
23
|
cattr_accessor(:logger) { ActiveSupport::TaggedLogging.new(ActiveSupport::Logger.new(STDOUT)) }
|
|
5
24
|
|
|
6
|
-
|
|
25
|
+
# The root path of the application
|
|
26
|
+
# @return [Pathname] the application root path
|
|
27
|
+
attr_reader :root_path
|
|
7
28
|
|
|
29
|
+
# The path to the Shakapacker configuration file
|
|
30
|
+
# @return [Pathname] the config file path
|
|
31
|
+
attr_reader :config_path
|
|
32
|
+
|
|
33
|
+
# Creates a new Shakapacker instance
|
|
34
|
+
#
|
|
35
|
+
# @param root_path [String, Pathname, nil] the application root path.
|
|
36
|
+
# Defaults to Rails.root if Rails is defined, otherwise uses current directory
|
|
37
|
+
# @param config_path [String, Pathname, nil] the path to shakapacker.yml.
|
|
38
|
+
# Can also be set via SHAKAPACKER_CONFIG environment variable.
|
|
39
|
+
# Defaults to +config/shakapacker.yml+ within the root_path
|
|
40
|
+
# @return [Shakapacker::Instance] the new instance
|
|
8
41
|
def initialize(root_path: nil, config_path: nil)
|
|
9
42
|
# Use Rails.root if Rails is defined and no root_path is provided
|
|
10
43
|
@root_path = root_path || (defined?(Rails) && Rails&.root) || Pathname.new(Dir.pwd)
|
|
@@ -15,10 +48,23 @@ class Shakapacker::Instance
|
|
|
15
48
|
@config_path = Pathname.new(ENV["SHAKAPACKER_CONFIG"] || config_path || default_config_path)
|
|
16
49
|
end
|
|
17
50
|
|
|
51
|
+
# Returns the current Rails environment as a StringInquirer
|
|
52
|
+
#
|
|
53
|
+
# This allows for convenient environment checking:
|
|
54
|
+
# env.development? # => true/false
|
|
55
|
+
# env.production? # => true/false
|
|
56
|
+
#
|
|
57
|
+
# @return [ActiveSupport::StringInquirer] the environment
|
|
18
58
|
def env
|
|
19
59
|
@env ||= Shakapacker::Env.inquire self
|
|
20
60
|
end
|
|
21
61
|
|
|
62
|
+
# Returns the configuration object for this instance
|
|
63
|
+
#
|
|
64
|
+
# The configuration is loaded from the shakapacker.yml file and provides
|
|
65
|
+
# access to all settings like source paths, output paths, and compilation options.
|
|
66
|
+
#
|
|
67
|
+
# @return [Shakapacker::Configuration] the configuration
|
|
22
68
|
def config
|
|
23
69
|
@config ||= Shakapacker::Configuration.new(
|
|
24
70
|
root_path: root_path,
|
|
@@ -27,26 +73,64 @@ class Shakapacker::Instance
|
|
|
27
73
|
)
|
|
28
74
|
end
|
|
29
75
|
|
|
76
|
+
# Returns the compiler strategy for determining staleness
|
|
77
|
+
#
|
|
78
|
+
# The strategy (mtime or digest) determines how Shakapacker decides whether
|
|
79
|
+
# assets need recompilation.
|
|
80
|
+
#
|
|
81
|
+
# @return [Shakapacker::CompilerStrategy] the compiler strategy
|
|
82
|
+
# @api private
|
|
30
83
|
def strategy
|
|
31
84
|
@strategy ||= Shakapacker::CompilerStrategy.from_config
|
|
32
85
|
end
|
|
33
86
|
|
|
87
|
+
# Returns the compiler for this instance
|
|
88
|
+
#
|
|
89
|
+
# The compiler is responsible for executing webpack/rspack to compile assets.
|
|
90
|
+
#
|
|
91
|
+
# @return [Shakapacker::Compiler] the compiler
|
|
34
92
|
def compiler
|
|
35
93
|
@compiler ||= Shakapacker::Compiler.new self
|
|
36
94
|
end
|
|
37
95
|
|
|
96
|
+
# Returns the development server instance
|
|
97
|
+
#
|
|
98
|
+
# The dev server instance can query the status of the webpack-dev-server,
|
|
99
|
+
# including whether it's running, its host/port, and configuration.
|
|
100
|
+
#
|
|
101
|
+
# @return [Shakapacker::DevServer] the dev server
|
|
38
102
|
def dev_server
|
|
39
103
|
@dev_server ||= Shakapacker::DevServer.new config
|
|
40
104
|
end
|
|
41
105
|
|
|
106
|
+
# Returns the manifest for looking up compiled assets
|
|
107
|
+
#
|
|
108
|
+
# The manifest reads the manifest.json file produced by webpack/rspack
|
|
109
|
+
# and provides methods to look up the compiled paths for source files.
|
|
110
|
+
#
|
|
111
|
+
# @return [Shakapacker::Manifest] the manifest
|
|
42
112
|
def manifest
|
|
43
113
|
@manifest ||= Shakapacker::Manifest.new self
|
|
44
114
|
end
|
|
45
115
|
|
|
116
|
+
# Returns the commands instance for build operations
|
|
117
|
+
#
|
|
118
|
+
# The commands object provides methods for bootstrapping, cleaning,
|
|
119
|
+
# clobbering, and compiling assets.
|
|
120
|
+
#
|
|
121
|
+
# @return [Shakapacker::Commands] the commands
|
|
46
122
|
def commands
|
|
47
123
|
@commands ||= Shakapacker::Commands.new self
|
|
48
124
|
end
|
|
49
125
|
|
|
126
|
+
# Returns whether CSS should be inlined by the dev server
|
|
127
|
+
#
|
|
128
|
+
# CSS inlining is enabled when:
|
|
129
|
+
# - The dev server has inline_css enabled
|
|
130
|
+
# - Hot Module Replacement (HMR) is enabled
|
|
131
|
+
# - The dev server is currently running
|
|
132
|
+
#
|
|
133
|
+
# @return [Boolean] true if CSS should be inlined
|
|
50
134
|
def inlining_css?
|
|
51
135
|
dev_server.inline_css? && dev_server.hmr? && dev_server.running?
|
|
52
136
|
end
|
data/lib/shakapacker/manifest.rb
CHANGED
|
@@ -1,23 +1,70 @@
|
|
|
1
|
-
#
|
|
2
|
-
# This allows javascript_pack_tag, stylesheet_pack_tag, asset_pack_path to take a reference to,
|
|
3
|
-
# say, "calendar.js" or "calendar.css" and turn it into "/packs/calendar-1016838bab065ae1e314.js" or
|
|
4
|
-
# "/packs/calendar-1016838bab065ae1e314.css".
|
|
1
|
+
# Manifest for looking up compiled asset paths
|
|
5
2
|
#
|
|
6
|
-
#
|
|
7
|
-
#
|
|
3
|
+
# The manifest reads the +manifest.json+ file produced by webpack/rspack during
|
|
4
|
+
# compilation and provides methods to look up the compiled (digested) paths for
|
|
5
|
+
# source files.
|
|
6
|
+
#
|
|
7
|
+
# This allows view helpers like +javascript_pack_tag+, +stylesheet_pack_tag+, and
|
|
8
|
+
# +asset_pack_path+ to take a reference to a source file (e.g., "calendar.js")
|
|
9
|
+
# and turn it into the compiled path with digest (e.g., "/packs/calendar-1016838bab065ae1e314.js").
|
|
10
|
+
#
|
|
11
|
+
# == Automatic Compilation
|
|
12
|
+
#
|
|
13
|
+
# When the configuration has +compile: true+ in shakapacker.yml, any lookups will
|
|
14
|
+
# automatically trigger compilation if the assets are stale. This is typically
|
|
15
|
+
# enabled in development and disabled in production.
|
|
16
|
+
#
|
|
17
|
+
# == Caching
|
|
18
|
+
#
|
|
19
|
+
# The manifest can cache the loaded data in memory when +cache_manifest: true+ is
|
|
20
|
+
# set in the configuration. This improves performance in production by avoiding
|
|
21
|
+
# repeated file reads.
|
|
22
|
+
#
|
|
23
|
+
# @example Looking up assets
|
|
24
|
+
# manifest = Shakapacker.manifest
|
|
25
|
+
# manifest.lookup("application.js")
|
|
26
|
+
# #=> "/packs/application-abc123.js"
|
|
27
|
+
#
|
|
28
|
+
# manifest.lookup!("missing.js")
|
|
29
|
+
# #=> raises Shakapacker::Manifest::MissingEntryError
|
|
30
|
+
#
|
|
31
|
+
# @see Shakapacker::Helper
|
|
8
32
|
class Shakapacker::Manifest
|
|
33
|
+
# Raised when an asset cannot be found in the manifest
|
|
9
34
|
class MissingEntryError < StandardError; end
|
|
10
35
|
|
|
11
36
|
delegate :config, :compiler, :dev_server, to: :@instance
|
|
12
37
|
|
|
38
|
+
# Creates a new manifest instance
|
|
39
|
+
#
|
|
40
|
+
# @param instance [Shakapacker::Instance] the Shakapacker instance
|
|
41
|
+
# @return [Shakapacker::Manifest] the new manifest
|
|
13
42
|
def initialize(instance)
|
|
14
43
|
@instance = instance
|
|
15
44
|
end
|
|
16
45
|
|
|
46
|
+
# Reloads the manifest data from disk
|
|
47
|
+
#
|
|
48
|
+
# Forces a fresh read of the manifest.json file, bypassing any cache.
|
|
49
|
+
# This is useful when you know the manifest has been updated.
|
|
50
|
+
#
|
|
51
|
+
# @return [Hash] the loaded manifest data
|
|
17
52
|
def refresh
|
|
18
53
|
@data = load
|
|
19
54
|
end
|
|
20
55
|
|
|
56
|
+
# Looks up an entry point with all its chunks (split code)
|
|
57
|
+
#
|
|
58
|
+
# This method is used when you need to load all chunks for a pack that has
|
|
59
|
+
# been split via code splitting. It returns an array of asset paths for the
|
|
60
|
+
# main entry and all its dynamic imports.
|
|
61
|
+
#
|
|
62
|
+
# @param name [String] the entry point name (e.g., "application")
|
|
63
|
+
# @param pack_type [Hash] options hash with :type key (:javascript, :stylesheet, etc.)
|
|
64
|
+
# @return [Array<String>, nil] array of asset paths, or nil if not found
|
|
65
|
+
# @example
|
|
66
|
+
# manifest.lookup_pack_with_chunks("application", type: :javascript)
|
|
67
|
+
# #=> ["/packs/runtime-abc123.js", "/packs/application-def456.js"]
|
|
21
68
|
def lookup_pack_with_chunks(name, pack_type = {})
|
|
22
69
|
compile if compiling?
|
|
23
70
|
|
|
@@ -28,23 +75,50 @@ class Shakapacker::Manifest
|
|
|
28
75
|
nil
|
|
29
76
|
end
|
|
30
77
|
|
|
78
|
+
# Like {#lookup_pack_with_chunks}, but raises an error if not found
|
|
79
|
+
#
|
|
80
|
+
# @param name [String] the entry point name
|
|
81
|
+
# @param pack_type [Hash] options hash with :type key
|
|
82
|
+
# @return [Array<String>] array of asset paths
|
|
83
|
+
# @raise [MissingEntryError] if the entry point is not found in the manifest
|
|
31
84
|
def lookup_pack_with_chunks!(name, pack_type = {})
|
|
32
85
|
lookup_pack_with_chunks(name, pack_type) || handle_missing_entry(name, pack_type)
|
|
33
86
|
end
|
|
34
87
|
|
|
35
|
-
#
|
|
36
|
-
#
|
|
88
|
+
# Looks up the compiled path for a given asset
|
|
89
|
+
#
|
|
90
|
+
# Computes the relative path for a Shakapacker asset using the manifest.json file.
|
|
91
|
+
# If automatic compilation is enabled and the assets are stale, triggers a
|
|
92
|
+
# compilation before looking up the path.
|
|
37
93
|
#
|
|
38
|
-
#
|
|
94
|
+
# @param name [String] the source file name (e.g., "calendar.js" or "calendar")
|
|
95
|
+
# @param pack_type [Hash] options hash with :type key (:javascript, :stylesheet, etc.).
|
|
96
|
+
# If not specified, the extension from the name is used.
|
|
97
|
+
# @return [String, nil] the compiled asset path, or nil if not found
|
|
98
|
+
# @example
|
|
99
|
+
# Shakapacker.manifest.lookup('calendar.js')
|
|
100
|
+
# #=> "/packs/calendar-1016838bab065ae1e122.js"
|
|
39
101
|
#
|
|
40
|
-
# Shakapacker.manifest.lookup('calendar
|
|
102
|
+
# Shakapacker.manifest.lookup('calendar', type: :javascript)
|
|
103
|
+
# #=> "/packs/calendar-1016838bab065ae1e122.js"
|
|
41
104
|
def lookup(name, pack_type = {})
|
|
42
105
|
compile if compiling?
|
|
43
106
|
|
|
44
107
|
find(full_pack_name(name, pack_type[:type]))
|
|
45
108
|
end
|
|
46
109
|
|
|
47
|
-
# Like lookup,
|
|
110
|
+
# Like {#lookup}, but raises an error if the asset is not found
|
|
111
|
+
#
|
|
112
|
+
# @param name [String] the source file name
|
|
113
|
+
# @param pack_type [Hash] options hash with :type key
|
|
114
|
+
# @return [String] the compiled asset path
|
|
115
|
+
# @raise [MissingEntryError] if the asset is not found in the manifest
|
|
116
|
+
# @example
|
|
117
|
+
# Shakapacker.manifest.lookup!('calendar.js')
|
|
118
|
+
# #=> "/packs/calendar-1016838bab065ae1e122.js"
|
|
119
|
+
#
|
|
120
|
+
# Shakapacker.manifest.lookup!('missing.js')
|
|
121
|
+
# #=> raises MissingEntryError
|
|
48
122
|
def lookup!(name, pack_type = {})
|
|
49
123
|
lookup(name, pack_type) || handle_missing_entry(name, pack_type)
|
|
50
124
|
end
|
data/lib/shakapacker/version.rb
CHANGED
data/lib/shakapacker.rb
CHANGED
|
@@ -3,22 +3,86 @@ require "active_support/core_ext/string/inquiry"
|
|
|
3
3
|
require "active_support/logger"
|
|
4
4
|
require "active_support/tagged_logging"
|
|
5
5
|
|
|
6
|
+
# = Shakapacker
|
|
7
|
+
#
|
|
8
|
+
# Shakapacker is a Ruby gem that integrates webpack and rspack with Rails applications,
|
|
9
|
+
# providing a modern asset pipeline for JavaScript, CSS, and other web assets.
|
|
10
|
+
#
|
|
11
|
+
# The main Shakapacker module provides singleton-style access to configuration,
|
|
12
|
+
# compilation, and asset manifest functionality. Most methods delegate to a shared
|
|
13
|
+
# {Shakapacker::Instance} object.
|
|
14
|
+
#
|
|
15
|
+
# == Basic Usage
|
|
16
|
+
#
|
|
17
|
+
# # Access configuration
|
|
18
|
+
# Shakapacker.config.source_path
|
|
19
|
+
# #=> Pathname("/path/to/app/packs")
|
|
20
|
+
#
|
|
21
|
+
# # Check if dev server is running
|
|
22
|
+
# Shakapacker.dev_server.running?
|
|
23
|
+
# #=> true
|
|
24
|
+
#
|
|
25
|
+
# # Look up compiled assets
|
|
26
|
+
# Shakapacker.manifest.lookup("application.js")
|
|
27
|
+
# #=> "/packs/application-abc123.js"
|
|
28
|
+
#
|
|
29
|
+
# # Compile assets
|
|
30
|
+
# Shakapacker.compile
|
|
31
|
+
#
|
|
32
|
+
# == Configuration
|
|
33
|
+
#
|
|
34
|
+
# Configuration is loaded from +config/shakapacker.yml+ and can be accessed via
|
|
35
|
+
# {Shakapacker.config}. The configuration determines the source paths, output paths,
|
|
36
|
+
# compilation settings, and dev server options.
|
|
37
|
+
#
|
|
38
|
+
# @see Shakapacker::Configuration
|
|
39
|
+
# @see Shakapacker::Instance
|
|
6
40
|
module Shakapacker
|
|
7
41
|
extend self
|
|
8
42
|
|
|
43
|
+
# Default environment when RAILS_ENV is not set
|
|
9
44
|
DEFAULT_ENV = "development".freeze
|
|
10
45
|
# Environments that use their RAILS_ENV value for NODE_ENV
|
|
11
46
|
# All other environments (production, staging, etc.) use "production" for webpack optimizations
|
|
12
47
|
DEV_TEST_ENVS = %w[development test].freeze
|
|
13
48
|
|
|
49
|
+
# Sets the shared Shakapacker instance
|
|
50
|
+
#
|
|
51
|
+
# This is primarily used for testing or advanced customization scenarios.
|
|
52
|
+
# In most applications, the default instance is sufficient.
|
|
53
|
+
#
|
|
54
|
+
# @param instance [Shakapacker::Instance] the instance to use
|
|
55
|
+
# @return [Shakapacker::Instance] the instance that was set
|
|
56
|
+
# @api public
|
|
14
57
|
def instance=(instance)
|
|
15
58
|
@instance = instance
|
|
16
59
|
end
|
|
17
60
|
|
|
61
|
+
# Returns the shared Shakapacker instance
|
|
62
|
+
#
|
|
63
|
+
# This instance is used by all module-level delegate methods. It provides
|
|
64
|
+
# access to configuration, compilation, manifest lookup, and more.
|
|
65
|
+
#
|
|
66
|
+
# @return [Shakapacker::Instance] the shared instance
|
|
67
|
+
# @api public
|
|
18
68
|
def instance
|
|
19
69
|
@instance ||= Shakapacker::Instance.new
|
|
20
70
|
end
|
|
21
71
|
|
|
72
|
+
# Temporarily overrides NODE_ENV for the duration of the block
|
|
73
|
+
#
|
|
74
|
+
# This is useful when you need to perform operations with a specific NODE_ENV
|
|
75
|
+
# value without permanently changing the environment.
|
|
76
|
+
#
|
|
77
|
+
# @param env [String] the NODE_ENV value to use temporarily
|
|
78
|
+
# @yield the block to execute with the temporary NODE_ENV
|
|
79
|
+
# @return [Object] the return value of the block
|
|
80
|
+
# @example
|
|
81
|
+
# Shakapacker.with_node_env("production") do
|
|
82
|
+
# # This code runs with NODE_ENV=production
|
|
83
|
+
# Shakapacker.compile
|
|
84
|
+
# end
|
|
85
|
+
# @api public
|
|
22
86
|
def with_node_env(env)
|
|
23
87
|
original = ENV["NODE_ENV"]
|
|
24
88
|
ENV["NODE_ENV"] = env
|
|
@@ -27,13 +91,32 @@ module Shakapacker
|
|
|
27
91
|
ENV["NODE_ENV"] = original
|
|
28
92
|
end
|
|
29
93
|
|
|
30
|
-
#
|
|
31
|
-
#
|
|
32
|
-
#
|
|
94
|
+
# Sets NODE_ENV based on RAILS_ENV if not already set
|
|
95
|
+
#
|
|
96
|
+
# Environment mapping:
|
|
97
|
+
# - +development+ and +test+ environments use their RAILS_ENV value for NODE_ENV
|
|
98
|
+
# - All other environments (+production+, +staging+, etc.) use "production" for webpack optimizations
|
|
99
|
+
#
|
|
100
|
+
# This method is typically called automatically during Rails initialization.
|
|
101
|
+
#
|
|
102
|
+
# @return [String] the NODE_ENV value that was set
|
|
103
|
+
# @api private
|
|
33
104
|
def ensure_node_env!
|
|
34
105
|
ENV["NODE_ENV"] ||= DEV_TEST_ENVS.include?(ENV["RAILS_ENV"]) ? ENV["RAILS_ENV"] : "production"
|
|
35
106
|
end
|
|
36
107
|
|
|
108
|
+
# Temporarily redirects Shakapacker logging to STDOUT
|
|
109
|
+
#
|
|
110
|
+
# This is useful for debugging or when you want to see compilation output
|
|
111
|
+
# in the console instead of the Rails log.
|
|
112
|
+
#
|
|
113
|
+
# @yield the block to execute with STDOUT logging
|
|
114
|
+
# @return [Object] the return value of the block
|
|
115
|
+
# @example
|
|
116
|
+
# Shakapacker.ensure_log_goes_to_stdout do
|
|
117
|
+
# Shakapacker.compile
|
|
118
|
+
# end
|
|
119
|
+
# @api public
|
|
37
120
|
def ensure_log_goes_to_stdout
|
|
38
121
|
old_logger = Shakapacker.logger
|
|
39
122
|
Shakapacker.logger = Logger.new(STDOUT)
|
|
@@ -42,8 +125,65 @@ module Shakapacker
|
|
|
42
125
|
Shakapacker.logger = old_logger
|
|
43
126
|
end
|
|
44
127
|
|
|
128
|
+
# @!method logger
|
|
129
|
+
# Returns the logger instance used by Shakapacker
|
|
130
|
+
# @return [Logger] the logger instance
|
|
131
|
+
# @see Shakapacker::Instance#logger
|
|
132
|
+
# @!method logger=(logger)
|
|
133
|
+
# Sets the logger instance used by Shakapacker
|
|
134
|
+
# @param logger [Logger] the logger to use
|
|
135
|
+
# @return [Logger] the logger that was set
|
|
136
|
+
# @see Shakapacker::Instance#logger=
|
|
137
|
+
# @!method env
|
|
138
|
+
# Returns the current Rails environment as an ActiveSupport::StringInquirer
|
|
139
|
+
# @return [ActiveSupport::StringInquirer] the environment
|
|
140
|
+
# @see Shakapacker::Instance#env
|
|
141
|
+
# @!method inlining_css?
|
|
142
|
+
# Returns whether CSS inlining is enabled
|
|
143
|
+
# @return [Boolean] true if CSS should be inlined
|
|
144
|
+
# @see Shakapacker::Instance#inlining_css?
|
|
45
145
|
delegate :logger, :logger=, :env, :inlining_css?, to: :instance
|
|
146
|
+
|
|
147
|
+
# @!method config
|
|
148
|
+
# Returns the Shakapacker configuration object
|
|
149
|
+
# @return [Shakapacker::Configuration] the configuration
|
|
150
|
+
# @see Shakapacker::Instance#config
|
|
151
|
+
# @!method compiler
|
|
152
|
+
# Returns the compiler instance for compiling assets
|
|
153
|
+
# @return [Shakapacker::Compiler] the compiler
|
|
154
|
+
# @see Shakapacker::Instance#compiler
|
|
155
|
+
# @!method manifest
|
|
156
|
+
# Returns the manifest instance for looking up compiled assets
|
|
157
|
+
# @return [Shakapacker::Manifest] the manifest
|
|
158
|
+
# @see Shakapacker::Instance#manifest
|
|
159
|
+
# @!method commands
|
|
160
|
+
# Returns the commands instance for build operations
|
|
161
|
+
# @return [Shakapacker::Commands] the commands object
|
|
162
|
+
# @see Shakapacker::Instance#commands
|
|
163
|
+
# @!method dev_server
|
|
164
|
+
# Returns the dev server instance for querying server status
|
|
165
|
+
# @return [Shakapacker::DevServer] the dev server
|
|
166
|
+
# @see Shakapacker::Instance#dev_server
|
|
46
167
|
delegate :config, :compiler, :manifest, :commands, :dev_server, to: :instance
|
|
168
|
+
|
|
169
|
+
# @!method bootstrap
|
|
170
|
+
# Creates the default configuration files and directory structure
|
|
171
|
+
# @return [void]
|
|
172
|
+
# @see Shakapacker::Commands#bootstrap
|
|
173
|
+
# @!method clean(count = nil, age = nil)
|
|
174
|
+
# Removes old compiled packs, keeping the most recent versions
|
|
175
|
+
# @param count [Integer, nil] number of versions to keep per entry
|
|
176
|
+
# @param age [Integer, nil] maximum age in seconds for packs to keep
|
|
177
|
+
# @return [void]
|
|
178
|
+
# @see Shakapacker::Commands#clean
|
|
179
|
+
# @!method clobber
|
|
180
|
+
# Removes all compiled packs
|
|
181
|
+
# @return [void]
|
|
182
|
+
# @see Shakapacker::Commands#clobber
|
|
183
|
+
# @!method compile
|
|
184
|
+
# Compiles all webpack/rspack packs
|
|
185
|
+
# @return [Boolean] true if compilation succeeded
|
|
186
|
+
# @see Shakapacker::Commands#compile
|
|
47
187
|
delegate :bootstrap, :clean, :clobber, :compile, to: :commands
|
|
48
188
|
end
|
|
49
189
|
|
|
@@ -11,7 +11,7 @@ namespace :shakapacker do
|
|
|
11
11
|
• Required and optional npm dependencies
|
|
12
12
|
• JavaScript transpiler (Babel, SWC, esbuild) configuration
|
|
13
13
|
• CSS, CSS Modules, and stylesheet preprocessor setup
|
|
14
|
-
• Binstubs presence (shakapacker, shakapacker-dev-server,
|
|
14
|
+
• Binstubs presence (shakapacker, shakapacker-dev-server, shakapacker-config)
|
|
15
15
|
• Version consistency between gem and npm package
|
|
16
16
|
• Legacy Webpacker file detection
|
|
17
17
|
|
|
@@ -42,18 +42,18 @@ namespace :shakapacker do
|
|
|
42
42
|
Note: When using 'rake', you must use '--' to separate rake options from task arguments.
|
|
43
43
|
Example: rake shakapacker:export_bundler_config -- --doctor
|
|
44
44
|
|
|
45
|
-
The task automatically falls back to the gem version if bin/
|
|
45
|
+
The task automatically falls back to the gem version if bin/shakapacker-config
|
|
46
46
|
binstub is not installed. To install all binstubs, run: rails shakapacker:binstubs
|
|
47
47
|
DESC
|
|
48
48
|
task :export_bundler_config do
|
|
49
49
|
# Try to use the binstub if it exists, otherwise use the gem's version
|
|
50
|
-
bin_path = Rails.root.join("bin/
|
|
50
|
+
bin_path = Rails.root.join("bin/shakapacker-config")
|
|
51
51
|
|
|
52
52
|
unless File.exist?(bin_path)
|
|
53
53
|
# Binstub not installed, use the gem's version directly
|
|
54
|
-
gem_bin_path = File.expand_path("../../install/bin/
|
|
54
|
+
gem_bin_path = File.expand_path("../../install/bin/shakapacker-config", __dir__)
|
|
55
55
|
|
|
56
|
-
$stderr.puts "Note: bin/
|
|
56
|
+
$stderr.puts "Note: bin/shakapacker-config binstub not found."
|
|
57
57
|
$stderr.puts "Using gem version directly. To install the binstub, run: rake shakapacker:binstubs"
|
|
58
58
|
$stderr.puts ""
|
|
59
59
|
|
data/package/config.ts
CHANGED
|
@@ -55,7 +55,6 @@ if (existsSync(configPath)) {
|
|
|
55
55
|
const envAppConfig = appYmlObject[railsEnv]
|
|
56
56
|
|
|
57
57
|
if (!envAppConfig) {
|
|
58
|
-
/* eslint no-console:0 */
|
|
59
58
|
console.warn(
|
|
60
59
|
`[SHAKAPACKER WARNING] Environment '${railsEnv}' not found in ${configPath}\n` +
|
|
61
60
|
`Available environments: ${Object.keys(appYmlObject).join(", ")}\n` +
|