Created
March 8, 2022 17:51
-
-
Save 29decibel/5d8443d5121232bc1033aec53c2fc9cc to your computer and use it in GitHub Desktop.
Use Svelte in Phoenix the simple way
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import esbuild from "esbuild"; | |
import esbuildSvelte from "esbuild-svelte"; | |
import sveltePreprocess from "svelte-preprocess"; | |
import { readdir } from "fs/promises"; | |
async function allSvelteComponents() { | |
const baseDir = "./js/app/"; | |
const all = await readdir(baseDir); | |
return all.filter((f) => f.endsWith(".svelte")).map((f) => `${baseDir}${f}`); | |
} | |
(async function () { | |
const components = await allSvelteComponents(); | |
const isProd = process.env.NODE_ENV == "production"; | |
esbuild | |
.build({ | |
entryPoints: components, | |
format: "esm", | |
bundle: true, | |
minify: isProd, | |
watch: !isProd, | |
outdir: "../priv/static/assets/svelte", | |
plugins: [ | |
esbuildSvelte({ | |
preprocess: sveltePreprocess(), | |
}), | |
], | |
}) | |
.catch(() => process.exit(1)); | |
})(); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/config/dev.exs b/config/dev.exs | |
index 43604e1..19e7c62 100644 | |
--- a/config/dev.exs | |
+++ b/config/dev.exs | |
@@ -40,7 +40,9 @@ config :example, ExampleWeb.Endpoint, | |
"--postcss", | |
"--watch", | |
cd: Path.expand("../assets", __DIR__) | |
- ] | |
+ ], | |
+ # build and watch svelte components | |
+ node: ["build.mjs", "--watch", cd: Path.expand("../assets", __DIR__)] | |
] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<%= ExampleWeb.SvelteView.render_component(@conn, "Hello", name: "Mike") %> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/mix.exs b/mix.exs | |
--- a/mix.exs | |
+++ b/mix.exs | |
@@ -116,7 +116,9 @@ defmodule Example.MixProject do | |
"assets.deploy": [ | |
"esbuild default --minify", | |
- "phx.digest" | |
+ "phx.digest", | |
+ # build svelte components | |
+ "NODE_ENV=production cmd --cd assets node ./build.mjs" | |
] | |
] | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/assets/package.json b/assets/package.json | |
--- a/assets/package.json | |
+++ b/assets/package.json | |
@@ -12,11 +12,16 @@ | |
"dependencies": { | |
+ "esbuild": "^0.14.23", | |
+ "esbuild-svelte": "^0.6.2", | |
+ "svelte": "^3.46.4", | |
+ "svelte-preprocess": "^4.10.4" | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule ExampleWeb.SvelteView do | |
use ExampleWeb, :view | |
# just for default values | |
def render_component(conn, name, props \\ []) | |
def render_component(conn, name, props) when is_list(props) do | |
render_component(conn, name, Enum.into(props, %{})) | |
end | |
def render_component(conn, name, props) when is_map(props) do | |
component_id = "svelte-ele-#{name}-#{random_id()}" | |
component_import_path = RootRoutes.static_path(conn, "/assets/svelte/#{name}.js") | |
props_json = props |> Jason.encode!() | |
component_class_name = name |> String.split("-") |> Enum.map_join(&String.capitalize(&1)) | |
[ | |
content_tag(:div, "", id: component_id), | |
content_tag :script, type: "module" do | |
""" | |
import #{component_class_name} from "#{component_import_path}" | |
new #{component_class_name}({ | |
target: document.getElementById("#{component_id}"), | |
props: #{props_json} | |
}) | |
""" | |
|> raw | |
end | |
] | |
end | |
defp random_id do | |
for _ <- 1..10, into: "", do: <<Enum.random('0123456789abcdef')>> | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment