View Source Installation
LiveReact replaces hex esbuild with Vite for both client side code and SSR to achieve a better development experience. Why ?
- Vite provides a best-in-class Hot-Reload functionality and offers many benefits not present in esbuild
hex esbuildpackage doesn't support plugins, while it's possible to do ssr withhex esbuild(check v0.2.0-rc-0) the SSR in development is broken.- the integration to react and ssr is more documented with Vite
In production, we'll use elixir-nodejs for SSR. If you don't need SSR, you can disable it with one line of code. TypeScript will be supported as well.
Steps
install nodejs (I recommend mise)
Add
live_reactto your list of dependencies inmix.exsand runmix deps.get
def deps do
[
{:live_react, "~> 1.0.0-rc.0"},
{:nodejs, "~> 3.1"} # if you want to use SSR in production
]
end- Add a config entry to your
config/dev.exs
config :live_react,
vite_host: "http://localhost:5173",
ssr_module: LiveReact.SSR.ViteJS,
ssr: true- Add a config entry to your
config/prod.exs
config :live_react,
ssr_module: LiveReact.SSR.NodeJS,
ssr: true # or false if you don't want SSR in production- Add
import LiveReactinhtml_helpers/0inside/lib/<app_name>_web.exlike so:
# /lib/<app_name>_web.ex
defp html_helpers do
quote do
# ...
import LiveReact # <-- Add this line
# ...
end
end- LiveReact comes with a handy mix task to setup all the required files. It won't alter any files you already have in your project, you need to adjust them on your own by looking at the sources. Additional instructions how to adjust
package.jsoncan be found at the end of this page.
It will create:
package.json- vite, typescript and postcss configs
- server entrypoint
- react components root
- Run the following in your terminal
mix deps.get
mix live_react.setup
npm install --prefix assets
- Add the following to your
assets/js/app.jsfile
...
import topbar from "topbar" // instead of ../vendor/topbar
import { getHooks } from "live_react";
import components from "../react";
import "../css/app.css" // the css file is handled by vite
const hooks = {
// ... your other hooks
...getHooks(components),
};
...
let liveSocket = new LiveSocket("/live", Socket, {
hooks: hooks, // <- pass the hooks
longPollFallbackMs: 2500,
params: { _csrf_token: csrfToken },
});
...- For tailwind support, make some addition to
contentin theassets/tailwind.config.jsfile
content: [
...
"./react/**/*.jsx", // <- if you are using jsx
"./react/**/*.tsx" // <- if you are using tsx
],
- Let's update
root.html.heexto use Vite files in development. There's a handy wrapper for it.
<LiveReact.Reload.vite_assets assets={["/js/app.js", "/css/app.css"]}>
<link phx-track-static rel="stylesheet" href={~p"/assets/app.css"} />
<script type="module" phx-track-static type="text/javascript" src={~p"/assets/app.js"}>
</script>
</LiveReact.Reload.vite_assets>- Update
mix.exsaliases and removetailwindandesbuildpackages
defp aliases do
[
setup: ["deps.get", "assets.setup", "assets.build"],
"assets.setup": ["cmd --cd assets npm install"],
"assets.build": [
"cmd --cd assets npm run build",
"cmd --cd assets npm run build-server"
],
"assets.deploy": [
"cmd --cd assets npm run build",
"cmd --cd assets npm run build-server",
"phx.digest"
]
]
end
defp deps do
[
# remove these lines, we don't need esbuild or tailwind here anymore
# {:esbuild, "~> 0.8", runtime: Mix.env() == :dev},
# {:tailwind, "~> 0.2", runtime: Mix.env() == :dev},
]
endRemove esbuild and tailwind config from
config/config.exsUpdate watchers in
config/dev.exsto look like this
config :my_app, MyAppWeb.Endpoint,
# ...
watchers: [
npm: ["run", "dev", cd: Path.expand("../assets", __DIR__)]
]- To make SSR working with
LiveReact.SSR.NodeJSin production, you have to add this entry to yourapplication.exsupervision tree to run the NodeJS server
If you don't want SSR in production, you can skip this step.
children = [
...
{NodeJS.Supervisor, [path: LiveReact.SSR.NodeJS.server_path(), pool_size: 4]},
# note Adjust the pool_size depending of the machine
]- Confirm everything is working by rendering the default React component anywhere in your Dead or Live Views
<.react name="Simple" />- (Optional) enable stateful hot reload of phoenix LiveViews - it allows for stateful reload across the whole stack 🤯. Just adjust your
dev.exsto look like this - addnotifysection and removelive|componentsfrom patterns.
# Watch static and templates for browser reloading.
config :my_app, MyAppWeb.Endpoint,
live_reload: [
notify: [
live_view: [
~r"lib/my_app_web/core_components.ex$",
~r"lib/my_app_web/(live|components)/.*(ex|heex)$"
]
],
patterns: [
~r"priv/static/(?!uploads/).*(js|css|png|jpeg|jpg|gif|svg)$",
~r"lib/my_app_web/controllers/.*(ex|heex)$"
]
]Profit! 💸
Adjusting your own package.json
Install these packages
cd assets
# vite
npm install -D vite @vitejs/plugin-react
# tailwind
npm install -D tailwindcss autoprefixer postcss @tailwindcss/forms
# typescript
npm install -D typescript @types/react @types/react-dom
# runtime dependencies
npm install --save vue topbar ../deps/live_react ../deps/phoenix ../deps/phoenix_html ../deps/phoenix_live_view
# remove topbar from vendor, since we'll use it from node_modules
rm vendor/topbar.js
and add these scripts used by watcher and mix assets.build command
{
"private": true,
"type": "module",
"scripts": {
"dev": "vite --host -l warn",
"build": "tsc && vite build",
"build-server": "tsc && vite build --ssr js/server.js --out-dir ../priv/react --minify esbuild && echo '{\"type\": \"module\" } ' > ../priv/react/package.json"
}
}