An experimental light-weight module to help with integrating Vite into your Phoenix project and watching for any code change in Vite's side.
Starting from Phoenix 1.6, esbuild is used to bundle JavaScript files and other assets instead of webpack. On the other hand, the latest version of Vue 3 recommends using Vite for building. Vite also supports other templates such as Lit, React, Preact, and Svelte, etc. Since during development, Phoenix's esbuild will watch for changes inside the assets folder and automatically re-bundles, and that it doesn't support *.vue
files, *.svelte
files, etc. directly, without writing a custom build script, it's relatively difficult to integrate Vite into a Phoenix project. Therefore, this tiny module serves to make such process a little bit easier.
With correct setup, VitePhoenix will automatically start watching for changes in your Vite project when you execute mix phx.server
. It will rebuild your files and put them inside the priv/static
folder in your Phoenix project.
Unlike the esbuild module that comes with Phoenix 1.6+, VitePhoenix does NOT install Node.js for you. Since it runs npx
for you, you will need to install Node.js before using VitePhoenix.
Adding vite_phoenix
to your list of dependencies in mix.exs
:
def deps do
[
{:vite_phoenix, "~> 0.1.3"}
]
end
Then run mix deps.get
.
VitePhoenix basically delegates all JavaScript stuffs to Vite, so in order to make it work, there are a few steps that need to be configured.
- After creating the project folder with
mix phx.new
, navigate toassets/js
folder under your project, and run either
npm create vue@latest
to bootstrap your Vue 3 + Vite project, or
npm create vite@latest <your-vite-project-name>
and select available templates to bootstrap your project.
-
Install VitePhoenix through the steps in Installation.
-
In your
config/config.exs
, configure the project name for VitePhoenix. Your project name here has to match the name you specify when running eithernpm create vue@latest
ornpm create vite@latest
config :vite_phoenix,
project_name: "<your-vite-project-name>",
js_version: "es2020" # Optionally provides the JS version for ESBuild in Vite. Default to "esnext"
- In your
config/dev.exs
, comment out or remove esbuild watcher for your Phoenix project, and add watcher for VitePhoenix.
config :my_phoenix, MyPhoenix,
watchers: [
# Start the esbuild watcher by calling Esbuild.install_and_run(:default, args)
# esbuild: {Esbuild, :install_and_run, [:default, ~w(--sourcemap=inline --watch)]},
vite_phoenix: {VitePhoenix, :run, [:default, ~w(--sourcemap --watch --emptyOutDir)]}
]
- By default, Vite will build everything under your Vite project folder and create a single
index.html
. In order to make use of suchindex.html
built by Vite, you would need to change yourPageController
that comes with any new Phoenix project, or any controller that serves as the entry point of your Phoenix project to sendindex.html
instead.
defmodule MyPhoenixWeb.PageController do
use MyPhoenixWeb, :controller
def index(conn, _params) do
conn
|> put_resp_header("Content-Type", "text/html; charset=utf-8")
|> send_file(200, Application.app_dir(:my_phoenix, "priv/static/index.html"))
end
end
-
(Optional) Delete
templates/page/index.html.heex
and other files undertemplates/layout
. -
(Optional) Delete esbuild-related lines per Phoenix's guide to remove esbuild.
-
(Optional) If you're also using vue-router and other routers for SPAs, you would also need to configure your
router.ex
to delegate non-Phoenix routes to your JavaScript router by adding a catch-all route. Note that the order of routes matters inrouter.ex
.
scope "/api", MyPhoenixWeb do
pipe_through :browser
get "/some_api", SomeApiController, :some_action
end
scope "/", MyPhoenixWeb do
pipe_through :browser
get "/*path", PageController, :index
end
- (Optional) Add files not included in the static path in your
endpoint.ex
plug Plug.Static,
at: "/",
from: :my_phoenix,
gzip: false,
only: ~w(assets fonts images favicon.ico robots.txt vite.svg)
- Run
mix phx.server
and visit http://localhost:4000 to see your JavaScript/TypeScript SPA powered by Vite.
As aforementioned, since VitePhoenix basically delegates everything JavaScript/TypeScript to Vite, and it doesn't use Phoenix's templates, it neither benefits from Phoenix's hot reload nor Vite's HMR. Even though Vite does rebuilds and puts latest files into priv/static
when anything is changed inside your Vite project, currently users have to refresh to see the latest result.