vite_ruby 3.9.3 → 4.0.0.alpha1
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 +2 -432
- data/README.md +1 -1
- data/default.vite.json +2 -7
- data/exe/vite +3 -5
- data/lib/tasks/vite.rake +19 -56
- data/lib/vite_ruby/build.rb +17 -47
- data/lib/vite_ruby/builder.rb +34 -29
- data/lib/vite_ruby/cli/build.rb +4 -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 +8 -8
- data/lib/vite_ruby/cli/install.rb +38 -43
- data/lib/vite_ruby/cli/upgrade.rb +4 -4
- data/lib/vite_ruby/cli/upgrade_packages.rb +4 -3
- data/lib/vite_ruby/cli/version.rb +1 -1
- data/lib/vite_ruby/cli/vite.rb +9 -24
- data/lib/vite_ruby/cli.rb +8 -21
- data/lib/vite_ruby/commands.rb +75 -30
- data/lib/vite_ruby/compatibility_check.rb +8 -8
- data/lib/vite_ruby/config.rb +37 -68
- data/lib/vite_ruby/dev_server_proxy.rb +24 -30
- data/lib/vite_ruby/error.rb +1 -1
- data/lib/vite_ruby/io.rb +4 -4
- data/lib/vite_ruby/manifest.rb +32 -46
- data/lib/vite_ruby/missing_entrypoint_error.rb +14 -22
- data/lib/vite_ruby/missing_executable_error.rb +1 -1
- data/lib/vite_ruby/runner.rb +12 -20
- data/lib/vite_ruby/version.rb +3 -3
- data/lib/vite_ruby.rb +34 -49
- metadata +12 -48
- data/lib/vite_ruby/cli/ssr.rb +0 -27
data/lib/vite_ruby/commands.rb
CHANGED
|
@@ -9,7 +9,7 @@ class ViteRuby::Commands
|
|
|
9
9
|
|
|
10
10
|
# Public: Defaults to production, and exits if the build fails.
|
|
11
11
|
def build_from_task(*args)
|
|
12
|
-
with_node_env(ENV.fetch(
|
|
12
|
+
with_node_env(ENV.fetch('NODE_ENV', 'production')) {
|
|
13
13
|
ensure_log_goes_to_stdout {
|
|
14
14
|
build(*args) || exit!
|
|
15
15
|
}
|
|
@@ -23,30 +23,52 @@ class ViteRuby::Commands
|
|
|
23
23
|
|
|
24
24
|
# Public: Removes all build cache and previously compiled assets.
|
|
25
25
|
def clobber
|
|
26
|
-
dirs = [config.build_output_dir, config.
|
|
26
|
+
dirs = [config.build_output_dir, config.build_cache_dir, config.vite_cache_dir]
|
|
27
27
|
dirs.each { |dir| dir.rmtree if dir.exist? }
|
|
28
|
-
$stdout.puts "Removed vite cache and output dirs:\n\t#{dirs.join("\n\t")}"
|
|
28
|
+
$stdout.puts "Removed vite cache and output dirs:\n\t#{ dirs.join("\n\t") }"
|
|
29
29
|
end
|
|
30
30
|
|
|
31
|
-
#
|
|
32
|
-
def
|
|
33
|
-
|
|
34
|
-
|
|
31
|
+
# Public: Receives arguments from a rake task.
|
|
32
|
+
def clean_from_task(args)
|
|
33
|
+
ensure_log_goes_to_stdout {
|
|
34
|
+
clean(keep_up_to: Integer(args.keep || 2), age_in_seconds: Integer(args.age || 3600))
|
|
35
|
+
}
|
|
35
36
|
end
|
|
36
37
|
|
|
37
|
-
#
|
|
38
|
-
|
|
39
|
-
|
|
38
|
+
# Public: Cleanup old assets in the output directory.
|
|
39
|
+
#
|
|
40
|
+
# keep_up_to - Max amount of backups to preserve.
|
|
41
|
+
# age_in_seconds - Amount of time to look back in order to preserve them.
|
|
42
|
+
#
|
|
43
|
+
# NOTE: By default keeps the last version, or 2 if created in the past hour.
|
|
44
|
+
#
|
|
45
|
+
# Examples:
|
|
46
|
+
# To force only 1 backup to be kept: clean(1, 0)
|
|
47
|
+
# To only keep files created within the last 10 minutes: clean(0, 600)
|
|
48
|
+
def clean(keep_up_to: 2, age_in_seconds: 3600)
|
|
49
|
+
return false unless may_clean?
|
|
50
|
+
|
|
51
|
+
versions
|
|
52
|
+
.each_with_index
|
|
53
|
+
.drop_while { |(mtime, _), index|
|
|
54
|
+
max_age = [0, Time.now - Time.at(mtime)].max
|
|
55
|
+
max_age < age_in_seconds || index < keep_up_to
|
|
56
|
+
}
|
|
57
|
+
.each do |(_, files), _|
|
|
58
|
+
clean_files(files)
|
|
59
|
+
end
|
|
60
|
+
true
|
|
40
61
|
end
|
|
41
62
|
|
|
42
|
-
# Internal:
|
|
43
|
-
def
|
|
44
|
-
`
|
|
63
|
+
# Internal: Installs the binstub for the CLI in the appropriate path.
|
|
64
|
+
def install_binstubs
|
|
65
|
+
`bundle binstub vite_ruby --path #{ config.root.join('bin') }`
|
|
66
|
+
`bundle config --delete bin`
|
|
45
67
|
end
|
|
46
68
|
|
|
47
69
|
# Internal: Verifies if ViteRuby is properly installed.
|
|
48
70
|
def verify_install
|
|
49
|
-
unless File.exist?(config.root.join(
|
|
71
|
+
unless File.exist?(config.root.join('bin/vite'))
|
|
50
72
|
warn <<~WARN
|
|
51
73
|
|
|
52
74
|
vite binstub not found.
|
|
@@ -59,7 +81,7 @@ class ViteRuby::Commands
|
|
|
59
81
|
unless config_path.exist?
|
|
60
82
|
warn <<~WARN
|
|
61
83
|
|
|
62
|
-
Configuration #{config_path} file for vite-plugin-ruby not found.
|
|
84
|
+
Configuration #{ config_path } file for vite-plugin-ruby not found.
|
|
63
85
|
Make sure `bundle exec vite install` has run successfully before running dependent tasks.
|
|
64
86
|
WARN
|
|
65
87
|
exit!
|
|
@@ -68,24 +90,24 @@ class ViteRuby::Commands
|
|
|
68
90
|
|
|
69
91
|
# Internal: Prints information about ViteRuby's environment.
|
|
70
92
|
def print_info
|
|
71
|
-
config.
|
|
72
|
-
$stdout.puts "bin/vite present?: #{File.exist?
|
|
93
|
+
Dir.chdir(config.root) do
|
|
94
|
+
$stdout.puts "bin/vite present?: #{ File.exist? 'bin/vite' }"
|
|
73
95
|
|
|
74
|
-
$stdout.puts "vite_ruby: #{ViteRuby::VERSION}"
|
|
96
|
+
$stdout.puts "vite_ruby: #{ ViteRuby::VERSION }"
|
|
75
97
|
ViteRuby.framework_libraries.each do |framework, library|
|
|
76
|
-
$stdout.puts "#{library.name}: #{library.version}"
|
|
77
|
-
$stdout.puts "#{framework}: #{Gem.loaded_specs[framework]&.version}"
|
|
98
|
+
$stdout.puts "#{ library.name }: #{ library.version }"
|
|
99
|
+
$stdout.puts "#{ framework }: #{ Gem.loaded_specs[framework]&.version }"
|
|
78
100
|
end
|
|
79
101
|
|
|
80
|
-
$stdout.puts "
|
|
81
|
-
$stdout.puts "
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
$stdout.puts "
|
|
102
|
+
$stdout.puts "node: #{ `node --version` }"
|
|
103
|
+
$stdout.puts "npm: #{ `npm --version` }"
|
|
104
|
+
$stdout.puts "yarn: #{ `yarn --version` rescue nil }"
|
|
105
|
+
$stdout.puts "pnpm: #{ `pnpm --version` rescue nil }"
|
|
106
|
+
$stdout.puts "ruby: #{ `ruby --version` }"
|
|
85
107
|
|
|
86
108
|
$stdout.puts "\n"
|
|
87
109
|
packages = `npm ls vite vite-plugin-ruby`
|
|
88
|
-
packages_msg = packages.include?(
|
|
110
|
+
packages_msg = packages.include?('vite@') ? "installed packages:\n#{ packages }" : '❌ Check that vite and vite-plugin-ruby have been added as development dependencies and installed.'
|
|
89
111
|
$stdout.puts packages_msg
|
|
90
112
|
|
|
91
113
|
ViteRuby::CompatibilityCheck.verify_plugin_version(config.root)
|
|
@@ -98,19 +120,42 @@ private
|
|
|
98
120
|
|
|
99
121
|
def_delegators :@vite_ruby, :config, :builder, :manifest, :logger, :logger=
|
|
100
122
|
|
|
123
|
+
def may_clean?
|
|
124
|
+
config.build_output_dir.exist? && config.manifest_path.exist?
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def clean_files(files)
|
|
128
|
+
files.select { |file| File.file?(file) }.each do |file|
|
|
129
|
+
File.delete(file)
|
|
130
|
+
logger.info("Removed #{ file }")
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def versions
|
|
135
|
+
all_files = Dir.glob("#{ config.build_output_dir }/**/*")
|
|
136
|
+
entries = all_files - [config.manifest_path] - current_version_files
|
|
137
|
+
entries.reject { |file| File.directory?(file) }
|
|
138
|
+
.group_by { |file| File.mtime(file).utc.to_i }
|
|
139
|
+
.sort.reverse
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def current_version_files
|
|
143
|
+
Dir.glob(manifest.refresh.values.map { |value| config.build_output_dir.join("#{ value['file'] }*") })
|
|
144
|
+
end
|
|
145
|
+
|
|
101
146
|
def with_node_env(env)
|
|
102
|
-
original = ENV[
|
|
103
|
-
ENV[
|
|
147
|
+
original = ENV['NODE_ENV']
|
|
148
|
+
ENV['NODE_ENV'] = env
|
|
104
149
|
yield
|
|
105
150
|
ensure
|
|
106
|
-
ENV[
|
|
151
|
+
ENV['NODE_ENV'] = original
|
|
107
152
|
end
|
|
108
153
|
|
|
109
154
|
def ensure_log_goes_to_stdout
|
|
110
155
|
old_logger, original_sync = logger, $stdout.sync
|
|
111
156
|
|
|
112
157
|
$stdout.sync = true
|
|
113
|
-
self.logger = Logger.new($stdout, formatter: proc { |_, _, progname, msg|
|
|
158
|
+
self.logger = Logger.new($stdout, formatter: proc { |_, _, progname, msg| progname == 'vite' ? msg : "#{ msg }\n" })
|
|
114
159
|
yield
|
|
115
160
|
ensure
|
|
116
161
|
self.logger, $stdout.sync = old_logger, original_sync
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
3
|
+
require 'json'
|
|
4
4
|
|
|
5
5
|
# Internal: Verifies that the installed vite-plugin-ruby version is compatible
|
|
6
6
|
# with the current version of vite_ruby.
|
|
@@ -11,9 +11,9 @@ module ViteRuby::CompatibilityCheck
|
|
|
11
11
|
class << self
|
|
12
12
|
# Public: Attempt to verify that the vite-plugin-ruby version is compatible.
|
|
13
13
|
def verify_plugin_version(root)
|
|
14
|
-
package = JSON.parse(root.join(
|
|
15
|
-
requirement = package.dig(
|
|
16
|
-
|
|
14
|
+
package = JSON.parse(root.join('package.json').read) rescue {}
|
|
15
|
+
requirement = package.dig('devDependencies', 'vite-plugin-ruby') ||
|
|
16
|
+
package.dig('dependencies', 'vite-plugin-ruby')
|
|
17
17
|
|
|
18
18
|
raise_unless_satisfied(requirement, ViteRuby::DEFAULT_PLUGIN_VERSION)
|
|
19
19
|
end
|
|
@@ -22,9 +22,9 @@ module ViteRuby::CompatibilityCheck
|
|
|
22
22
|
def raise_unless_satisfied(npm_req, ruby_req)
|
|
23
23
|
unless compatible_plugin?(npm_req, ruby_req)
|
|
24
24
|
raise ArgumentError, <<~ERROR
|
|
25
|
-
vite-plugin-ruby@#{npm_req} might not be compatible with vite_ruby-#{ViteRuby::VERSION}
|
|
25
|
+
vite-plugin-ruby@#{ npm_req } might not be compatible with vite_ruby-#{ ViteRuby::VERSION }
|
|
26
26
|
|
|
27
|
-
You may disable this check if needed: https://vite-ruby.netlify.app/config/#
|
|
27
|
+
You may disable this check if needed: https://vite-ruby.netlify.app/config/#skipCompatibilityCheck
|
|
28
28
|
|
|
29
29
|
You may upgrade both by running:
|
|
30
30
|
|
|
@@ -37,12 +37,12 @@ module ViteRuby::CompatibilityCheck
|
|
|
37
37
|
# requirement.
|
|
38
38
|
def compatible_plugin?(npm_req, ruby_req)
|
|
39
39
|
npm_req, ruby_req = [npm_req, ruby_req]
|
|
40
|
-
.map { |req| Gem::Requirement.new(req.sub(
|
|
40
|
+
.map { |req| Gem::Requirement.new(req.sub('^', '~>')) }
|
|
41
41
|
|
|
42
42
|
current_version = npm_req.requirements.first.second
|
|
43
43
|
|
|
44
44
|
ruby_req.satisfied_by?(current_version)
|
|
45
|
-
rescue
|
|
45
|
+
rescue StandardError
|
|
46
46
|
true
|
|
47
47
|
end
|
|
48
48
|
end
|
data/lib/vite_ruby/config.rb
CHANGED
|
@@ -1,36 +1,26 @@
|
|
|
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
|
-
def origin
|
|
9
|
-
"#{protocol}://#{host_with_port}"
|
|
10
|
-
end
|
|
11
|
-
|
|
12
8
|
def protocol
|
|
13
|
-
https ?
|
|
9
|
+
https ? 'https' : 'http'
|
|
14
10
|
end
|
|
15
11
|
|
|
16
12
|
def host_with_port
|
|
17
|
-
"#{host}:#{port}"
|
|
13
|
+
"#{ host }:#{ port }"
|
|
18
14
|
end
|
|
19
15
|
|
|
20
|
-
# Internal: Path
|
|
21
|
-
def
|
|
22
|
-
|
|
23
|
-
# NOTE: Generated by Vite when `manifest: true`, which vite-plugin-ruby enables.
|
|
24
|
-
build_output_dir.join(".vite/manifest.json"),
|
|
25
|
-
|
|
26
|
-
# NOTE: Path where vite-plugin-ruby outputs the assets manifest file.
|
|
27
|
-
build_output_dir.join(".vite/manifest-assets.json"),
|
|
28
|
-
]
|
|
16
|
+
# Internal: Path where Vite outputs the manifest file.
|
|
17
|
+
def manifest_path
|
|
18
|
+
build_output_dir.join('manifest.json')
|
|
29
19
|
end
|
|
30
20
|
|
|
31
|
-
# Internal: Path
|
|
32
|
-
def
|
|
33
|
-
|
|
21
|
+
# Internal: Path where vite-plugin-ruby outputs the assets manifest file.
|
|
22
|
+
def assets_manifest_path
|
|
23
|
+
build_output_dir.join('manifest-assets.json')
|
|
34
24
|
end
|
|
35
25
|
|
|
36
26
|
# Public: The directory where Vite will store the built assets.
|
|
@@ -45,7 +35,7 @@ class ViteRuby::Config
|
|
|
45
35
|
|
|
46
36
|
# Internal: The directory where Vite stores its processing cache.
|
|
47
37
|
def vite_cache_dir
|
|
48
|
-
root.join(
|
|
38
|
+
root.join('node_modules/.vite')
|
|
49
39
|
end
|
|
50
40
|
|
|
51
41
|
# Public: The directory that Vite uses as root.
|
|
@@ -55,64 +45,46 @@ class ViteRuby::Config
|
|
|
55
45
|
|
|
56
46
|
# Public: Loads an optional config/vite.rb file that can modify ViteRuby.env
|
|
57
47
|
def load_ruby_config
|
|
58
|
-
rb_config_path = File.expand_path(config_path.sub(/.json$/,
|
|
48
|
+
rb_config_path = File.expand_path(config_path.sub(/.json$/, '.rb'), root)
|
|
59
49
|
load rb_config_path if File.exist?(rb_config_path)
|
|
60
50
|
end
|
|
61
51
|
|
|
62
52
|
# Public: Sets additional environment variables for vite-plugin-ruby.
|
|
63
|
-
def to_env
|
|
53
|
+
def to_env
|
|
64
54
|
CONFIGURABLE_WITH_ENV.each_with_object({}) do |option, env|
|
|
65
55
|
unless (value = @config[option]).nil?
|
|
66
|
-
env["#{ViteRuby::ENV_PREFIX}_#{option.upcase}"] = value.to_s
|
|
56
|
+
env["#{ ViteRuby::ENV_PREFIX }_#{ option.upcase }"] = value.to_s
|
|
67
57
|
end
|
|
68
|
-
end.merge(
|
|
58
|
+
end.merge(ViteRuby.env)
|
|
69
59
|
end
|
|
70
60
|
|
|
71
61
|
# Internal: Files and directories that should be watched for changes.
|
|
72
62
|
def watched_paths
|
|
73
63
|
[
|
|
74
64
|
*(watch_additional_paths + additional_entrypoints).reject { |dir|
|
|
75
|
-
dir.start_with?(
|
|
65
|
+
dir.start_with?('~/') || dir.start_with?(source_code_dir)
|
|
76
66
|
},
|
|
77
|
-
"#{source_code_dir}/**/*",
|
|
78
|
-
config_path.sub(/.json$/,
|
|
67
|
+
"#{ source_code_dir }/**/*",
|
|
68
|
+
config_path.sub(/.json$/, '.{rb,json}'),
|
|
79
69
|
*DEFAULT_WATCHED_PATHS,
|
|
80
70
|
].freeze
|
|
81
71
|
end
|
|
82
72
|
|
|
83
|
-
# Internal: Changes the current directory to the root dir.
|
|
84
|
-
def within_root(&block)
|
|
85
|
-
Dir.chdir(File.expand_path(root), &block)
|
|
86
|
-
end
|
|
87
|
-
|
|
88
73
|
private
|
|
89
74
|
|
|
90
75
|
# Internal: Coerces all the configuration values, in case they were passed
|
|
91
76
|
# as environment variables which are always strings.
|
|
92
77
|
def coerce_values(config)
|
|
93
|
-
config[
|
|
94
|
-
config[
|
|
95
|
-
config[
|
|
96
|
-
config[
|
|
97
|
-
config
|
|
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)
|
|
78
|
+
config['mode'] = config['mode'].to_s
|
|
79
|
+
config['port'] = config['port'].to_i
|
|
80
|
+
config['root'] = Pathname.new(config['root'])
|
|
81
|
+
config['build_cache_dir'] = config['root'].join(config['build_cache_dir'])
|
|
82
|
+
coerce_booleans(config, 'auto_build', 'hide_build_console_output', 'https', 'skip_compatibility_check')
|
|
101
83
|
end
|
|
102
84
|
|
|
103
85
|
# Internal: Coerces configuration options to boolean.
|
|
104
86
|
def coerce_booleans(config, *names)
|
|
105
|
-
|
|
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"
|
|
87
|
+
names.each { |name| config[name] = [true, 'true'].include?(config[name]) }
|
|
116
88
|
end
|
|
117
89
|
|
|
118
90
|
def initialize(attrs)
|
|
@@ -126,8 +98,8 @@ private
|
|
|
126
98
|
# Public: Returns the project configuration for Vite.
|
|
127
99
|
def resolve_config(**attrs)
|
|
128
100
|
config = config_defaults.merge(attrs.transform_keys(&:to_s))
|
|
129
|
-
file_path = File.join(config[
|
|
130
|
-
file_config = config_from_file(file_path, mode: config[
|
|
101
|
+
file_path = File.join(config['root'], config['config_path'])
|
|
102
|
+
file_config = config_from_file(file_path, mode: config['mode'])
|
|
131
103
|
new DEFAULT_CONFIG.merge(file_config).merge(config_from_env).merge(config)
|
|
132
104
|
end
|
|
133
105
|
|
|
@@ -135,21 +107,21 @@ private
|
|
|
135
107
|
|
|
136
108
|
# Internal: Converts camelCase to snake_case.
|
|
137
109
|
SNAKE_CASE = ->(camel_cased_word) {
|
|
138
|
-
camel_cased_word.to_s.gsub(
|
|
110
|
+
camel_cased_word.to_s.gsub(/::/, '/')
|
|
139
111
|
.gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
|
|
140
112
|
.gsub(/([a-z\d])([A-Z])/, '\1_\2')
|
|
141
|
-
.tr(
|
|
113
|
+
.tr('-', '_')
|
|
142
114
|
.downcase
|
|
143
115
|
}
|
|
144
116
|
|
|
145
117
|
# Internal: Default values for a Ruby application.
|
|
146
|
-
def config_defaults(asset_host: nil, mode: ENV.fetch(
|
|
118
|
+
def config_defaults(asset_host: nil, mode: ENV.fetch('RACK_ENV', 'development'), root: Dir.pwd)
|
|
147
119
|
{
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
}
|
|
120
|
+
'asset_host' => option_from_env('asset_host') || asset_host,
|
|
121
|
+
'config_path' => option_from_env('config_path') || DEFAULT_CONFIG.fetch('config_path'),
|
|
122
|
+
'mode' => option_from_env('mode') || mode,
|
|
123
|
+
'root' => option_from_env('root') || root,
|
|
124
|
+
}
|
|
153
125
|
end
|
|
154
126
|
|
|
155
127
|
# Internal: Used to load a JSON file from the specified path.
|
|
@@ -163,7 +135,7 @@ private
|
|
|
163
135
|
|
|
164
136
|
# Internal: Retrieves a configuration option from environment variables.
|
|
165
137
|
def option_from_env(name)
|
|
166
|
-
ViteRuby.env["#{ViteRuby::ENV_PREFIX}_#{name.upcase}"]
|
|
138
|
+
ViteRuby.env["#{ ViteRuby::ENV_PREFIX }_#{ name.upcase }"]
|
|
167
139
|
end
|
|
168
140
|
|
|
169
141
|
# Internal: Extracts the configuration options provided as env vars.
|
|
@@ -178,16 +150,16 @@ private
|
|
|
178
150
|
# Internal: Loads the configuration options provided in a JSON file.
|
|
179
151
|
def config_from_file(path, mode:)
|
|
180
152
|
multi_env_config = load_json(path)
|
|
181
|
-
multi_env_config.fetch(
|
|
153
|
+
multi_env_config.fetch('all', {})
|
|
182
154
|
.merge(multi_env_config.fetch(mode, {}))
|
|
183
155
|
rescue Errno::ENOENT => error
|
|
184
|
-
$stderr << "Check that your vite.json configuration file is available in the load path:\n\n\t#{error.message}\n\n"
|
|
156
|
+
$stderr << "Check that your vite.json configuration file is available in the load path:\n\n\t#{ error.message }\n\n"
|
|
185
157
|
{}
|
|
186
158
|
end
|
|
187
159
|
end
|
|
188
160
|
|
|
189
161
|
# Internal: Shared configuration with the Vite plugin for Ruby.
|
|
190
|
-
DEFAULT_CONFIG = load_json("#{__dir__}/../../default.vite.json").freeze
|
|
162
|
+
DEFAULT_CONFIG = load_json("#{ __dir__ }/../../default.vite.json").freeze
|
|
191
163
|
|
|
192
164
|
# Internal: Configuration options that can not be provided as env vars.
|
|
193
165
|
NOT_CONFIGURABLE_WITH_ENV = %w[additional_entrypoints watch_additional_paths].freeze
|
|
@@ -197,15 +169,12 @@ private
|
|
|
197
169
|
|
|
198
170
|
# Internal: If any of these files is modified the build won't be skipped.
|
|
199
171
|
DEFAULT_WATCHED_PATHS = %w[
|
|
200
|
-
bun.lockb
|
|
201
172
|
package-lock.json
|
|
202
173
|
package.json
|
|
203
174
|
pnpm-lock.yaml
|
|
204
175
|
postcss.config.js
|
|
205
176
|
tailwind.config.js
|
|
206
177
|
vite.config.js
|
|
207
|
-
vite.config.mjs
|
|
208
|
-
vite.config.mts
|
|
209
178
|
vite.config.ts
|
|
210
179
|
windi.config.ts
|
|
211
180
|
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(env)
|
|
21
21
|
else
|
|
22
22
|
@app.call(env)
|
|
23
23
|
end
|
|
@@ -30,47 +30,41 @@ 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(
|
|
41
|
-
.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
|
+
.sub(/(\.(?!min|module)\w+)\.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[
|
|
57
|
-
return true if path.start_with?(
|
|
58
|
-
|
|
59
|
-
true if file_in_vite_root?(path) # Fallback if Vite can serve the file
|
|
56
|
+
path = normalize_uri(env['PATH_INFO'])
|
|
57
|
+
return true if path.start_with?(vite_asset_url_prefix) # Vite asset
|
|
58
|
+
return true if path.start_with?(VITE_DEPENDENCY_PREFIX) # Packages and imports
|
|
59
|
+
return true if file_in_vite_root?(path) # Fallback if Vite can serve the file
|
|
60
60
|
end
|
|
61
61
|
|
|
62
|
-
# NOTE: When using an empty 'public_output_dir', we need to rely on a
|
|
63
|
-
# filesystem check to check whether Vite should serve the request.
|
|
64
62
|
def file_in_vite_root?(path)
|
|
65
|
-
path.include?(
|
|
66
|
-
config.vite_root_dir.join(path.start_with?(
|
|
63
|
+
path.include?('.') && # Check for extension, avoid filesystem if possible.
|
|
64
|
+
config.vite_root_dir.join(path.start_with?('/') ? path[1..-1] : path).file?
|
|
67
65
|
end
|
|
68
66
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
#
|
|
72
|
-
# If the path starts with that prefix, it will be redirected to Vite.
|
|
73
|
-
def vite_url_prefix
|
|
74
|
-
@vite_url_prefix ||= config.public_output_dir.empty? ? VITE_DEPENDENCY_PREFIX : "/#{config.public_output_dir}/"
|
|
67
|
+
def vite_asset_url_prefix
|
|
68
|
+
@vite_asset_url_prefix ||= config.public_output_dir.empty? ? "\0" : "/#{ config.public_output_dir }/"
|
|
75
69
|
end
|
|
76
70
|
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|
|
|
@@ -15,13 +15,13 @@ module ViteRuby::IO
|
|
|
15
15
|
stdin.close
|
|
16
16
|
out = Thread.new { read_lines(stdout, &with_output) }
|
|
17
17
|
err = Thread.new { stderr.read }
|
|
18
|
-
[out.value, err.value
|
|
18
|
+
[out.value, err.value, wait_threads.value]
|
|
19
19
|
}
|
|
20
20
|
end
|
|
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
|