Current section
Files
Jump to
Current section
Files
lib/mix/tasks/vitex.ex
defmodule Mix.Tasks.Vitex do
@moduledoc """
Invokes Vite with the given args.
Usage:
$ mix vitex COMMAND ARGS
Examples:
$ mix vitex build
$ mix vitex dev
$ mix vitex preview
"""
@shortdoc "Invokes Vite with the given args"
use Mix.Task
@impl true
def run(args) do
npm_path =
find_executable("npm") || find_executable("bun") || find_executable("pnpm") ||
find_executable("yarn")
unless npm_path do
raise "No package manager found. Please install npm, bun, pnpm, or yarn."
end
# Change to assets directory
assets_dir = Path.join(File.cwd!(), "assets")
unless File.exists?(assets_dir) do
raise "Assets directory not found at #{assets_dir}"
end
# Run vite command
cmd_args =
if npm_path =~ "bun" do
["x", "--bun", "vite"] ++ args
else
["run", "vite"] ++ args
end
# Pass through important environment variables
env = [
{"NODE_ENV", node_env()},
{"MIX_ENV", to_string(Mix.env())},
{"PHOENIX_BUILD_PATH", Mix.Project.build_path()}
]
# Pass through Phoenix-specific env vars if they exist
env =
env
|> maybe_add_env("PHX_HOST")
|> maybe_add_env("VITE_DEV_SERVER_KEY")
|> maybe_add_env("VITE_DEV_SERVER_CERT")
|> maybe_add_env("PHOENIX_DOCKER")
|> maybe_add_env("DOCKER_ENV")
|> maybe_add_env("VITE_PORT")
|> maybe_add_env("PHOENIX_BYPASS_ENV_CHECK")
|> maybe_add_env("CI")
|> maybe_add_env("RELEASE_NAME")
|> maybe_add_env("FLY_APP_NAME")
|> maybe_add_env("GIGALIXIR_APP_NAME")
|> maybe_add_env("HEROKU_APP_NAME")
|> maybe_add_env("RENDER")
|> maybe_add_env("RAILWAY_ENVIRONMENT")
Mix.shell().cmd("cd #{assets_dir} && #{npm_path} #{Enum.join(cmd_args, " ")}",
env: env
)
end
defp find_executable(name) do
System.find_executable(name)
end
defp node_env do
if Mix.env() == :prod, do: "production", else: "development"
end
defp maybe_add_env(env, key) do
case System.get_env(key) do
nil -> env
value -> env ++ [{key, value}]
end
end
end
defmodule Mix.Tasks.Vitex.Build do
@moduledoc """
Builds assets via Vite.
Usage:
$ mix vite.build
The task will install dependencies if needed and then run the build.
"""
@shortdoc "Builds assets via Vite"
use Mix.Task
@impl true
def run(_args) do
Mix.Tasks.Vitex.Deps.run([])
Mix.Tasks.Vitex.run(["build"])
end
end
defmodule Mix.Tasks.Vitex.Deps do
@moduledoc """
Installs JavaScript dependencies.
Usage:
$ mix vite.deps
"""
@shortdoc "Installs JavaScript dependencies"
use Mix.Task
@impl true
def run(_args) do
npm_path =
find_executable("npm") || find_executable("bun") || find_executable("pnpm") ||
find_executable("yarn")
unless npm_path do
raise "No package manager found. Please install npm, bun, pnpm, or yarn."
end
assets_dir = Path.join(File.cwd!(), "assets")
unless File.exists?(assets_dir) do
raise "Assets directory not found at #{assets_dir}"
end
install_cmd =
cond do
npm_path =~ "yarn" -> "install"
npm_path =~ "bun" -> "install"
npm_path =~ "pnpm" -> "install"
true -> "ci --progress=false --no-audit --loglevel=error"
end
Mix.shell().cmd("cd #{assets_dir} && #{npm_path} #{install_cmd}")
end
defp find_executable(name) do
System.find_executable(name)
end
end