defmodule PhoenixVite.Components do @moduledoc """ Vite related components to be used within your phoenix application. ## Usage Put the following into your `
` of your phoenix root layout:
` of a html page. """ attr :names, :list, required: true attr :to_url, {:fun, 1}, default: &Function.identity/1 # https://vite.dev/guide/backend-integration.html def assets_from_dev_server(assigns) do ~H""" <.reference_for_file :for={name <- @names} file={name} to_url={@to_url} /> """ end @doc """ Asset references of vite manifest to be placed into the `
` of a html page. Caches manifests at runtime when refernces require parsing per provided source. """ attr :name, :string, required: true attr :manifest, :any, required: true attr :to_url, {:fun, 1}, default: &Function.identity/1 # https://vite.dev/guide/backend-integration.html def assets_from_manifest(%{manifest: manifest} = assigns) do manifest = cached_manifest(manifest) assigns = assign(assigns, manifest: cached_manifest(manifest)) ~H""" <.assets_from_manifest_for_name :for={name <- @names} name={name} manifest={@manifest} to_url={@to_url} /> """ end attr :name, :string, required: true attr :manifest, :map, required: true attr :to_url, {:fun, 1}, default: &Function.identity/1 # https://vite.dev/guide/backend-integration.html defp assets_from_manifest_for_name(%{manifest: manifest, name: name} = assigns) do name = Path.relative(name) assigns = assign(assigns, chunk: Map.fetch!(manifest, name), imported_chunks: Manifest.imported_chunks(manifest, name) ) ~H""" <.reference_for_file :for={css <- @chunk.css} file={css} to_url={@to_url} cache /> <%= for chunk <- @imported_chunks, css <- chunk.css do %> <.reference_for_file file={css} to_url={@to_url} cache /> <% end %> <.reference_for_file file={@chunk.file} to_url={@to_url} cache /> <.reference_for_file :for={chunk <- @imported_chunks} file={chunk.file} rel="modulepreload" to_url={@to_url} cache /> """ end attr :file, :string, required: true attr :to_url, {:fun, 1}, required: true attr :cache, :boolean, default: false attr :rest, :global defp reference_for_file(assigns) do ~H""" """ end defp cache_enabled_path(path, true) do "/" |> Path.join(path) |> URI.parse() |> URI.append_query("vsn=d") |> URI.to_string() end defp cache_enabled_path(path, false) do "/" |> Path.join(path) |> URI.parse() |> URI.to_string() end defp cached_manifest(%{} = manifest) do manifest end defp cached_manifest(manifest) do key = {__MODULE__, manifest} case :persistent_term.get(key, nil) do nil -> manifest = Manifest.parse(manifest) :persistent_term.put(key, manifest) manifest manifest -> manifest end end @doc """ Manually clear the cache for a vite manifest source. """ def clear_manifest_cache(manifest) do :persistent_term.erase({__MODULE__, manifest}) end end