class ViteRuby::Manifest
on demand as needed, before performing any lookup.
NOTE: Using “autoBuild”: true` in ‘config/vite.json` file will trigger a build
=> { “file” => “/vite/assets/calendar-1016838bab065ae1e314.js”, “imports” => [] }
lookup_entrypoint(’calendar’, type: :javascript)
Example:
manifest file which maps entrypoint names to file paths.
Public: Registry for accessing resources managed by Vite, using a generated
def extension_for_type(entry_type)
def extension_for_type(entry_type) case entry_type when :javascript then 'js' when :stylesheet then 'css' when :typescript then 'ts' else entry_type end end
def find_manifest_entry(name)
def find_manifest_entry(name) if dev_server_running? { 'file' => prefix_vite_asset(name.to_s) } else manifest[name.to_s] end end
def initialize(vite_ruby)
def initialize(vite_ruby) @vite_ruby = vite_ruby @build_mutex = Mutex.new if config.auto_build end
def load_manifest
def load_manifest files = [config.manifest_path, config.assets_manifest_path].select(&:exist?) files.map { |path| JSON.parse(path.read) }.inject({}, &:merge).tap(&method(:resolve_references)) end
def lookup(name, type: nil)
manifest.lookup('calendar.js')
Example:
Returns a relative path, or nil if the asset is not found.
Internal: Computes the path for a given Vite asset using manifest.json.
def lookup(name, type: nil) @build_mutex.synchronize { builder.build } if should_build? find_manifest_entry(with_file_extension(name, type)) end
def lookup!(*args, **options)
Internal: Strict version of lookup.
def lookup!(*args, **options) lookup(*args, **options) || missing_entry_error(*args, **options) end
def manifest
NOTE: When using build-on-demand in development and testing, the manifest
Internal: The parsed data from manifest.json.
def manifest return refresh if config.auto_build @manifest ||= load_manifest end
def missing_entry_error(name, type: nil, **_options)
def missing_entry_error(name, type: nil, **_options) raise ViteRuby::MissingEntrypointError, OpenStruct.new( file_name: with_file_extension(name, type), last_build: builder.last_build_metadata, manifest: @manifest, config: config, ) end
def path_for(name, **options)
Public: Returns the path for the specified Vite entrypoint file.
def path_for(name, **options) lookup!(name, **options).fetch('file') end
def prefix_vite_asset(path)
def prefix_vite_asset(path) File.join("/#{ config.public_output_dir }", path) end
def react_refresh_preamble
def react_refresh_preamble if dev_server_running? <<~REACT_REFRESH <script type="module"> import RefreshRuntime from '#{ prefix_vite_asset('@react-refresh') }' RefreshRuntime.injectIntoGlobalHook(window) window.$RefreshReg$ = () => {} window.$RefreshSig$ = () => (type) => type window.__vite_plugin_react_preamble_installed__ = true </script> REACT_REFRESH end end
def refresh
def refresh @manifest = load_manifest end
def resolve_entries(*names, **options)
Public: Returns scripts, imported modules, and stylesheets for the specified
def resolve_entries(*names, **options) entries = names.map { |name| lookup!(name, **options) } script_paths = entries.map { |entry| entry.fetch('file') } imports = dev_server_running? ? [] : entries.flat_map { |entry| entry['imports'] }.compact.uniq { scripts: script_paths, imports: imports.map { |entry| entry.fetch('file') }.uniq, stylesheets: dev_server_running? ? [] : (entries + imports).flat_map { |entry| entry['css'] }.compact.uniq, } end
def resolve_references(manifest)
def resolve_references(manifest) manifest.each_value do |entry| entry['file'] = prefix_vite_asset(entry['file']) entry['css'] = entry['css'].map { |path| prefix_vite_asset(path) } if entry['css'] entry['imports']&.map! { |name| manifest.fetch(name) } end end
def should_build?
NOTE: Auto compilation is convenient when running tests, when the developer
def should_build? config.auto_build && !dev_server_running? end
def vite_client_src
def vite_client_src prefix_vite_asset('@vite/client') if dev_server_running? end
def with_file_extension(name, entry_type)
def with_file_extension(name, entry_type) return name unless File.extname(name.to_s).empty? extension = extension_for_type(entry_type) extension ? "#{ name }.#{ extension }" : name end