update installer and documentation

This commit is contained in:
Denis Donici 2026-03-06 01:50:41 +02:00
parent 27d5540d69
commit 90a25b8205
8 changed files with 233 additions and 20 deletions

View file

@ -81,6 +81,8 @@ Make sure you have it installed in production too. You might be using `node` in
You can make sure you have `node` installed by running `node --version` in your project directory.
You can also use **Bun** instead of Node.js/npm for installing dependencies and running Vite (see [Installation](#installation)); production SSR still uses Node.js.
If you don't want SSR, you can disable it by not setting `NodeJS.Supervisor` in `application.ex`. More on that in the [SSR](#ssr-server-side-rendering) section of this document.
## Installation
@ -91,7 +93,7 @@ LiveSvelte uses [Vite](https://vite.dev/) for building and [phoenix_vite](https:
### Option A — Igniter installer (recommended)
Requires Phoenix 1.8+ and Node.js 19+.
Requires Phoenix 1.8+ and Node.js 19+ (or Bun for package management and builds).
#### New project
@ -142,11 +144,12 @@ With phoenix_vite, the layout uses `PhoenixVite.Components.assets` and the endpo
Visit `http://localhost:4000/svelte_demo` to confirm the demo Svelte component is working.
Add `--bun` to use Bun instead of npm/npx:
#### Using Bun
```bash
mix igniter.install live_svelte --bun
```
Use the `--bun` flag to use Bun instead of npm/npx:
- **Existing project:** `mix igniter.install live_svelte --bun`
- **New project:** `mix igniter.new my_app --with phx.new --install live_svelte --bun`
---
@ -154,6 +157,8 @@ mix igniter.install live_svelte --bun
Use this if you prefer not to use Igniter, or need full control over the configuration.
To use **Bun** instead of npm when installing manually, add the `bun` dependency, set `config :phoenix_vite, PhoenixVite.Bun, ...`, and use `phoenix_vite.bun` in mix aliases and `PhoenixVite.Bun` in the Vite watcher. See the [Installation guide](https://hexdocs.pm/live_svelte/installation.html) for details.
**1.** Add dependencies to `mix.exs`:
```elixir

View file

@ -4,7 +4,7 @@ Deploying a LiveSvelte application requires Node.js on the server for SSR (serve
## Requirements
- **Node.js 19+** on the production server (for `LiveSvelte.SSR.NodeJS`)
- **Node.js 19+** on the production server (for `LiveSvelte.SSR.NodeJS`). If you use Bun for local builds, the production server still needs Node.js 19+ for SSR (the SSR bundle is run by Node.js).
- Standard Phoenix/Elixir deployment tooling (releases, Docker, etc.)
## Build Steps

View file

@ -4,7 +4,7 @@ LiveSvelte uses [Vite](https://vitejs.dev/) for both client and SSR builds, repl
## Prerequisites
- **Node.js 19+** — required for SSR (server-side rendering)
- **Node.js 19+ or Bun** — for package management and Vite builds. Production SSR (when using `LiveSvelte.SSR.NodeJS`) still requires Node.js 19+ on the server.
- **Elixir 1.17+**
- **Phoenix 1.8+** — required for the Igniter installer
- **Igniter** — the installation scaffolding tool
@ -31,11 +31,14 @@ For a **new** project with LiveSvelte pre-installed:
mix igniter.new my_app --with phx.new --install live_svelte
```
Use the `--bun` flag to use `bun` instead of `npm`:
#### Using Bun
```bash
mix igniter.install live_svelte --bun
```
To use **Bun** instead of Node.js/npm for package management and Vite:
- **Existing project:** `mix igniter.install live_svelte --bun`
- **New project:** `mix igniter.new my_app --with phx.new --install live_svelte --bun`
After install, `mix assets.setup` and `mix assets.build` use Bun (e.g. `bun install`, phoenix_vite's Bun task) instead of npm.
### Step 3: Install JS dependencies and build
@ -54,7 +57,7 @@ Running `mix igniter.install live_svelte` makes the following changes to your pr
**`package.json`** (at project root) — the installer moves it from `assets/` and adds:
- `live_svelte`, `phoenix_vite: "file:./deps/phoenix_vite"` (dev), and Svelte-related deps
**`config/config.exs`** — adds `config :phoenix_vite, PhoenixVite.Npm, ...`
**`config/config.exs`** — adds `config :phoenix_vite, PhoenixVite.Npm, ...` (when using `--bun`, the installer configures `PhoenixVite.Bun` and Bun-based aliases instead).
**`assets/vite.config.mjs`** — adds the Svelte plugin, `liveSveltePlugin`, and `ssr: { noExternal: ... }`. A single config is used for both client and SSR builds (no separate `vite.ssr.config.js`); the SSR build is run via `phoenix_vite.npm vite build --ssr js/server.js --outDir ../priv/svelte`.
@ -143,6 +146,19 @@ If you must install manually (e.g. Phoenix < 1.8), the overall steps mirror the
7. Configure SSR in `config/`
8. **For instant Svelte/CSS HMR with phoenix_vite:** In `config/dev.exs`, add to your endpoint `static_url: [host: "localhost", port: 5173]` and in `watchers` add `vite: {PhoenixVite.Npm, :run, [:vite, ~w(dev)]}`. Without these, the layout serves built assets and changes to Svelte components will not hot-reload.
#### Using Bun with manual installation
To use **Bun** instead of npm when installing manually:
1. Add the optional dependency in `mix.exs`: `{:bun, ">= 1.5.1 and < 2.0.0-0"}`
2. In `config/config.exs`, use `config :phoenix_vite, PhoenixVite.Bun, ...` (with the same options you would use for `PhoenixVite.Npm`; see [phoenix_vite](https://hexdocs.pm/phoenix_vite) for the Bun API).
3. In `mix.exs` aliases, use `phoenix_vite.bun` instead of `phoenix_vite.npm`:
- `"assets.setup": ["phoenix_vite.bun assets install", "tailwind.install --if-missing"]`
- `"assets.build"`: same two `phoenix_vite.bun vite build ...` commands as in the npm version.
4. In `config/dev.exs` watchers, use `vite: {PhoenixVite.Bun, :run, [:vite, ~w(dev)]}`.
Production SSR still uses Node.js (`LiveSvelte.SSR.NodeJS`); the server must have Node.js 19+ installed.
## Disabling SSR
If you don't need server-side rendering, disable it globally:

View file

@ -49,4 +49,4 @@ Plain LiveView may be sufficient when:
| Phoenix | 1.7+ (1.8+ for Igniter installer) |
| Phoenix LiveView | 1.0+ |
| Elixir | 1.17+ |
| Node.js | 19+ (for SSR) |
| Node.js or Bun | Node.js 19+ for SSR; Bun or Node.js 19+ for tooling |

View file

@ -0,0 +1,192 @@
# New Phoenix project without Ecto (Igniter + LiveSvelte)
Step-by-step guide to create a new Phoenix app **without Ecto** inside the `live_svelte` folder, using the Igniter installer and the local LiveSvelte library.
## Prerequisites
- Elixir 1.17+
- Node.js 19+ (or Bun)
- Phoenix 1.8+ (pulled in by Igniter)
## Step 1: Install the Igniter archive
From any directory:
```bash
mix archive.install hex igniter_new
```
## Step 2: Create the new Phoenix app inside `live_svelte`
Go to the `live_svelte` directory and run Igniter with `phx.new` and `--no-ecto`:
```bash
cd /home/gevera/Projects/elixir/phx_live/live_svelte
mix igniter.new my_app --with phx.new --with-args="--no-ecto" --install live_svelte
```
Replace `my_app` with your app name (e.g. `alan_app`). This creates `live_svelte/my_app/` with Phoenix (no Ecto) and LiveSvelte pre-installed.
To use **Bun** instead of npm:
```bash
mix igniter.new my_app --with phx.new --with-args="--no-ecto" --install live_svelte --bun
```
## Step 3: Use the local LiveSvelte library (development)
The installer adds LiveSvelte from Hex. To use the **local** LiveSvelte in this repo instead:
1. **Edit the new apps `mix.exs`**
Find the `live_svelte` dependency and change it to a path dependency:
```elixir
# Change from:
# {:live_svelte, "~> 0.17.x"},
# To:
{:live_svelte, path: ".."},
```
2. **Edit the new apps `package.json`**
Point `live_svelte` and Phoenix deps to the local/relative paths (same layout as `example_project` and the fixed `alan_app`):
- `live_svelte`: use `"file:.."` (parent directory = LiveSvelte root).
- Phoenix-related deps: use `"file:./deps/..."` (Mix puts them in `my_app/deps/`).
Example:
```json
"dependencies": {
"live_svelte": "file:..",
"phoenix": "file:./deps/phoenix",
"phoenix_html": "file:./deps/phoenix_html",
"phoenix_live_view": "file:./deps/phoenix_live_view",
"topbar": "^3.0.0"
},
"devDependencies": {
"phoenix_vite": "file:./deps/phoenix_vite",
...
}
```
If your `package.json` has `file:../deps/...`, change those to `file:./deps/...` and `live_svelte` to `file:..`.
## Step 4: Install dependencies and run
From the **new app** directory:
```bash
cd my_app
mix deps.get
mix assets.setup
mix phx.server
```
Open `http://localhost:4000` and visit `/svelte_demo` to confirm LiveSvelte works.
## Summary
| Step | Command / action |
|------|-------------------|
| 1 | `mix archive.install hex igniter_new` |
| 2 | `cd live_svelte` then `mix igniter.new my_app --with phx.new --with-args="--no-ecto" --install live_svelte` |
| 3 | In `my_app`: set `{:live_svelte, path: ".."}` in `mix.exs` and fix `package.json` to `live_svelte: "file:.."` and Phoenix deps to `file:./deps/...` |
| 4 | `cd my_app`, `mix deps.get`, `mix assets.setup`, `mix phx.server` |
Optional: add `--bun` to the `igniter.new` command to use Bun instead of npm.
---
## If `igniter.new` fails with "dependencies were not loaded"
Igniter can fail with:
```text
** (RuntimeError) cannot retrieve dependencies information because dependencies were not loaded.
Please invoke one of "deps.loadpaths", "loadpaths", or "compile" Mix task
```
That happens when it creates the new app and then tries to compile before the new projects deps are loaded. The app directory (e.g. `my_app/`) is still created by `phx.new`; only the LiveSvelte install step didnt run. You can finish setup by hand.
### Recover the existing app (e.g. `my_app`)
1. **Go into the new app and load deps:**
```bash
cd live_svelte/my_app
mix deps.get
mix compile
```
2. **Add LiveSvelte and Phoenix Vite to `mix.exs`** in the `deps/0` list (and keep `igniter` if its there):
```elixir
{:phoenix_vite, "~> 0.4"},
{:live_svelte, path: ".."}
```
3. **Fetch deps and run the LiveSvelte installer:**
```bash
mix deps.get
mix igniter.install live_svelte
```
Use `--bun` if you want Bun: `mix igniter.install live_svelte --bun`.
4. **Fix `package.json` for local LiveSvelte** (same as Step 3 in the main flow):
- `"live_svelte": "file:.."`
- Phoenix deps: `"file:./deps/phoenix"`, `"file:./deps/phoenix_html"`, `"file:./deps/phoenix_live_view"`
- In devDependencies: `"phoenix_vite": "file:./deps/phoenix_vite"`
5. **Install assets and run:**
```bash
mix assets.setup
mix phx.server
```
---
## Alternative: create with `phx.new` then install LiveSvelte
To avoid `igniter.new` entirely (e.g. if the "dependencies were not loaded" error keeps happening):
1. **Create a Phoenix app without Ecto** from the `live_svelte` directory:
```bash
cd live_svelte
mix phx.new my_app --no-ecto
```
(You need the `phx_new` archive: `mix archive.install hex phx_new`.)
2. **Add Igniter and LiveSvelte** in the new apps `mix.exs` (in `deps/0`):
```elixir
{:igniter, "~> 0.6", only: [:dev, :test]},
{:phoenix_vite, "~> 0.4"},
{:live_svelte, path: ".."}
```
3. **Install deps and run the LiveSvelte installer:**
```bash
cd my_app
mix deps.get
mix igniter.install live_svelte
```
Use `mix igniter.install live_svelte --bun` for Bun.
4. **Fix `package.json`** so the app uses the local LiveSvelte and local Phoenix deps (same as Step 3 above: `live_svelte``"file:.."`, Phoenix deps → `"file:./deps/..."`).
5. **Setup assets and run:**
```bash
mix assets.setup
mix phx.server
```
This way you never run `igniter.new`; you use `phx.new` and then `igniter.install live_svelte`.

View file

@ -60,7 +60,7 @@ This injects Svelte component CSS directly into the JS bundle instead of extract
**Cause:** The `liveSveltePlugin` is missing from one or both Vite configs.
**Fix:** Ensure `liveSveltePlugin()` is in `vite.config.mjs` and that `ssr: { noExternal: ... }` is set. The same config is used for both client and SSR builds (via `phoenix_vite.npm vite build --ssr js/server.js ...`).
**Fix:** Ensure `liveSveltePlugin()` is in `vite.config.mjs` and that `ssr: { noExternal: ... }` is set. The same config is used for both client and SSR builds (via `phoenix_vite.npm vite build --ssr js/server.js ...`). If you use Bun, the same steps apply with `phoenix_vite.bun` and `PhoenixVite.Bun`.
```js
// assets/vite.config.mjs
@ -236,4 +236,4 @@ config :my_app, MyAppWeb.Endpoint,
]
```
Without these, the layout serves built assets from `priv/static` and Svelte/CSS changes do not hot-reload.
(If you use Bun, use `PhoenixVite.Bun` and `phoenix_vite.bun` in aliases instead.) Without these, the layout serves built assets from `priv/static` and Svelte/CSS changes do not hot-reload.

View file

@ -68,7 +68,7 @@ defmodule Mix.Tasks.LiveSvelte.Install do
"config.exs",
:phoenix_vite,
[PhoenixVite.Npm, :assets],
{:code, Sourceror.parse_string!(~s|[args: [], cd: __DIR__]|)}
{:code, Sourceror.parse_string!(~s|[args: [], cd: Path.expand("..", __DIR__)]|)}
)
end
@ -370,7 +370,7 @@ defmodule Mix.Tasks.LiveSvelte.Install do
content,
~r/([ \t]*)(children = \[)/,
"\\1node_js_children =\n" <>
"\\1 if Application.compile_env(:live_svelte, :ssr_module, nil) == LiveSvelte.SSR.NodeJS do\n" <>
"\\1 if Application.get_env(:live_svelte, :ssr_module, nil) == LiveSvelte.SSR.NodeJS do\n" <>
"\\1 [{NodeJS.Supervisor, [path: LiveSvelte.SSR.NodeJS.server_path(), pool_size: 4]}]\n" <>
"\\1 else\n" <>
"\\1 []\n" <>

View file

@ -146,12 +146,12 @@ defmodule Mix.Tasks.LiveSvelte.InstallTest do
assert content =~ "NodeJS.Supervisor"
end
test "NodeJS.Supervisor is wrapped in compile_env guard, not unconditional" do
test "NodeJS.Supervisor is wrapped in get_env guard, not unconditional" do
result = run_installer()
content = file_content(result, "lib/test/application.ex")
assert content =~ "Application.compile_env(:live_svelte, :ssr_module",
"NodeJS.Supervisor must be wrapped in a compile_env guard so it only starts in prod"
assert content =~ "Application.get_env(:live_svelte, :ssr_module",
"NodeJS.Supervisor must be wrapped in a get_env guard so it only starts in prod"
refute content =~ ~r/children\s*=\s*\[\s*\{NodeJS\.Supervisor/,
"NodeJS.Supervisor must not be a bare unconditional entry in the children list"