vite_ruby 3.3.4 → 3.10.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 +176 -0
- data/default.vite.json +2 -1
- data/exe/vite +3 -3
- data/lib/tasks/vite.rake +43 -47
- data/lib/vite_ruby/build.rb +4 -4
- data/lib/vite_ruby/builder.rb +13 -13
- data/lib/vite_ruby/cli/build.rb +6 -6
- data/lib/vite_ruby/cli/clobber.rb +4 -4
- data/lib/vite_ruby/cli/dev.rb +3 -3
- data/lib/vite_ruby/cli/file_utils.rb +16 -9
- data/lib/vite_ruby/cli/install.rb +44 -32
- data/lib/vite_ruby/cli/ssr.rb +8 -8
- data/lib/vite_ruby/cli/upgrade.rb +4 -4
- data/lib/vite_ruby/cli/upgrade_packages.rb +3 -4
- data/lib/vite_ruby/cli/version.rb +1 -1
- data/lib/vite_ruby/cli/vite.rb +20 -9
- data/lib/vite_ruby/cli.rb +13 -13
- data/lib/vite_ruby/commands.rb +20 -74
- data/lib/vite_ruby/compatibility_check.rb +7 -7
- data/lib/vite_ruby/config.rb +54 -38
- data/lib/vite_ruby/dev_server_proxy.rb +21 -20
- data/lib/vite_ruby/error.rb +1 -1
- data/lib/vite_ruby/io.rb +3 -3
- data/lib/vite_ruby/manifest.rb +42 -23
- data/lib/vite_ruby/missing_entrypoint_error.rb +9 -10
- data/lib/vite_ruby/missing_executable_error.rb +1 -1
- data/lib/vite_ruby/runner.rb +16 -14
- data/lib/vite_ruby/version.rb +3 -3
- data/lib/vite_ruby.rb +26 -26
- metadata +36 -10
data/lib/vite_ruby/config.rb
CHANGED
|
@@ -1,35 +1,36 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
3
|
+
require "json"
|
|
4
4
|
|
|
5
5
|
# Public: Allows to resolve configuration sourced from `config/vite.json` and
|
|
6
6
|
# environment variables, combining them with the default options.
|
|
7
7
|
class ViteRuby::Config
|
|
8
8
|
def origin
|
|
9
|
-
"#{
|
|
9
|
+
"#{protocol}://#{host_with_port}"
|
|
10
10
|
end
|
|
11
11
|
|
|
12
12
|
def protocol
|
|
13
|
-
https ?
|
|
13
|
+
https ? "https" : "http"
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
def host_with_port
|
|
17
|
-
"#{
|
|
17
|
+
"#{host}:#{port}"
|
|
18
18
|
end
|
|
19
19
|
|
|
20
|
-
# Internal: Path
|
|
21
|
-
def
|
|
22
|
-
|
|
23
|
-
|
|
20
|
+
# Internal: Path to the manifest files generated by Vite and vite-plugin-ruby.
|
|
21
|
+
def known_manifest_paths
|
|
22
|
+
[
|
|
23
|
+
# NOTE: Generated by Vite when `manifest: true`, which vite-plugin-ruby enables.
|
|
24
|
+
build_output_dir.join(".vite/manifest.json"),
|
|
24
25
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
# NOTE: Path where vite-plugin-ruby outputs the assets manifest file.
|
|
27
|
+
build_output_dir.join(".vite/manifest-assets.json"),
|
|
28
|
+
]
|
|
28
29
|
end
|
|
29
30
|
|
|
30
31
|
# Internal: Path to the manifest files generated by Vite and vite-plugin-ruby.
|
|
31
32
|
def manifest_paths
|
|
32
|
-
|
|
33
|
+
known_manifest_paths.select(&:exist?)
|
|
33
34
|
end
|
|
34
35
|
|
|
35
36
|
# Public: The directory where Vite will store the built assets.
|
|
@@ -44,7 +45,7 @@ class ViteRuby::Config
|
|
|
44
45
|
|
|
45
46
|
# Internal: The directory where Vite stores its processing cache.
|
|
46
47
|
def vite_cache_dir
|
|
47
|
-
root.join(
|
|
48
|
+
root.join("node_modules/.vite")
|
|
48
49
|
end
|
|
49
50
|
|
|
50
51
|
# Public: The directory that Vite uses as root.
|
|
@@ -54,7 +55,7 @@ class ViteRuby::Config
|
|
|
54
55
|
|
|
55
56
|
# Public: Loads an optional config/vite.rb file that can modify ViteRuby.env
|
|
56
57
|
def load_ruby_config
|
|
57
|
-
rb_config_path = File.expand_path(config_path.sub(/.json$/,
|
|
58
|
+
rb_config_path = File.expand_path(config_path.sub(/.json$/, ".rb"), root)
|
|
58
59
|
load rb_config_path if File.exist?(rb_config_path)
|
|
59
60
|
end
|
|
60
61
|
|
|
@@ -62,7 +63,7 @@ class ViteRuby::Config
|
|
|
62
63
|
def to_env(env_vars = ViteRuby.env)
|
|
63
64
|
CONFIGURABLE_WITH_ENV.each_with_object({}) do |option, env|
|
|
64
65
|
unless (value = @config[option]).nil?
|
|
65
|
-
env["#{
|
|
66
|
+
env["#{ViteRuby::ENV_PREFIX}_#{option.upcase}"] = value.to_s
|
|
66
67
|
end
|
|
67
68
|
end.merge(env_vars)
|
|
68
69
|
end
|
|
@@ -71,10 +72,10 @@ class ViteRuby::Config
|
|
|
71
72
|
def watched_paths
|
|
72
73
|
[
|
|
73
74
|
*(watch_additional_paths + additional_entrypoints).reject { |dir|
|
|
74
|
-
dir.start_with?(
|
|
75
|
+
dir.start_with?("~/") || dir.start_with?(source_code_dir)
|
|
75
76
|
},
|
|
76
|
-
"#{
|
|
77
|
-
config_path.sub(/.json$/,
|
|
77
|
+
"#{source_code_dir}/**/*",
|
|
78
|
+
config_path.sub(/.json$/, ".{rb,json}"),
|
|
78
79
|
*DEFAULT_WATCHED_PATHS,
|
|
79
80
|
].freeze
|
|
80
81
|
end
|
|
@@ -89,17 +90,29 @@ private
|
|
|
89
90
|
# Internal: Coerces all the configuration values, in case they were passed
|
|
90
91
|
# as environment variables which are always strings.
|
|
91
92
|
def coerce_values(config)
|
|
92
|
-
config[
|
|
93
|
-
config[
|
|
94
|
-
config[
|
|
95
|
-
config[
|
|
96
|
-
config[
|
|
97
|
-
|
|
93
|
+
config["mode"] = config["mode"].to_s
|
|
94
|
+
config["port"] = config["port"].to_i
|
|
95
|
+
config["root"] = root = Pathname.new(config["root"])
|
|
96
|
+
config["build_cache_dir"] = root.join(config["build_cache_dir"])
|
|
97
|
+
config["ssr_output_dir"] = root.join(config["ssr_output_dir"])
|
|
98
|
+
config["dev_server_connect_timeout"] = config["dev_server_connect_timeout"].to_f
|
|
99
|
+
coerce_booleans(config, "auto_build", "hide_build_console_output", "https", "skip_compatibility_check", "skip_proxy")
|
|
100
|
+
config["package_manager"] ||= detect_package_manager(root)
|
|
98
101
|
end
|
|
99
102
|
|
|
100
103
|
# Internal: Coerces configuration options to boolean.
|
|
101
104
|
def coerce_booleans(config, *names)
|
|
102
|
-
|
|
105
|
+
truthy = [true, "true"]
|
|
106
|
+
names.each { |name| config[name] = truthy.include?(config[name]) }
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def detect_package_manager(root)
|
|
110
|
+
return "npm" if root.join("package-lock.json").exist?
|
|
111
|
+
return "pnpm" if root.join("pnpm-lock.yaml").exist?
|
|
112
|
+
return "bun" if root.join("bun.lockb").exist? || root.join("bun.lock").exist?
|
|
113
|
+
return "yarn" if root.join("yarn.lock").exist?
|
|
114
|
+
|
|
115
|
+
"npm"
|
|
103
116
|
end
|
|
104
117
|
|
|
105
118
|
def initialize(attrs)
|
|
@@ -113,8 +126,8 @@ private
|
|
|
113
126
|
# Public: Returns the project configuration for Vite.
|
|
114
127
|
def resolve_config(**attrs)
|
|
115
128
|
config = config_defaults.merge(attrs.transform_keys(&:to_s))
|
|
116
|
-
file_path = File.join(config[
|
|
117
|
-
file_config = config_from_file(file_path, mode: config[
|
|
129
|
+
file_path = File.join(config["root"], config["config_path"])
|
|
130
|
+
file_config = config_from_file(file_path, mode: config["mode"])
|
|
118
131
|
new DEFAULT_CONFIG.merge(file_config).merge(config_from_env).merge(config)
|
|
119
132
|
end
|
|
120
133
|
|
|
@@ -122,20 +135,20 @@ private
|
|
|
122
135
|
|
|
123
136
|
# Internal: Converts camelCase to snake_case.
|
|
124
137
|
SNAKE_CASE = ->(camel_cased_word) {
|
|
125
|
-
camel_cased_word.to_s.gsub(
|
|
138
|
+
camel_cased_word.to_s.gsub("::", "/")
|
|
126
139
|
.gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
|
|
127
140
|
.gsub(/([a-z\d])([A-Z])/, '\1_\2')
|
|
128
|
-
.tr(
|
|
141
|
+
.tr("-", "_")
|
|
129
142
|
.downcase
|
|
130
143
|
}
|
|
131
144
|
|
|
132
145
|
# Internal: Default values for a Ruby application.
|
|
133
|
-
def config_defaults(asset_host: nil, mode: ENV.fetch(
|
|
146
|
+
def config_defaults(asset_host: nil, mode: ENV.fetch("RACK_ENV", "development"), root: Dir.pwd)
|
|
134
147
|
{
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
148
|
+
"asset_host" => option_from_env("asset_host") || asset_host,
|
|
149
|
+
"config_path" => option_from_env("config_path") || DEFAULT_CONFIG.fetch("config_path"),
|
|
150
|
+
"mode" => option_from_env("mode") || mode,
|
|
151
|
+
"root" => option_from_env("root") || root,
|
|
139
152
|
}.select { |_, value| value }
|
|
140
153
|
end
|
|
141
154
|
|
|
@@ -150,7 +163,7 @@ private
|
|
|
150
163
|
|
|
151
164
|
# Internal: Retrieves a configuration option from environment variables.
|
|
152
165
|
def option_from_env(name)
|
|
153
|
-
ViteRuby.env["#{
|
|
166
|
+
ViteRuby.env["#{ViteRuby::ENV_PREFIX}_#{name.upcase}"]
|
|
154
167
|
end
|
|
155
168
|
|
|
156
169
|
# Internal: Extracts the configuration options provided as env vars.
|
|
@@ -165,16 +178,16 @@ private
|
|
|
165
178
|
# Internal: Loads the configuration options provided in a JSON file.
|
|
166
179
|
def config_from_file(path, mode:)
|
|
167
180
|
multi_env_config = load_json(path)
|
|
168
|
-
multi_env_config.fetch(
|
|
181
|
+
multi_env_config.fetch("all", {})
|
|
169
182
|
.merge(multi_env_config.fetch(mode, {}))
|
|
170
183
|
rescue Errno::ENOENT => error
|
|
171
|
-
$stderr << "Check that your vite.json configuration file is available in the load path:\n\n\t#{
|
|
184
|
+
$stderr << "Check that your vite.json configuration file is available in the load path:\n\n\t#{error.message}\n\n"
|
|
172
185
|
{}
|
|
173
186
|
end
|
|
174
187
|
end
|
|
175
188
|
|
|
176
189
|
# Internal: Shared configuration with the Vite plugin for Ruby.
|
|
177
|
-
DEFAULT_CONFIG = load_json("#{
|
|
190
|
+
DEFAULT_CONFIG = load_json("#{__dir__}/../../default.vite.json").freeze
|
|
178
191
|
|
|
179
192
|
# Internal: Configuration options that can not be provided as env vars.
|
|
180
193
|
NOT_CONFIGURABLE_WITH_ENV = %w[additional_entrypoints watch_additional_paths].freeze
|
|
@@ -184,12 +197,15 @@ private
|
|
|
184
197
|
|
|
185
198
|
# Internal: If any of these files is modified the build won't be skipped.
|
|
186
199
|
DEFAULT_WATCHED_PATHS = %w[
|
|
200
|
+
bun.lockb
|
|
187
201
|
package-lock.json
|
|
188
202
|
package.json
|
|
189
203
|
pnpm-lock.yaml
|
|
190
204
|
postcss.config.js
|
|
191
205
|
tailwind.config.js
|
|
192
206
|
vite.config.js
|
|
207
|
+
vite.config.mjs
|
|
208
|
+
vite.config.mts
|
|
193
209
|
vite.config.ts
|
|
194
210
|
windi.config.ts
|
|
195
211
|
yarn.lock
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
3
|
+
require "rack/proxy"
|
|
4
4
|
|
|
5
5
|
# Public: Allows to relay asset requests to the Vite development server.
|
|
6
6
|
class ViteRuby::DevServerProxy < Rack::Proxy
|
|
7
7
|
HOST_WITH_PORT_REGEX = %r{^(.+?)(:\d+)/}
|
|
8
|
-
VITE_DEPENDENCY_PREFIX =
|
|
8
|
+
VITE_DEPENDENCY_PREFIX = "/@"
|
|
9
9
|
|
|
10
10
|
def initialize(app = nil, options = {})
|
|
11
11
|
@vite_ruby = options.delete(:vite_ruby) || ViteRuby.instance
|
|
12
|
-
options[:streaming] = false if config.mode ==
|
|
12
|
+
options[:streaming] = false if config.mode == "test" && !options.key?(:streaming)
|
|
13
13
|
super
|
|
14
14
|
end
|
|
15
15
|
|
|
@@ -17,7 +17,7 @@ class ViteRuby::DevServerProxy < Rack::Proxy
|
|
|
17
17
|
def perform_request(env)
|
|
18
18
|
if vite_should_handle?(env) && dev_server_running?
|
|
19
19
|
forward_to_vite_dev_server(env)
|
|
20
|
-
super
|
|
20
|
+
super
|
|
21
21
|
else
|
|
22
22
|
@app.call(env)
|
|
23
23
|
end
|
|
@@ -30,39 +30,40 @@ private
|
|
|
30
30
|
def_delegators :@vite_ruby, :config, :dev_server_running?
|
|
31
31
|
|
|
32
32
|
def rewrite_uri_for_vite(env)
|
|
33
|
-
uri = env.fetch(
|
|
34
|
-
env[
|
|
33
|
+
uri = env.fetch("REQUEST_URI") { [env["PATH_INFO"], env["QUERY_STRING"]].reject { |str| str.to_s.strip.empty? }.join("?") }
|
|
34
|
+
env["PATH_INFO"], env["QUERY_STRING"] = (env["REQUEST_URI"] = normalize_uri(uri)).split("?")
|
|
35
35
|
end
|
|
36
36
|
|
|
37
37
|
def normalize_uri(uri)
|
|
38
38
|
uri
|
|
39
|
-
.sub(HOST_WITH_PORT_REGEX,
|
|
40
|
-
.sub(
|
|
39
|
+
.sub(HOST_WITH_PORT_REGEX, "/") # Hanami adds the host and port.
|
|
40
|
+
.sub(".ts.js", ".ts") # Hanami's javascript helper always adds the extension.
|
|
41
41
|
.sub(/\.(sass|scss|styl|stylus|less|pcss|postcss)\.css$/, '.\1') # Rails' stylesheet_link_tag always adds the extension.
|
|
42
42
|
end
|
|
43
43
|
|
|
44
44
|
def forward_to_vite_dev_server(env)
|
|
45
45
|
rewrite_uri_for_vite(env)
|
|
46
|
-
env[
|
|
47
|
-
env[
|
|
48
|
-
env[
|
|
49
|
-
env[
|
|
50
|
-
env[
|
|
51
|
-
env[
|
|
52
|
-
env[
|
|
46
|
+
env["QUERY_STRING"] ||= ""
|
|
47
|
+
env["HTTP_HOST"] = env["HTTP_X_FORWARDED_HOST"] = config.host
|
|
48
|
+
env["HTTP_X_FORWARDED_SERVER"] = config.host_with_port
|
|
49
|
+
env["HTTP_PORT"] = env["HTTP_X_FORWARDED_PORT"] = config.port.to_s
|
|
50
|
+
env["HTTP_X_FORWARDED_PROTO"] = env["HTTP_X_FORWARDED_SCHEME"] = config.protocol
|
|
51
|
+
env["HTTPS"] = env["HTTP_X_FORWARDED_SSL"] = "off" unless config.https
|
|
52
|
+
env["SCRIPT_NAME"] = ""
|
|
53
53
|
end
|
|
54
54
|
|
|
55
55
|
def vite_should_handle?(env)
|
|
56
|
-
path = normalize_uri(env[
|
|
56
|
+
path = normalize_uri(env["PATH_INFO"])
|
|
57
57
|
return true if path.start_with?(vite_url_prefix) # Vite asset
|
|
58
|
-
|
|
58
|
+
|
|
59
|
+
true if file_in_vite_root?(path) # Fallback if Vite can serve the file
|
|
59
60
|
end
|
|
60
61
|
|
|
61
62
|
# NOTE: When using an empty 'public_output_dir', we need to rely on a
|
|
62
63
|
# filesystem check to check whether Vite should serve the request.
|
|
63
64
|
def file_in_vite_root?(path)
|
|
64
|
-
path.include?(
|
|
65
|
-
config.vite_root_dir.join(path.start_with?(
|
|
65
|
+
path.include?(".") && # Check for extension, avoid filesystem if possible.
|
|
66
|
+
config.vite_root_dir.join(path.start_with?("/") ? path[1..] : path).file?
|
|
66
67
|
end
|
|
67
68
|
|
|
68
69
|
# NOTE: Vite is configured to use 'public_output_dir' as the base, which can
|
|
@@ -70,6 +71,6 @@ private
|
|
|
70
71
|
#
|
|
71
72
|
# If the path starts with that prefix, it will be redirected to Vite.
|
|
72
73
|
def vite_url_prefix
|
|
73
|
-
@vite_url_prefix ||= config.public_output_dir.empty? ? VITE_DEPENDENCY_PREFIX : "/#{
|
|
74
|
+
@vite_url_prefix ||= config.public_output_dir.empty? ? VITE_DEPENDENCY_PREFIX : "/#{config.public_output_dir}/"
|
|
74
75
|
end
|
|
75
76
|
end
|
data/lib/vite_ruby/error.rb
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
# Internal: Provides common functionality for errors.
|
|
4
4
|
class ViteRuby::Error < StandardError
|
|
5
5
|
def message
|
|
6
|
-
super.sub(
|
|
6
|
+
super.sub(":troubleshooting:", <<~MSG)
|
|
7
7
|
Visit the Troubleshooting guide for more information:
|
|
8
8
|
https://vite-ruby.netlify.app/guide/troubleshooting.html#troubleshooting
|
|
9
9
|
MSG
|
data/lib/vite_ruby/io.rb
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
3
|
+
require "open3"
|
|
4
4
|
|
|
5
5
|
# Public: Builds on top of Ruby I/O open3 providing a friendlier experience.
|
|
6
6
|
module ViteRuby::IO
|
|
7
7
|
class << self
|
|
8
8
|
# Internal: A modified version of capture3 that can continuosly print stdout.
|
|
9
9
|
# NOTE: Streaming output provides a better UX when running bin/vite build.
|
|
10
|
-
def capture(*cmd, with_output: $stdout.method(:puts), stdin_data:
|
|
10
|
+
def capture(*cmd, with_output: $stdout.method(:puts), stdin_data: "", **opts)
|
|
11
11
|
return Open3.capture3(*cmd, **opts) unless with_output
|
|
12
12
|
|
|
13
13
|
Open3.popen3(*cmd, **opts) { |stdin, stdout, stderr, wait_threads|
|
|
@@ -21,7 +21,7 @@ module ViteRuby::IO
|
|
|
21
21
|
|
|
22
22
|
# Internal: Reads and yield every line in the stream. Returns the full content.
|
|
23
23
|
def read_lines(io)
|
|
24
|
-
buffer = +
|
|
24
|
+
buffer = +""
|
|
25
25
|
while line = io.gets
|
|
26
26
|
buffer << line
|
|
27
27
|
yield line
|
data/lib/vite_ruby/manifest.rb
CHANGED
|
@@ -19,20 +19,37 @@ class ViteRuby::Manifest
|
|
|
19
19
|
#
|
|
20
20
|
# Raises an error if the resource could not be found in the manifest.
|
|
21
21
|
def path_for(name, **options)
|
|
22
|
-
lookup!(name, **options).fetch(
|
|
22
|
+
lookup!(name, **options).fetch("file")
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Internal: Recursively collects all imported chunks for a given entry.
|
|
26
|
+
# Returns chunks in dependency-first order (deepest imports first), deduped.
|
|
27
|
+
def import_chunks_for(entry, seen_filenames: Set.new)
|
|
28
|
+
chunks = []
|
|
29
|
+
|
|
30
|
+
entry["imports"]&.each do |chunk|
|
|
31
|
+
filename = chunk["file"]
|
|
32
|
+
next if seen_filenames.include?(filename)
|
|
33
|
+
seen_filenames.add(filename)
|
|
34
|
+
|
|
35
|
+
chunks.concat(import_chunks_for(chunk, seen_filenames: seen_filenames))
|
|
36
|
+
chunks << chunk
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
chunks
|
|
23
40
|
end
|
|
24
41
|
|
|
25
42
|
# Public: Returns scripts, imported modules, and stylesheets for the specified
|
|
26
43
|
# entrypoint files.
|
|
27
44
|
def resolve_entries(*names, **options)
|
|
28
45
|
entries = names.map { |name| lookup!(name, **options) }
|
|
29
|
-
script_paths = entries.map { |entry| entry.fetch(
|
|
46
|
+
script_paths = entries.map { |entry| entry.fetch("file") }
|
|
30
47
|
|
|
31
|
-
imports = dev_server_running? ? [] : entries.flat_map { |entry| entry
|
|
48
|
+
imports = dev_server_running? ? [] : entries.flat_map { |entry| import_chunks_for(entry) }
|
|
32
49
|
{
|
|
33
50
|
scripts: script_paths,
|
|
34
|
-
imports: imports.
|
|
35
|
-
stylesheets: dev_server_running? ? [] : (entries + imports).flat_map { |entry| entry[
|
|
51
|
+
imports: imports.filter_map { |entry| entry.fetch("file") }.uniq,
|
|
52
|
+
stylesheets: dev_server_running? ? [] : (entries + imports).flat_map { |entry| entry["css"] }.compact.uniq,
|
|
36
53
|
}
|
|
37
54
|
end
|
|
38
55
|
|
|
@@ -43,7 +60,7 @@ class ViteRuby::Manifest
|
|
|
43
60
|
|
|
44
61
|
# Public: The path from where the browser can download the Vite HMR client.
|
|
45
62
|
def vite_client_src
|
|
46
|
-
prefix_asset_with_host(
|
|
63
|
+
prefix_asset_with_host("@vite/client") if dev_server_running?
|
|
47
64
|
end
|
|
48
65
|
|
|
49
66
|
# Public: The content of the preamble needed by the React Refresh plugin.
|
|
@@ -51,7 +68,7 @@ class ViteRuby::Manifest
|
|
|
51
68
|
if dev_server_running?
|
|
52
69
|
<<~REACT_REFRESH
|
|
53
70
|
<script type="module">
|
|
54
|
-
#{
|
|
71
|
+
#{react_preamble_code}
|
|
55
72
|
</script>
|
|
56
73
|
REACT_REFRESH
|
|
57
74
|
end
|
|
@@ -61,7 +78,7 @@ class ViteRuby::Manifest
|
|
|
61
78
|
def react_preamble_code
|
|
62
79
|
if dev_server_running?
|
|
63
80
|
<<~REACT_PREAMBLE_CODE
|
|
64
|
-
import RefreshRuntime from '#{
|
|
81
|
+
import RefreshRuntime from '#{prefix_asset_with_host("@react-refresh")}'
|
|
65
82
|
RefreshRuntime.injectIntoGlobalHook(window)
|
|
66
83
|
window.$RefreshReg$ = () => {}
|
|
67
84
|
window.$RefreshSig$ = () => (type) => type
|
|
@@ -95,7 +112,7 @@ protected
|
|
|
95
112
|
private
|
|
96
113
|
|
|
97
114
|
# Internal: The prefix used by Vite.js to request files with an absolute path.
|
|
98
|
-
FS_PREFIX =
|
|
115
|
+
FS_PREFIX = "/@fs/"
|
|
99
116
|
|
|
100
117
|
extend Forwardable
|
|
101
118
|
|
|
@@ -110,7 +127,7 @@ private
|
|
|
110
127
|
# Internal: Finds the specified entry in the manifest.
|
|
111
128
|
def find_manifest_entry(name)
|
|
112
129
|
if dev_server_running?
|
|
113
|
-
{
|
|
130
|
+
{"file" => prefix_vite_asset(name)}
|
|
114
131
|
else
|
|
115
132
|
manifest[name]
|
|
116
133
|
end
|
|
@@ -128,19 +145,21 @@ private
|
|
|
128
145
|
|
|
129
146
|
# Internal: Loads and merges the manifest files, resolving the asset paths.
|
|
130
147
|
def load_manifest
|
|
131
|
-
|
|
132
|
-
|
|
148
|
+
config.manifest_paths
|
|
149
|
+
.map { |path| JSON.parse(path.read) }
|
|
150
|
+
.inject({}, &:merge)
|
|
151
|
+
.tap { |manifest| resolve_references(manifest) }
|
|
133
152
|
end
|
|
134
153
|
|
|
135
154
|
# Internal: Scopes an asset to the output folder in public, as a path.
|
|
136
155
|
def prefix_vite_asset(path)
|
|
137
|
-
File.join(vite_asset_origin ||
|
|
156
|
+
File.join(vite_asset_origin || "/", config.public_output_dir, path)
|
|
138
157
|
end
|
|
139
158
|
|
|
140
159
|
# Internal: Prefixes an asset with the `asset_host` for tags that do not use
|
|
141
160
|
# the framework tag helpers.
|
|
142
161
|
def prefix_asset_with_host(path)
|
|
143
|
-
File.join(vite_asset_origin || config.asset_host ||
|
|
162
|
+
File.join(vite_asset_origin || config.asset_host || "/", config.public_output_dir, path)
|
|
144
163
|
end
|
|
145
164
|
|
|
146
165
|
# Internal: The origin of assets managed by Vite.
|
|
@@ -151,11 +170,11 @@ private
|
|
|
151
170
|
# Internal: Resolves the paths that reference a manifest entry.
|
|
152
171
|
def resolve_references(manifest)
|
|
153
172
|
manifest.each_value do |entry|
|
|
154
|
-
entry[
|
|
173
|
+
entry["file"] = prefix_vite_asset(entry["file"])
|
|
155
174
|
%w[css assets].each do |key|
|
|
156
175
|
entry[key] = entry[key].map { |path| prefix_vite_asset(path) } if entry[key]
|
|
157
176
|
end
|
|
158
|
-
entry[
|
|
177
|
+
entry["imports"]&.map! { |name| manifest.fetch(name) }
|
|
159
178
|
end
|
|
160
179
|
end
|
|
161
180
|
|
|
@@ -164,7 +183,7 @@ private
|
|
|
164
183
|
return resolve_virtual_entry(name) if type == :virtual
|
|
165
184
|
|
|
166
185
|
name = with_file_extension(name.to_s, type)
|
|
167
|
-
raise ArgumentError, "Asset names can not be relative. Found: #{
|
|
186
|
+
raise ArgumentError, "Asset names can not be relative. Found: #{name}" if name.start_with?(".")
|
|
168
187
|
|
|
169
188
|
# Explicit path, relative to the source_code_dir.
|
|
170
189
|
name.sub(%r{^~/(.+)$}) { return Regexp.last_match(1) }
|
|
@@ -173,7 +192,7 @@ private
|
|
|
173
192
|
name.sub(%r{^/(.+)$}) { return resolve_absolute_entry(Regexp.last_match(1)) }
|
|
174
193
|
|
|
175
194
|
# Sugar: Prefix with the entrypoints dir if the path is not nested.
|
|
176
|
-
name.include?(
|
|
195
|
+
name.include?("/") ? name : File.join(config.entrypoints_dir, name)
|
|
177
196
|
end
|
|
178
197
|
|
|
179
198
|
# Internal: Entry names in the manifest are relative to the Vite.js.
|
|
@@ -194,7 +213,7 @@ private
|
|
|
194
213
|
# Internal: Adds a file extension to the file name, unless it already has one.
|
|
195
214
|
def with_file_extension(name, entry_type)
|
|
196
215
|
if File.extname(name).empty? && (ext = extension_for_type(entry_type))
|
|
197
|
-
"#{
|
|
216
|
+
"#{name}.#{ext}"
|
|
198
217
|
else
|
|
199
218
|
name
|
|
200
219
|
end
|
|
@@ -203,16 +222,16 @@ private
|
|
|
203
222
|
# Internal: Allows to receive :javascript and :stylesheet as :type in helpers.
|
|
204
223
|
def extension_for_type(entry_type)
|
|
205
224
|
case entry_type
|
|
206
|
-
when :javascript then
|
|
207
|
-
when :stylesheet then
|
|
208
|
-
when :typescript then
|
|
225
|
+
when :javascript then "js"
|
|
226
|
+
when :stylesheet then "css"
|
|
227
|
+
when :typescript then "ts"
|
|
209
228
|
else entry_type
|
|
210
229
|
end
|
|
211
230
|
end
|
|
212
231
|
|
|
213
232
|
# Internal: Raises a detailed message when an entry is missing in the manifest.
|
|
214
233
|
def missing_entry_error(name, **options)
|
|
215
|
-
raise ViteRuby::MissingEntrypointError
|
|
234
|
+
raise ViteRuby::MissingEntrypointError.new(
|
|
216
235
|
file_name: resolve_entry_name(name, **options),
|
|
217
236
|
last_build: builder.last_build_metadata,
|
|
218
237
|
manifest: @manifest,
|
|
@@ -5,27 +5,26 @@
|
|
|
5
5
|
# NOTE: The complexity here is justified by the improved usability of providing
|
|
6
6
|
# a more specific error message depending on the situation.
|
|
7
7
|
class ViteRuby::MissingEntrypointError < ViteRuby::Error
|
|
8
|
-
|
|
9
|
-
def_delegators :@info, :file_name, :last_build, :manifest, :config
|
|
8
|
+
attr_reader :file_name, :last_build, :manifest, :config
|
|
10
9
|
|
|
11
|
-
def initialize(
|
|
12
|
-
@
|
|
10
|
+
def initialize(file_name:, last_build:, manifest:, config:)
|
|
11
|
+
@file_name, @last_build, @manifest, @config = file_name, last_build, manifest, config
|
|
13
12
|
super <<~MSG
|
|
14
|
-
Vite Ruby can't find #{
|
|
13
|
+
Vite Ruby can't find #{file_name} in the manifests.
|
|
15
14
|
|
|
16
15
|
Possible causes:
|
|
17
|
-
#{
|
|
16
|
+
#{possible_causes(last_build)}
|
|
18
17
|
:troubleshooting:
|
|
19
|
-
#{
|
|
20
|
-
#{
|
|
18
|
+
#{"Manifest files found:\n#{config.manifest_paths.map { |path| " #{path.relative_path_from(config.root)}" }.join("\n")}\n" if last_build.success}
|
|
19
|
+
#{"Last build in #{config.mode} mode:\n#{last_build.to_json}\n" if last_build.success}
|
|
21
20
|
MSG
|
|
22
21
|
end
|
|
23
22
|
|
|
24
23
|
def possible_causes(last_build)
|
|
25
24
|
if last_build.success == false
|
|
26
25
|
FAILED_BUILD_CAUSES
|
|
27
|
-
.sub(
|
|
28
|
-
.sub(
|
|
26
|
+
.sub(":mode:", config.mode)
|
|
27
|
+
.sub(":errors:", last_build.errors.to_s.gsub(/^(?!$)/, " "))
|
|
29
28
|
elsif config.auto_build
|
|
30
29
|
DEFAULT_CAUSES
|
|
31
30
|
else
|
data/lib/vite_ruby/runner.rb
CHANGED
|
@@ -12,7 +12,7 @@ class ViteRuby::Runner
|
|
|
12
12
|
cmd = command_for(argv)
|
|
13
13
|
return Kernel.exec(*cmd) if exec
|
|
14
14
|
|
|
15
|
-
log_or_noop = ->(line) { logger.info(
|
|
15
|
+
log_or_noop = ->(line) { logger.info("vite") { line } } unless config.hide_build_console_output
|
|
16
16
|
ViteRuby::IO.capture(*cmd, chdir: config.root, with_output: log_or_noop)
|
|
17
17
|
}
|
|
18
18
|
rescue Errno::ENOENT => error
|
|
@@ -28,24 +28,26 @@ private
|
|
|
28
28
|
# Internal: Returns an Array with the command to run.
|
|
29
29
|
def command_for(args)
|
|
30
30
|
[config.to_env(env)].tap do |cmd|
|
|
31
|
-
|
|
32
|
-
cmd.push(
|
|
33
|
-
cmd.push(
|
|
34
|
-
cmd.push(
|
|
35
|
-
cmd.push(*args)
|
|
36
|
-
cmd.push('--mode', config.mode) unless args.include?('--mode') || args.include?('-m')
|
|
31
|
+
exec_args, vite_args = args.partition { |arg| arg.start_with?("--node-options") }
|
|
32
|
+
cmd.push(*vite_executable(*exec_args))
|
|
33
|
+
cmd.push(*vite_args)
|
|
34
|
+
cmd.push("--mode", config.mode) unless args.include?("--mode") || args.include?("-m")
|
|
37
35
|
end
|
|
38
36
|
end
|
|
39
37
|
|
|
40
38
|
# Internal: Resolves to an executable for Vite.
|
|
41
|
-
def vite_executable
|
|
39
|
+
def vite_executable(*exec_args)
|
|
42
40
|
bin_path = config.vite_bin_path
|
|
43
|
-
return [bin_path] if File.exist?(bin_path)
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
41
|
+
return [bin_path] if bin_path && File.exist?(bin_path)
|
|
42
|
+
|
|
43
|
+
x = case config.package_manager
|
|
44
|
+
when "npm" then %w[npx]
|
|
45
|
+
when "pnpm" then %w[pnpm exec]
|
|
46
|
+
when "bun" then %w[bun x --bun]
|
|
47
|
+
when "yarn" then %w[yarn]
|
|
48
|
+
else raise ArgumentError, "Unknown package manager #{config.package_manager.inspect}"
|
|
49
49
|
end
|
|
50
|
+
|
|
51
|
+
[*x, *exec_args, "vite"]
|
|
50
52
|
end
|
|
51
53
|
end
|
data/lib/vite_ruby/version.rb
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
class ViteRuby
|
|
4
|
-
VERSION =
|
|
4
|
+
VERSION = "3.10.2"
|
|
5
5
|
|
|
6
6
|
# Internal: Versions used by default when running `vite install`.
|
|
7
|
-
DEFAULT_VITE_VERSION =
|
|
8
|
-
DEFAULT_PLUGIN_VERSION =
|
|
7
|
+
DEFAULT_VITE_VERSION = "^8.0.0"
|
|
8
|
+
DEFAULT_PLUGIN_VERSION = "^5.2.0"
|
|
9
9
|
end
|