vite_rails 1.0.6 → 1.0.11

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.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +24 -0
  3. data/CONTRIBUTING.md +0 -1
  4. data/README.md +43 -70
  5. data/lib/install/config/vite.config.ts +1 -1
  6. data/lib/install/javascript/entrypoints/application.js +8 -4
  7. data/lib/install/template.rb +3 -3
  8. data/lib/tasks/vite/build.rake +12 -6
  9. data/lib/tasks/vite/clean.rake +1 -3
  10. data/lib/tasks/vite/install_dependencies.rake +3 -9
  11. data/lib/tasks/vite/verify_install.rake +3 -3
  12. data/lib/vite_rails.rb +23 -34
  13. data/lib/vite_rails/builder.rb +11 -13
  14. data/lib/vite_rails/commands.rb +51 -10
  15. data/lib/vite_rails/config.rb +65 -35
  16. data/lib/vite_rails/dev_server_proxy.rb +26 -18
  17. data/lib/vite_rails/helper.rb +17 -8
  18. data/lib/vite_rails/manifest.rb +14 -12
  19. data/lib/vite_rails/runner.rb +3 -6
  20. data/lib/vite_rails/version.rb +1 -1
  21. data/package.json +9 -2
  22. data/package/default.vite.json +2 -1
  23. data/test/builder_test.rb +27 -22
  24. data/test/commands_test.rb +67 -0
  25. data/test/config_test.rb +133 -0
  26. data/test/dev_server_proxy_test.rb +102 -0
  27. data/test/dev_server_test.rb +0 -30
  28. data/test/engine_rake_tasks_test.rb +56 -17
  29. data/test/helper_test.rb +37 -105
  30. data/test/manifest_test.rb +33 -29
  31. data/test/mode_test.rb +6 -11
  32. data/test/mounted_app/test/dummy/config/vite.json +5 -11
  33. data/test/mounted_app/test/dummy/package.json +5 -4
  34. data/test/mounted_app/test/dummy/yarn.lock +208 -0
  35. data/test/rake_tasks_test.rb +7 -21
  36. data/test/runner_test.rb +31 -0
  37. data/test/test_app/app/frontend/entrypoints/application.js +2 -0
  38. data/test/test_app/config/vite.json +0 -2
  39. data/test/test_app/config/vite_additional_paths.json +5 -0
  40. data/test/test_app/config/vite_public_dir.json +5 -0
  41. data/test/test_app/public/vite-production/manifest.json +22 -0
  42. data/test/test_helper.rb +48 -14
  43. metadata +23 -25
  44. data/test/command_test.rb +0 -35
  45. data/test/configuration_test.rb +0 -80
  46. data/test/dev_server_runner_test.rb +0 -83
  47. data/test/test_app/app/javascript/entrypoints/application.js +0 -10
  48. data/test/test_app/app/javascript/entrypoints/multi_entry.css +0 -4
  49. data/test/test_app/app/javascript/entrypoints/multi_entry.js +0 -4
  50. data/test/test_app/config/vite_public_root.yml +0 -20
  51. data/test/test_app/public/vite/manifest.json +0 -36
  52. data/test/vite_runner_test.rb +0 -59
  53. data/test/webpacker_test.rb +0 -15
@@ -11,6 +11,15 @@ class ViteRails::Commands
11
11
  manifest.refresh
12
12
  end
13
13
 
14
+ # Public: Defaults to production, and exits if the build fails.
15
+ def build_from_rake
16
+ with_node_env(ENV.fetch('NODE_ENV', 'production')) {
17
+ ensure_log_goes_to_stdout {
18
+ build || exit!
19
+ }
20
+ }
21
+ end
22
+
14
23
  # Public: Builds all assets that are managed by Vite, from the entrypoints.
15
24
  def build
16
25
  builder.build.tap { manifest.refresh }
@@ -20,6 +29,14 @@ class ViteRails::Commands
20
29
  def clobber
21
30
  config.build_output_dir.rmtree if config.build_output_dir.exist?
22
31
  config.build_cache_dir.rmtree if config.build_cache_dir.exist?
32
+ config.vite_cache_dir.rmtree if config.vite_cache_dir.exist?
33
+ end
34
+
35
+ # Public: Receives arguments from a rake task.
36
+ def clean_from_rake(args)
37
+ ensure_log_goes_to_stdout {
38
+ clean(keep_up_to: Integer(args.keep || 2), age_in_seconds: Integer(args.age || 3600))
39
+ }
23
40
  end
24
41
 
25
42
  # Public: Cleanup old assets in the output directory.
@@ -33,21 +50,16 @@ class ViteRails::Commands
33
50
  # To force only 1 backup to be kept: clean(1, 0)
34
51
  # To only keep files created within the last 10 minutes: clean(0, 600)
35
52
  def clean(keep_up_to: 2, age_in_seconds: 3600)
36
- return false unless config.build_output_dir.exist? && config.manifest_path.exist?
53
+ return false unless may_clean?
37
54
 
38
- versions.sort.reverse
55
+ versions
39
56
  .each_with_index
40
57
  .drop_while { |(mtime, _), index|
41
58
  max_age = [0, Time.now - Time.at(mtime)].max
42
59
  max_age < age_in_seconds || index < keep_up_to
43
60
  }
44
- .each do |(_, files), _index|
45
- files.each do |file|
46
- next unless File.file?(file)
47
-
48
- File.delete(file)
49
- logger.info("Removed #{ file }")
50
- end
61
+ .each do |(_, files), _|
62
+ clean_files(files)
51
63
  end
52
64
  true
53
65
  end
@@ -56,13 +68,42 @@ private
56
68
 
57
69
  delegate :config, :builder, :manifest, :logger, to: :@vite_rails
58
70
 
71
+ def may_clean?
72
+ config.build_output_dir.exist? && config.manifest_path.exist?
73
+ end
74
+
75
+ def clean_files(files)
76
+ files.select { |file| File.file?(file) }.each do |file|
77
+ File.delete(file)
78
+ logger.info("Removed #{ file }")
79
+ end
80
+ end
81
+
59
82
  def versions
60
83
  all_files = Dir.glob("#{ config.build_output_dir }/**/*")
61
84
  entries = all_files - [config.manifest_path] - current_version_files
62
- entries.reject { |file| File.directory?(file) }.group_by { |file| File.mtime(file).utc.to_i }
85
+ entries.reject { |file| File.directory?(file) }
86
+ .group_by { |file| File.mtime(file).utc.to_i }
87
+ .sort.reverse
63
88
  end
64
89
 
65
90
  def current_version_files
66
91
  Dir.glob(manifest.refresh.values.map { |value| config.build_output_dir.join("#{ value['file'] }*") })
67
92
  end
93
+
94
+ def with_node_env(env)
95
+ original = ENV['NODE_ENV']
96
+ ENV['NODE_ENV'] = env
97
+ yield
98
+ ensure
99
+ ENV['NODE_ENV'] = original
100
+ end
101
+
102
+ def ensure_log_goes_to_stdout
103
+ old_logger = ViteRails.logger
104
+ ViteRails.logger = ActiveSupport::Logger.new(STDOUT)
105
+ yield
106
+ ensure
107
+ ViteRails.logger = old_logger
108
+ end
68
109
  end
@@ -1,16 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'json'
4
+
3
5
  # Public: Allows to resolve configuration sourced from `config/vite.json` and
4
6
  # environment variables, combining them with the default options.
5
7
  class ViteRails::Config
6
8
  delegate :as_json, :inspect, to: :@config
7
9
 
8
- def initialize(config)
9
- @config = config.tap { coerce_values(config) }.freeze
10
-
11
- config.each_key do |option|
12
- define_singleton_method(option) { @config[option] }
13
- end
10
+ def initialize(attrs)
11
+ @config = attrs.tap { |config| coerce_values(config) }.freeze
14
12
  end
15
13
 
16
14
  def protocol
@@ -28,7 +26,26 @@ class ViteRails::Config
28
26
 
29
27
  # Public: The directory where Vite will store the built assets.
30
28
  def build_output_dir
31
- public_dir.join(public_output_dir)
29
+ root.join(public_dir, public_output_dir)
30
+ end
31
+
32
+ # Public: The directory where the entries are located.
33
+ def resolved_entrypoints_dir
34
+ root.join(source_code_dir, entrypoints_dir)
35
+ end
36
+
37
+ # Internal: The directory where Vite stores its processing cache.
38
+ def vite_cache_dir
39
+ root.join('node_modules/.vite')
40
+ end
41
+
42
+ # Public: Sets additional environment variables for vite-plugin-ruby.
43
+ def to_env
44
+ CONFIGURABLE_WITH_ENV.each_with_object({}) do |option, env|
45
+ unless (value = @config[option]).nil?
46
+ env["#{ ViteRails::ENV_PREFIX }_#{ option.upcase }"] = value.to_s
47
+ end
48
+ end.merge(ViteRails.env)
32
49
  end
33
50
 
34
51
  private
@@ -36,10 +53,11 @@ private
36
53
  # Internal: Coerces all the configuration values, in case they were passed
37
54
  # as environment variables which are always strings.
38
55
  def coerce_values(config)
39
- coerce_booleans(config, 'auto_build', 'https')
40
- coerce_paths(config, 'assets_dir', 'build_cache_dir', 'config_path', 'public_dir', 'source_code_dir', 'public_output_dir', 'root')
56
+ config['mode'] = config['mode'].to_s
41
57
  config['port'] = config['port'].to_i
42
- config['root'] ||= Rails.root
58
+ config['root'] = Pathname.new(config['root'])
59
+ config['build_cache_dir'] = config['root'].join(config['build_cache_dir'])
60
+ coerce_booleans(config, 'auto_build', 'hide_build_console_output', 'https')
43
61
  end
44
62
 
45
63
  # Internal: Coerces configuration options to boolean.
@@ -47,58 +65,70 @@ private
47
65
  names.each { |name| config[name] = [true, 'true'].include?(config[name]) }
48
66
  end
49
67
 
50
- # Internal: Converts configuration options to pathname.
51
- def coerce_paths(config, *names)
52
- names.each { |name| config[name] = Pathname.new(config[name]) unless config[name].nil? }
53
- end
54
-
55
68
  class << self
56
69
  # Public: Returns the project configuration for Vite.
57
- def resolve_config
58
- new DEFAULT_CONFIG.merge(config_from_file).merge(config_from_env)
59
- rescue Errno::ENOENT => error
60
- warn "Check that your vite.json configuration file is available in the load path. #{ error.message }"
61
- new DEFAULT_CONFIG.merge(config_from_env)
70
+ def resolve_config(**attrs)
71
+ config = attrs.transform_keys(&:to_s).reverse_merge(config_defaults)
72
+ file_path = File.join(config['root'], config['config_path'])
73
+ file_config = config_from_file(file_path, mode: config['mode'])
74
+ new DEFAULT_CONFIG.merge(file_config).merge(config_from_env).merge(config)
62
75
  end
63
76
 
64
77
  private
65
78
 
79
+ # Internal: Default values for a Rails application.
80
+ def config_defaults
81
+ {
82
+ 'asset_host' => option_from_env('asset_host') || Rails.application&.config&.action_controller&.asset_host,
83
+ 'config_path' => option_from_env('config_path') || DEFAULT_CONFIG.fetch('config_path'),
84
+ 'mode' => option_from_env('mode') || Rails.env.to_s,
85
+ 'root' => option_from_env('root') || Rails.root || Dir.pwd,
86
+ }
87
+ end
88
+
66
89
  # Internal: Used to load a JSON file from the specified path.
67
90
  def load_json(path)
68
91
  JSON.parse(File.read(File.expand_path(path))).deep_transform_keys(&:underscore)
69
92
  end
70
93
 
71
94
  # Internal: Retrieves a configuration option from environment variables.
72
- def config_option_from_env(name)
73
- ENV["#{ ViteRails::ENV_PREFIX }_#{ name.upcase }"]
95
+ def option_from_env(name)
96
+ ViteRails.env["#{ ViteRails::ENV_PREFIX }_#{ name.upcase }"]
74
97
  end
75
98
 
76
99
  # Internal: Extracts the configuration options provided as env vars.
77
100
  def config_from_env
78
- CONFIGURABLE_WITH_ENV.each_with_object({}) do |key, env_vars|
79
- if value = config_option_from_env(key)
80
- env_vars[key] = value
101
+ CONFIGURABLE_WITH_ENV.each_with_object({}) do |option, env_vars|
102
+ if value = option_from_env(option)
103
+ env_vars[option] = value
81
104
  end
82
- end.merge(mode: vite_mode)
83
- end
84
-
85
- # Internal: The mode Vite should run on.
86
- def vite_mode
87
- config_option_from_env('mode') || Rails.env.to_s
105
+ end
88
106
  end
89
107
 
90
108
  # Internal: Loads the configuration options provided in a JSON file.
91
- def config_from_file
92
- path = config_option_from_env('config_path') || DEFAULT_CONFIG.fetch('config_path')
109
+ def config_from_file(path, mode:)
93
110
  multi_env_config = load_json(path)
94
111
  multi_env_config.fetch('all', {})
95
- .merge(multi_env_config.fetch(vite_mode, {}))
112
+ .merge(multi_env_config.fetch(mode, {}))
113
+ rescue Errno::ENOENT => error
114
+ warn "Check that your vite.json configuration file is available in the load path. #{ error.message }"
115
+ {}
96
116
  end
97
117
  end
98
118
 
99
119
  # Internal: Shared configuration with the Vite plugin for Ruby.
100
120
  DEFAULT_CONFIG = load_json("#{ __dir__ }/../../package/default.vite.json").freeze
101
121
 
122
+ # Internal: Configuration options that can not be provided as env vars.
123
+ NOT_CONFIGURABLE_WITH_ENV = %w[watch_additional_paths].freeze
124
+
102
125
  # Internal: Configuration options that can be provided as env vars.
103
- CONFIGURABLE_WITH_ENV = (DEFAULT_CONFIG.keys + ['root']).freeze
126
+ CONFIGURABLE_WITH_ENV = (DEFAULT_CONFIG.keys + %w[mode root] - NOT_CONFIGURABLE_WITH_ENV).freeze
127
+
128
+ public
129
+
130
+ # Define getters for the configuration options.
131
+ (CONFIGURABLE_WITH_ENV + NOT_CONFIGURABLE_WITH_ENV).each do |option|
132
+ define_method(option) { @config[option] }
133
+ end
104
134
  end
@@ -14,18 +14,8 @@ class ViteRails::DevServerProxy < Rack::Proxy
14
14
 
15
15
  # Rack: Intercept asset requests and send them to the Vite server.
16
16
  def perform_request(env)
17
- if vite_should_handle?(env['REQUEST_URI'], env['HTTP_REFERER']) && dev_server.running?
18
- env['REQUEST_URI'] = env['REQUEST_URI']
19
- .sub(vite_asset_url_prefix, '/')
20
- .sub('.ts.js', '.ts') # Patch: Rails helpers always append the extension.
21
- env['PATH_INFO'], env['QUERY_STRING'] = env['REQUEST_URI'].split('?')
22
-
23
- env['HTTP_HOST'] = env['HTTP_X_FORWARDED_HOST'] = config.host
24
- env['HTTP_X_FORWARDED_SERVER'] = config.host_with_port
25
- env['HTTP_PORT'] = env['HTTP_X_FORWARDED_PORT'] = config.port.to_s
26
- env['HTTP_X_FORWARDED_PROTO'] = env['HTTP_X_FORWARDED_SCHEME'] = config.protocol
27
- env['HTTPS'] = env['HTTP_X_FORWARDED_SSL'] = 'off' unless config.https
28
- env['SCRIPT_NAME'] = ''
17
+ if vite_should_handle?(env) && dev_server_running?
18
+ forward_to_vite_dev_server(env)
29
19
  super(env)
30
20
  else
31
21
  @app.call(env)
@@ -34,13 +24,31 @@ class ViteRails::DevServerProxy < Rack::Proxy
34
24
 
35
25
  private
36
26
 
37
- delegate :config, :dev_server, to: :@vite_rails
27
+ delegate :config, :dev_server_running?, to: :@vite_rails
38
28
 
39
- def vite_should_handle?(url, referer)
40
- return true if url.start_with?(vite_asset_url_prefix) # Vite Asset
41
- return true if url.start_with?(VITE_DEPENDENCY_PREFIX) # Vite Package Asset
42
- return true if url.include?('?t=') # Hot Reload
43
- return true if referer && URI.parse(referer).path.start_with?(vite_asset_url_prefix) # Entry Imported from another Entry.
29
+ def rewrite_uri_for_vite(env)
30
+ uri = env.fetch('REQUEST_URI') { [env['PATH_INFO'], env['QUERY_STRING']].reject(&:blank?).join('?') }
31
+ .sub(vite_asset_url_prefix, '/')
32
+ env['PATH_INFO'], env['QUERY_STRING'] = (env['REQUEST_URI'] = uri).split('?')
33
+ end
34
+
35
+ def forward_to_vite_dev_server(env)
36
+ rewrite_uri_for_vite(env)
37
+ env['HTTP_HOST'] = env['HTTP_X_FORWARDED_HOST'] = config.host
38
+ env['HTTP_X_FORWARDED_SERVER'] = config.host_with_port
39
+ env['HTTP_PORT'] = env['HTTP_X_FORWARDED_PORT'] = config.port.to_s
40
+ env['HTTP_X_FORWARDED_PROTO'] = env['HTTP_X_FORWARDED_SCHEME'] = config.protocol
41
+ env['HTTPS'] = env['HTTP_X_FORWARDED_SSL'] = 'off' unless config.https
42
+ env['SCRIPT_NAME'] = ''
43
+ end
44
+
45
+ def vite_should_handle?(env)
46
+ path, query, referer = env['PATH_INFO'], env['QUERY_STRING'], env['HTTP_REFERER']
47
+ return true if path.start_with?(vite_asset_url_prefix) # Vite asset
48
+ return true if path.start_with?(VITE_DEPENDENCY_PREFIX) # Packages and imports
49
+ return true if query&.start_with?('t=') # Hot Reload for a stylesheet
50
+ return true if query&.start_with?('import&') # Hot Reload for an imported entrypoint
51
+ return true if referer && URI.parse(referer).path.start_with?(vite_asset_url_prefix) # Entry imported from another entry.
44
52
  end
45
53
 
46
54
  def vite_asset_url_prefix
@@ -2,19 +2,26 @@
2
2
 
3
3
  # Public: Allows to render HTML tags for scripts and styles processed by Vite.
4
4
  module ViteRails::Helper
5
- DEFAULT_VITE_SKIP_PRELOAD_TAGS = Rails::VERSION::MAJOR <= 5 && Rails::VERSION::MINOR < 2
5
+ DEFAULT_VITE_SKIP_PRELOAD_TAGS = Rails.gem_version < Gem::Version.new('5.2.0')
6
6
 
7
7
  # Public: Returns the current Vite Rails instance.
8
8
  def current_vite_instance
9
9
  ViteRails.instance
10
10
  end
11
11
 
12
- # Public: Computes the relative path for the specified given Vite asset.
12
+ # Public: Renders a script tag for vite/client to enable HMR in development.
13
+ def vite_client_tag
14
+ return unless current_vite_instance.dev_server_running?
15
+
16
+ content_tag('script', '', src: current_vite_instance.manifest.prefix_vite_asset('@vite/client'), type: 'module')
17
+ end
18
+
19
+ # Public: Resolves the path for the specified Vite asset.
13
20
  #
14
21
  # Example:
15
22
  # <%= vite_asset_path 'calendar.css' %> # => "/vite/assets/calendar-1016838bab065ae1e122.css"
16
23
  def vite_asset_path(name, **options)
17
- current_vite_instance.manifest.lookup!(name, **options).fetch('file')
24
+ path_to_asset current_vite_instance.manifest.lookup!(name, **options).fetch('file')
18
25
  end
19
26
 
20
27
  # Public: Renders a <script> tag for the specified Vite entrypoints.
@@ -26,15 +33,17 @@ module ViteRails::Helper
26
33
  crossorigin: 'anonymous',
27
34
  **options)
28
35
  js_entries = names.map { |name| current_vite_instance.manifest.lookup!(name, type: asset_type) }
29
- js_tags = javascript_include_tag(*js_entries.map { |entry| entry['file'] }, type: type, crossorigin: crossorigin, **options)
36
+ js_tags = javascript_include_tag(*js_entries.map { |entry| entry['file'] }, crossorigin: crossorigin, type: type, **options)
30
37
 
31
- unless skip_preload_tags || ViteRails.dev_server.running?
38
+ unless skip_preload_tags || current_vite_instance.dev_server_running?
32
39
  preload_paths = js_entries.flat_map { |entry| entry['imports'] }.compact.uniq
33
40
  preload_tags = preload_paths.map { |path| preload_link_tag(path, crossorigin: crossorigin) }
34
41
  end
35
42
 
36
- unless skip_style_tags || ViteRails.dev_server.running?
37
- style_paths = names.map { |name| current_vite_instance.manifest.lookup(name, type: :stylesheet)&.fetch('file') }.compact
43
+ unless skip_style_tags || current_vite_instance.dev_server_running?
44
+ style_paths = names.map { |name|
45
+ current_vite_instance.manifest.lookup(name.delete_suffix('.js'), type: :stylesheet)&.fetch('file')
46
+ }.compact
38
47
  style_tags = stylesheet_link_tag(*style_paths)
39
48
  end
40
49
 
@@ -46,7 +55,7 @@ module ViteRails::Helper
46
55
  # NOTE: Because TypeScript is not a valid target in browsers, we only specify
47
56
  # the ts file when running the Vite development server.
48
57
  def vite_typescript_tag(*names, **options)
49
- vite_javascript_tag(*names, asset_type: :typescript, **options)
58
+ vite_javascript_tag(*names, asset_type: :typescript, extname: false, **options)
50
59
  end
51
60
 
52
61
  # Public: Renders a <link> tag for the specified Vite entrypoints.
@@ -31,7 +31,7 @@ class ViteRails::Manifest
31
31
  # Example:
32
32
  # ViteRails.manifest.lookup('calendar.js')
33
33
  # # { "file" => "/vite/assets/calendar-1016838bab065ae1e122.js", "imports" => [] }
34
- def lookup(name, type:)
34
+ def lookup(name, type: nil)
35
35
  build if should_build?
36
36
 
37
37
  find_manifest_entry(with_file_extension(name, type))
@@ -42,6 +42,11 @@ class ViteRails::Manifest
42
42
  @manifest = load_manifest
43
43
  end
44
44
 
45
+ # Public: Scopes an asset to the output folder in public, as a path.
46
+ def prefix_vite_asset(path)
47
+ File.join("/#{ config.public_output_dir }", path)
48
+ end
49
+
45
50
  private
46
51
 
47
52
  delegate :config, :builder, :dev_server_running?, to: :@vite_rails
@@ -55,7 +60,7 @@ private
55
60
  # Internal: Finds the specified entry in the manifest.
56
61
  def find_manifest_entry(name)
57
62
  if dev_server_running?
58
- { 'file' => "/#{ config.public_output_dir.join(name.to_s) }" }
63
+ { 'file' => prefix_vite_asset(name.to_s) }
59
64
  else
60
65
  manifest[name.to_s]
61
66
  end
@@ -80,8 +85,8 @@ private
80
85
  def load_manifest
81
86
  if config.manifest_path.exist?
82
87
  JSON.parse(config.manifest_path.read).each do |_, entry|
83
- entry['file'] = within_public_output_dir(entry['file'])
84
- entry['imports'] = entry['imports']&.map { |path| within_public_output_dir(path) }
88
+ entry['file'] = prefix_vite_asset(entry['file'])
89
+ entry['imports'] = entry['imports']&.map { |path| prefix_vite_asset(path) }
85
90
  end
86
91
  else
87
92
  {}
@@ -92,12 +97,8 @@ private
92
97
  def with_file_extension(name, entry_type)
93
98
  return name unless File.extname(name.to_s).empty?
94
99
 
95
- "#{ name }.#{ extension_for_type(entry_type) }"
96
- end
97
-
98
- # Internal: Scopes the paths in the manifest to the output folder in public.
99
- def within_public_output_dir(path)
100
- "/#{ config.public_output_dir.join(path) }"
100
+ extension = extension_for_type(entry_type)
101
+ extension ? "#{ name }.#{ extension }" : name
101
102
  end
102
103
 
103
104
  # Internal: Allows to receive :javascript and :stylesheet as :type in helpers.
@@ -106,7 +107,7 @@ private
106
107
  when :javascript then 'js'
107
108
  when :stylesheet then 'css'
108
109
  when :typescript then dev_server_running? ? 'ts' : 'js'
109
- else entry_type.to_s
110
+ else entry_type
110
111
  end
111
112
  end
112
113
 
@@ -129,9 +130,10 @@ private
129
130
  [
130
131
  (dev_server_running? && 'Vite has not yet re-built your latest changes.'),
131
132
  (local && !dev_server_running? && "\"autoBuild\": false in your #{ config.mode } configuration."),
133
+ (local && !dev_server_running? && 'The Vite development server has crashed or is no longer available.'),
132
134
  'You have misconfigured config/vite.json file.',
133
135
  (!local && 'Assets have not been precompiled'),
134
- ].select(&:itself)
136
+ ].compact
135
137
  rescue StandardError
136
138
  []
137
139
  end