Giter Site home page Giter Site logo

woutdp / live_svelte Goto Github PK

View Code? Open in Web Editor NEW
864.0 864.0 31.0 17.95 MB

Svelte inside Phoenix LiveView with seamless end-to-end reactivity

Home Page: https://hexdocs.pm/live_svelte

License: MIT License

Elixir 74.81% JavaScript 10.18% CSS 0.10% Svelte 7.03% HTML 4.84% Dockerfile 1.92% Nix 1.12%
elixir liveview phoenix phoenix-liveview ssr svelte websocket

live_svelte's People

Contributors

absowoot avatar acco avatar alan7sage avatar atomkirk avatar c-sinclair avatar drkreso avatar tonydangblog avatar vonagam avatar voughtdq avatar woutdp avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

live_svelte's Issues

LocalStroage and Session Storage not defined

I was trying to use data i stored in the svelte store on a new liveview it however came as blank and navigating back the data was logged on the console am still new to liveview and i;m geussing the two are independed i tried calling the client session storage or local storge but neigther works ...

I have been looking for ways to pass data within liveview minus saving in the database initially am handling a multi stage form how would you go through now that livesvelte is in picture..
sessionStorage is not defined

ReferenceError: sessionStorage is not defined
    at /home/maxino/Value_8/Realest8/realest8_platform/priv/svelte/server.js:9897:3
    at $$render (/home/maxino/Value_8/Realest8/realest8_platform/priv/svelte/server.js:9261:18)
    at Object.render (/home/maxino/Value_8/Realest8/realest8_platform/priv/svelte/server.js:9269:20)
    at render2 (/home/maxino/Value_8/Realest8/realest8_platform/priv/svelte/server.js:9938:22)
    at callModuleFunction (/home/maxino/Value_8/Realest8/realest8_platform/deps/nodejs/priv/server.js:32:23)
    at getResponse (/home/maxino/Value_8/Realest8/realest8_platform/deps/nodejs/priv/server.js:44:26)
    at Interface.onLine (/home/maxino/Value_8/Realest8/realest8_platform/deps/nodejs/priv/server.js:53:39)
    at Interface.emit (node:events:514:28)
    at [_onLine] [as _onLine] (node:internal/readline/interface:422:12)
    at [_normalWrite] [as _normalWrite] (node:internal/readline/interface:616:22)

Shorter way of defining a live_component

I think it's a bit cumbersome atm.

Ideally I can just call a function.

Also the id is something I'd like to avoid to provide if it's possible.

Would be nice to keep slots, if we can make that work

Excessive SSR for LiveViews

Right now if ssr is activated then it happens twice on mount - first for disconnected mount and then for connected - and also on each live navigation between different views. Except disconnected mount those renders are not needed and might actually slow down things. It is obvious that there is no point in rendering connected mount. As for live navigation - it seems like main gain of ssr is an ability to see a page before assets have loaded, but in live navigation we already have js and css loaded so there should be no advantage from ssr.

I currently set ssr={!connected?(@socket)} on a svelte component in live view to avoid those renders. I think it worth mentioning somewhere.

Docker issue mix assets.deploy

Reported by victorbjorklund: https://elixirforum.com/t/livesvelte-e2e-reactivity-in-liveview-with-svelte/54822/2?u=woutdp

But getting some errors when building in Docker:

=> ERROR [builder 16/20] RUN mix assets.deploy 1.3s
[builder 16/20] RUN mix assets.deploy:
#26 1.253 /app/assets/node_modules/esbuild-svelte/dist/index.js:23
#26 1.253 const svelteFilter = (options == null ? void 0 : options.include) ?? SVELTE_FILTER;
#26 1.253 ^
#26 1.253
#26 1.253 SyntaxError: Unexpected token ‘?’
#26 1.253 at wrapSafe (internal/modules/cjs/loader.js:915:16)
#26 1.253 at Module._compile (internal/modules/cjs/loader.js:963:27)
#26 1.253 at Object.Module._extensions…js (internal/modules/cjs/loader.js:1027:10)
#26 1.253 at Module.load (internal/modules/cjs/loader.js:863:32)
#26 1.253 at Function.Module._load (internal/modules/cjs/loader.js:708:14)
#26 1.253 at Module.require (internal/modules/cjs/loader.js:887:19)
#26 1.253 at require (internal/modules/cjs/helpers.js:74:18)
#26 1.253 at Object. (/app/assets/build.js:2:22)
#26 1.253 at Module._compile (internal/modules/cjs/loader.js:999:30)
#26 1.253 at Object.Module._extensions…js (internal/modules/cjs/loader.js:1027:10)
#26 1.268 ** (exit) 1
#26 1.268 (mix 1.14.2) lib/mix/tasks/cmd.ex:74: Mix.Tasks.Cmd.run/1
#26 1.268 (mix 1.14.2) lib/mix/task.ex:421: anonymous fn/3 in Mix.Task.run_task/4
#26 1.268 (mix 1.14.2) lib/mix/task.ex:479: Mix.Task.run_alias/6
#26 1.268 (mix 1.14.2) lib/mix/cli.ex:84: Mix.CLI.run_task/2

executor failed running [/bin/sh -c mix assets.deploy]: exit code: 1

Not sure if error is LiveSvelte, Esbuild-svelte or Docker.

Suggest renaming LiveSvelte.render to LiveSvelte.svelte

Now that I have more experience with Phoenix components, it seems that <.foo> in heex templates should be a noun - a component name - instead of a verb. Therefore I am suggesting deprecating LiveSvelte.render in favor of LiveSvelte.svelte so that it is more in the spirit of .button, .link, etc.

Creating files under assets/svelte/_build for ~V

assets/svelte/_build contains artifacts from llive views that use the ~V sigil.

This directory seems to be created when I run (among other mix commands) mix phx.server. However, this directory is not getting created. I'm using live_svelte version 0.11.0.

This has happened to me before and it "Just Started Working." However, I seem to have broken the ~V sigil's magic permanently this time.

Intermittent SSR crash

  1. Run the application at https://github.com/dev-guy/phoenix-ash-svelte-flowbite/blob/main/README.md . Unfortunately it needs Postgres to set up. I need to remove that part or install on a hosting service. Until then you can ignore.
  2. Open Safari and go to http://localhost:4000/svelte/mermaid . I don't know why it has to be Safari. Chrome is more difficult.
  3. Go to http://localhost:4000/svelte/counter
  4. Repeat steps 2 and 3 until it crashes on counter. It crashes more frequently on Mermaid but the counter page is a lot less complicated so should be easier to figure out.

Note that you can't make it happen by refreshing the counter page. The mermaid page is definitely part of the problem and you make the crash happen by simply refreshing it but sometimes it works.

Error message shown in browser

Error message shown in 'mix phx.server' console:


/Users/dg/agle/202308/phoenix-ash-svelte-flowbite/priv/static/assets/server/server.js:14964
  return typeof selector === "string" ? new Selection([[document.querySelector(selector)]], [document.documentElement]) : new Selection([[selector]], root);
                                                        ^

ReferenceError: document is not defined
    at select_default2 (/Users/dg/agle/202308/phoenix-ash-svelte-flowbite/priv/static/assets/server/server.js:14964:57)
    at Object.render3 [as render] (/Users/dg/agle/202308/phoenix-ash-svelte-flowbite/priv/static/assets/server/server.js:181274:19)
    at /Users/dg/agle/202308/phoenix-ash-svelte-flowbite/priv/static/assets/server/server.js:181576:22
    at new Promise (<anonymous>)
    at performCall (/Users/dg/agle/202308/phoenix-ash-svelte-flowbite/priv/static/assets/server/server.js:181575:35)
    at executeQueue ([info] GET /
[debug] Processing with KantanWeb.PageController.home/2
  Parameters: %{}
  Pipelines: [:browser]
[info] Sent 200 in 10ms
[info] GET /svelte/mermaid
[debug] Processing with KantanWeb.PageController.mermaid/2
  Parameters: %{}
  Pipelines: [:browser]
[error] GenServer #PID<0.613.0> terminating
** (ArgumentError) argument error
    :erlang.port_command(#Port<0.9>, "[[\"server/server\",\"ssrRenderComponent\"],[\"Mermaid\",{},{}]]\n")
    (nodejs 2.0.0) lib/nodejs/worker.ex:102: NodeJS.Worker.handle_call/3
    (stdlib 4.3) gen_server.erl:1149: :gen_server.try_handle_call/4
    (stdlib 4.3) gen_server.erl:1178: :gen_server.handle_msg/6
    (stdlib 4.3) proc_lib.erl:240: :proc_lib.init_p_do_apply/3
Last message (from #PID<0.831.0>): {{"server/server", "ssrRenderComponent"}, ["Mermaid", %{}, %{}], [binary: false, timeout: 30000]}
State: ["/Users/dg/agle/202308/phoenix-ash-svelte-flowbite/_build/dev/lib/nodejs/priv/server.js", #Port<0.9>]
Client #PID<0.831.0> is alive

    (stdlib 4.3) gen.erl:256: :gen.do_call/4
    (elixir 1.14.4) lib/gen_server.ex:1035: GenServer.call/3
    (nodejs 2.0.0) lib/nodejs/supervisor.ex:38: anonymous fn/5 in NodeJS.Supervisor.run_in_transaction/3
    (poolboy 1.5.2) /Users/dg/agle/202308/phoenix-ash-svelte-flowbite/deps/poolboy/src/poolboy.erl:84: :poolboy.transaction/3
    (nodejs 2.0.0) lib/nodejs/supervisor.ex:68: NodeJS.Supervisor.call/3
    (nodejs 2.0.0) lib/nodejs/supervisor.ex:77: NodeJS.Supervisor.call!/3
    (live_svelte 0.5.1) lib/ssr.ex:19: LiveSvelte.SSR.render/3
    (live_svelte 0.5.1) lib/component.ex:56: LiveSvelte."render (overridable 1)"/1
    (phoenix_live_view 0.18.18) lib/phoenix_live_view/tag_engine.ex:68: Phoenix.LiveView.TagEngine.component/3
    (kantan 0.1.0) lib/kantan_web/controllers/page_html/mermaid.html.heex:1: anonymous fn/2 in KantanWeb.PageHTML.mermaid/1
    (phoenix_live_view 0.18.18) lib/phoenix_live_view/engine.ex:137: Phoenix.HTML.Safe.Phoenix.LiveView.Rendered.to_iodata/1
    (phoenix_live_view 0.18.18) lib/phoenix_live_view/engine.ex:153: Phoenix.HTML.Safe.Phoenix.LiveView.Rendered.to_iodata/3
    (phoenix 1.7.2) lib/phoenix/controller.ex:1010: anonymous fn/5 in Phoenix.Controller.template_render_to_iodata/4
    (telemetry 1.2.1) /Users/dg/agle/202308/phoenix-ash-svelte-flowbite/deps/telemetry/src/telemetry.erl:321: :telemetry.span/3
    (phoenix 1.7.2) lib/phoenix/controller.ex:976: Phoenix.Controller.render_and_send/4
    (kantan 0.1.0) lib/kantan_web/controllers/page_controller.ex:1: KantanWeb.PageController.action/2
    (kantan 0.1.0) lib/kantan_web/controllers/page_controller.ex:1: KantanWeb.PageController.phoenix_controller_pipeline/2
    (phoenix 1.7.2) lib/phoenix/router.ex:430: Phoenix.Router.__call__/5
    (kantan 0.1.0) lib/kantan_web/endpoint.ex:1: KantanWeb.Endpoint.plug_builder_call/2
    (kantan 0.1.0) deps/plug/lib/plug/debugger.ex:136: KantanWeb.Endpoint."call (overridable 3)"/2
[info] Sent 500 in 122ms
[error] #PID<0.831.0> running Phoenix.Endpoint.SyncCodeReloadPlug (connection #PID<0.783.0>, stream id 8) terminated
Server: localhost:4000 (http)
Request: GET /svelte/mermaid
** (exit) an exception was raised:
    ** (NodeJS.Error) got {:node_js_worker_exit, {{:badarg, [{:erlang, :port_command, [#Port<0.9>, "[[\"server/server\",\"ssrRenderComponent\"],[\"Mermaid\",{},{}]]\n"], [error_info: %{module: :erl_erts_errors}]}, {NodeJS.Worker, :handle_call, 3, [file: 'lib/nodejs/worker.ex', line: 102]}, {:gen_server, :try_handle_call, 4, [file: 'gen_server.erl', line: 1149]}, {:gen_server, :handle_msg, 6, [file: 'gen_server.erl', line: 1178]}, {:proc_lib, :init_p_do_apply, 3, [file: 'proc_lib.erl', line: 240]}]}, {GenServer, :call, [#PID<0.613.0>, {{"server/server", "ssrRenderComponent"}, ["Mermaid", %{}, %{}], [binary: false, timeout: 30000]}, 30000]}}} while retrieving Exception.message/1 for %NodeJS.Error{message: {:node_js_worker_exit, {{:badarg, [{:erlang, :port_command, [#Port<0.9>, "[[\"server/server\",\"ssrRenderComponent\"],[\"Mermaid\",{},{}]]\n"], [error_info: %{module: :erl_erts_errors}]}, {NodeJS.Worker, :handle_call, 3, [file: 'lib/nodejs/worker.ex', line: 102]}, {:gen_server, :try_handle_call, 4, [file: 'gen_server.erl', line: 1149]}, {:gen_server, :handle_msg, 6, [file: 'gen_server.erl', line: 1178]}, {:proc_lib, :init_p_do_apply, 3, [file: 'proc_lib.erl', line: 240]}]}, {GenServer, :call, [#PID<0.613.0>, {{"server/server", "ssrRenderComponent"}, ["Mermaid", %{}, %{}], [binary: false, timeout: 30000]}, 30000]}}}, stack: nil} (expected a string)
        (nodejs 2.0.0) lib/nodejs/supervisor.ex:80: NodeJS.Supervisor.call!/3
        (live_svelte 0.5.1) lib/ssr.ex:19: LiveSvelte.SSR.render/3
        (live_svelte 0.5.1) lib/component.ex:56: LiveSvelte."render (overridable 1)"/1
        (phoenix_live_view 0.18.18) lib/phoenix_live_view/tag_engine.ex:68: Phoenix.LiveView.TagEngine.component/3
        (kantan 0.1.0) lib/kantan_web/controllers/page_html/mermaid.html.heex:1: anonymous fn/2 in KantanWeb.PageHTML.mermaid/1
        (phoenix_live_view 0.18.18) lib/phoenix_live_view/engine.ex:137: Phoenix.HTML.Safe.Phoenix.LiveView.Rendered.to_iodata/1
        (phoenix_live_view 0.18.18) lib/phoenix_live_view/engine.ex:153: Phoenix.HTML.Safe.Phoenix.LiveView.Rendered.to_iodata/3
        (phoenix 1.7.2) lib/phoenix/controller.ex:1010: anonymous fn/5 in Phoenix.Controller.template_render_to_iodata/4
        (telemetry 1.2.1) /Users/dg/agle/202308/phoenix-ash-svelte-flowbite/deps/telemetry/src/telemetry.erl:321: :telemetry.span/3
        (phoenix 1.7.2) lib/phoenix/controller.ex:976: Phoenix.Controller.render_and_send/4
        (kantan 0.1.0) lib/kantan_web/controllers/page_controller.ex:1: KantanWeb.PageController.action/2
        (kantan 0.1.0) lib/kantan_web/controllers/page_controller.ex:1: KantanWeb.PageController.phoenix_controller_pipeline/2
        (phoenix 1.7.2) lib/phoenix/router.ex:430: Phoenix.Router.__call__/5
        (kantan 0.1.0) lib/kantan_web/endpoint.ex:1: KantanWeb.Endpoint.plug_builder_call/2
        (kantan 0.1.0) deps/plug/lib/plug/debugger.ex:136: KantanWeb.Endpoint."call (overridable 3)"/2
        (kantan 0.1.0) lib/kantan_web/endpoint.ex:1: KantanWeb.Endpoint.call/2
        (phoenix 1.7.2) lib/phoenix/endpoint/sync_code_reload_plug.ex:22: Phoenix.Endpoint.SyncCodeReloadPlug.do_call/4
        (plug_cowboy 2.6.1) lib/plug/cowboy/handler.ex:11: Plug.Cowboy.Handler.init/2
        (cowboy 2.10.0) /Users/dg/agle/202308/phoenix-ash-svelte-flowbite/deps/cowboy/src/cowboy_handler.erl:37: :cowboy_handler.execute/2
        (cowboy 2.10.0) /Users/dg/agle/202308/phoenix-ash-svelte-flowbite/deps/cowboy/src/cowboy_stream_h.erl:306: :cowboy_stream_h.execute/3

Singletons

To avoid wasting memory on features that might not be used, some Svelte frameworks, such as Svelte Skeleton v2, use singleton stores that are intended to be created via top-level SvelteKit files such as +layout.svelte.

<script>
import { initializeStores } from '@skeletonlabs/skeleton';
initializeStores();
</script>

initializeToastStore() does this:

return setContext(TOAST_STORE_KEY, toastStore);

In other words, the Toast store is a singleton that is accessed via a top-level Svelte context that is available to every Svelte component in the application.

A LiveSvelte application needs to initialize the Skeleton toast store somehow. The top-level objects of a Phoenix application are generally app.js and app.html.heex. Of course, using app.js doesn't work because Svelte throws an error when getContext/setContext/hasContext are called outside of component initialization. Apparently, only a .svelte file can initiate a workflow that calls *Context() since contexts are associated with Svelte components.

Heex templates can include Svelte components via LiveSvelte. Can app.html.heex do it? To try, I created a Svelte component that initializes the Toast store. I added the following to the top of app.html.heex: <.svelte name='Toast'>.

Toast.svelte:

<script>
import { initializeStores, Toast } from '@skeletonlabs/skeleton';
initializeStores();
</script>
<Toast />

My application starts fine -- in fact, it works with Svelte Skeleton 1.x so long as you remove the bit about initializeStores. However, this doesn't work with Skeleton 2.x which now uses Svelte contexts. Svelte components must share a common ancestor in order to access the same context instance. Since the above component doesn't have any children, other Svelte components in my application can't access the context singleton created by it. Therefore, they complain that initializeStores has not been called.

Top-level contexts could be established via a parent LiveSvelte component with slots and/or subcomponents. However, such an approach is at odds with creating a Phoenix application that consists of dead views, live views, and LiveSvelte components.

Working with frameworks that require SvelteKit (because of top-level Svelte contexts) would be a huge win because the most interesting parts of the Svelte ecosystem are headed that way.

Simplify tailwind install step

I don't like it copies the entire file, while the important change is just one line. Ideally it changes the target tailwind file and adds the line, and if it can't find it, don't add it. And in addition add some instructions to setup tailwind yourself if you want.

Remove knowledge of LiveView from Svelte components

Hi there

This is great - thanks for this - I was actually going to create something similar but no need now - what you've done is great.

One thing though - I think it would be better if the Svelte components had no idea they were in a LiveView app - currently you're using

<button class="plus" phx-click="increment">
    +1
</button>

from inside the Svelte component, i.e. the Svelte component uses phx-click attribute, which seems wrong to me.

I think the better solution would be for the component to dispatch an event, e.g.

<script>
	import { createEventDispatcher } from 'svelte';

	const dispatch = createEventDispatcher();

	function handleClick() {
		dispatch('increment');
	}
</script>

<button class="plus" on:click={handleClick}>
    +1
</button>

or just using event forwarding,

and for your LiveSvelte.render component to also take an events argument or something, which in turn send a message to LiveView, e.g.

<LiveSvelte.render name="SimpleCounter" props={%{number: @number}} events={%{increment: "increment"}} />

One slightly tricky thing is that ideally you'd be able to map the payload between what gets emitted ----> what you send to the LiveView handler - there would be various approaches for this - I guess sending event.detail wouldn't be a bad default.

Anyway, this way your Svelte components would have no knowledge of LiveView/Phoenix and you could more easily import third-party components, etc.

Just an idea - what do you think?

Only run SSR once on mount

Currently we invoke the SSR render call on every update, this should only happen on mount.

I've found it difficult to achieve as the mount doesn't have the assign attributes and the update and preload function don't actually update the attributes.

I think the way of going about it is setting the state in the parent LiveView somehow and then check if it already ran the SSR render

~V without assigns

I'm using ~V for a dead view that doesn't use assigns. The compiler complains that assigns is defined but not used. So I rename it to _assigns. Then I get the error:

** (RuntimeError) ~H requires a variable named "assigns" to exist and be set to a map
    (phoenix_live_view 0.18.18) expanding macro: Phoenix.Component.sigil_H/2
    lib/kantan_web/controllers/svelte/navigation.ex:6: KantanWeb.Svelte.Navigation.render/2
    (live_svelte 0.5.1) expanding macro: LiveSvelte.sigil_V/2
    lib/kantan_web/controllers/svelte/navigation.ex:6: KantanWeb.Svelte.Navigation.render/2

[QUESTION] SSR Rendering

I have a question regarding server side rendering

LightStatusBar.svelte

<script>
  import { tweened } from "svelte/motion";
  import { cubicOut } from "svelte/easing";
  export let brightness = 0;

  const progress = tweened(0, {
    duration: 400,
    easing: cubicOut,
  });

  const updateProgress = (b) => progress.set(b / 100);

  $: updateProgress(brightness);
</script>

<progress class="border-none w-full rounded-lg h-12" value={$progress} />
<div
  class="h-12 rounded-md w-full font-mono font-semibold"
>
  <div class="text-center w-full flex items-center justify-center h-full">
    {brightness > 0 ? `${brightness}%` : "OFF"}
  </div>
</div>

<style>
  :root{
    --progColor: linear-gradient(to right, hsl(6, 100%, 80%), hsl(356, 100%, 65%));
    --progHeight: 20px;
}

progress, progress::-webkit-progress-value {
    width: 100%;
    border: 0;
    height: var(--progHeight);
    border-radius: 20px;
    background: var(--progColor);
}
progress::-webkit-progress-bar {
    width: 100%;
    border: 0;
    height: var(--progHeight);
    border-radius: 20px;
    background: white;
}

progress::-moz-progress-bar {
    width: 100%;
    border: 0;
    height: var(--progHeight);
    border-radius: 20px;
    background: var(--progColor);
}

</style>

LightControllers.svelte

<script>
  export let pushEvent;
  export let isOn = false;
  const toggleLight = () => {
    isOn = !isOn;
    pushEvent(isOn ? "on" : "off");
  };
</script>

<div class="my-2 flex justify-between items-center">
  <button
    type="button"
    class={`${
      isOn ? "bg-brand" : "bg-gray-200"
    } relative inline-flex h-6 w-11 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-brand focus:ring-offset-2`}
    role="switch"
    aria-checked="false"
    on:click={toggleLight}
  >
    <span class="sr-only">Use setting</span>
    <span
      aria-hidden="true"
      class={`${
        isOn ? "translate-x-5" : "translate-x-0"
      } pointer-events-none inline-block h-5 w-5 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out`}
    />
  </button>
  <div class="flex gap-2">
    <button
      phx-click="down"
      class="flex items-center justify-center text-xl font-bold w-10 h-10 p-2 rounded bg-slate-100 hover:bg-brand active:bg-brand shadow-md hover:shadow-xl"
    >
      <svg
        xmlns="http://www.w3.org/2000/svg"
        fill="none"
        viewBox="0 0 24 24"
        stroke-width="1.5"
        stroke="currentColor"
        class="w-6 h-6"
      >
        <path
          stroke-linecap="round"
          stroke-linejoin="round"
          d="M19.5 8.25l-7.5 7.5-7.5-7.5"
        />
      </svg>
    </button>
    <button
      phx-click="up"
      class="flex items-center justify-center text-xl font-bold w-10 h-10 p-2 rounded bg-slate-100 hover:bg-brand active:bg-brand shadow-md hover:shadow-xl"
    >
      <svg
        xmlns="http://www.w3.org/2000/svg"
        fill="none"
        viewBox="0 0 24 24"
        stroke-width="1.5"
        stroke="currentColor"
        class="w-6 h-6"
      >
        <path
          stroke-linecap="round"
          stroke-linejoin="round"
          d="M4.5 15.75l7.5-7.5 7.5 7.5"
        />
      </svg>
    </button>
  </div>
</div>

live_page.ex

defmodule LightBulbWeb.LivePage do
  use LightBulbWeb, :live_view
  require Logger

  def mount(_params, _session, socket) do
    Logger.info(socket)
    {:ok, assign(socket, %{brightness: 10, previous: nil})}
  end

  def render(assigns) do
    ~H"""
    <div class="max-w-screen-xl mx-auto p-4 flex flex-col gap-4">
      <h1 class="text-center text-2xl font-light my-4">Light Bulb Controller</h1>
      <LiveSvelte.render name="LightStatusBar" props={%{brightness: @brightness}} />
      <LiveSvelte.render name="LightControllers" props={%{isOn: isOn?(@brightness)}} />
    </div>
    """
  end

  def handle_event("up", _, socket) do
    brightness = socket.assigns.brightness
    Logger.info brightness
    case brightness do
      100 ->
        {:noreply, socket}

      _ ->
        new_brightness = brightness + 10
        {:noreply, assign(socket, %{brightness: new_brightness, previous: brightness})}
    end
  end

  def handle_event("down", _, socket) do
    brightness = socket.assigns.brightness
    Logger.info brightness

    case brightness do
      0 ->
        {:noreply, socket}

      _ ->
        new_brightness = brightness - 10
        {:noreply, assign(socket, %{brightness: new_brightness, previous: brightness})}
    end
  end

  def handle_event("on", _, socket) do
    previous = socket.assigns.previous
    brightness = socket.assigns.brightness
    {:noreply, assign(socket, %{brightness: previous, previous: brightness})}
  end

  def handle_event("off", _, socket) do
    previous = socket.assigns.brightness
    {:noreply, assign(socket, %{brightness: 0, previous: previous})}
  end

  defp isOn?(brightness) do
    brightness > 0
  end
end

Even thought I trigger Pheonix function up/down to increase or decrease the brightness, on SSR I do get the initial state of 10%
image
What am I missing? Do I need to change somehow the handle_event functions or is it on the Svelte side?
Thank You

How to use NPM packages for svelte ?

I'm trying to use https://unpic.pics/img/svelte/ but getting an error:

<script lang="ts">
  import { Image } from "@unpic/svelte";
</script>

<nav>
  <div class="flex flex-col justify-center sm:items-start">
    <a
      href="/"
      dir="auto"
      class="break-words whitespace-pre-wrap text-base inline-flex w-max justify-center text-gray-700 no-underline hover:text-gray-600 hover:no-underline sm:justify-start select-none"
      ><div class="flex flex-col relative w-12">
        <Image
          alt="Website name"
          priority={false}
          width={40}
          height={40}
          layout="constrained"
          decoding="async"
          class="bg-transparent object-contain object-center"
          src="/images/app/logo-t-s.webp"
        />
      </div>
    </a>
  </div>
</nav>

Error:

For typescript support, I've simply added typescript as devDependencies

Screenshot 2023-05-07 at 5 00 28 AM

Set HEAD correctly

For the SSR, we sometimes return a head depending if the Svelte component has something like:

<svelte:head>
  <title>Some title</title>
</svelte:head>

Ideally we include this in the root head somehow on first page render, I haven't found a way to do this from the live_component.

Currently this just does not work and we don't include the head, we only include the styling.

Enable discussion panel

The live_svelte packages feel so awesome. Enabling a discussion panel would help people if they wanna discuss stuff about getting started or doing a specific tweak, something that is not an issue.

esbuild 0.17 build & watch steps work completely differently

esbuild broke the way build works starting with 0.17.0 and I'm trying to make it work with live_svelte.

  • Phoenix 1.7.2
  • Win11
  • esbuild "^0.17.19"

I did a bit of fiddling and tried to:

  1. remove any "watch" in optClient and optsServer in build.js:
//
// Comment out usage of "watch" in optClient and optsServer
//    // watch,
//


// const client = esbuild.build(optsClient)
// const server = esbuild.build(optsServer)

// if (watch) {
//     client.then(_result => {
//         process.stdin.on("close", () => process.exit(0))
//         process.stdin.resume()
//     })

//     server.then(_result => {
//         process.stdin.on("close", () => process.exit(0))
//         process.stdin.resume()
//     })
// }
const ctx0 = esbuild.context(optsClient)

ctx0.then(v => {
    if (watch) {
        v.watch().then(v => {
            
        })
        v.dispose();
    }
});

const ctx1 = esbuild.context(optsServer)

ctx1.then(v => {
    if (watch) {
        v.watch().then(v => {
            
        })
        v.dispose();
    }
});

(I know I would want to use "await" but esbuild is not happy that it's top-level)

I also ended up adding a bunch of dependencies to package.json not mentioned in the README:

{
  "devDependencies": {
  },
  "dependencies": {
    "esbuild": "^0.17.19",

    "esbuild-svelte": "^0.7.3",
    "esbuild-plugin-import-glob": "^0.1.1",
    "svelte-preprocess": "^5.0.4",

    "phoenix": "file:../deps/phoenix",
    "phoenix_html": "file:../deps/phoenix_html",
    "phoenix_live_view": "file:../deps/phoenix_live_view"
  }
}

I feel I'm close. The only error I'm getting is this one:

mix.bat phx.server
[info] Running ProjectWeb.Endpoint with cowboy 2.10.0 at 127.0.0.1:4000 (http)
[info] Access ProjectWeb.Endpoint at http://localhost:4000
[watch] build finished, watching for changes...
[watch] build finished, watching for changes...
X [ERROR] Could not resolve "live_svelte"

    js/app.js:31:25:
      31 Γöé import { getHooks } from "live_svelte"
         Γò╡                          ~~~~~~~~~~~~~

  You can mark the path "live_svelte" as external to exclude it from the bundle, which will remove this error.

1 error

Rebuilding...

Done in 454ms.

So I wonder if there's any hints for me. I love where this project is going VERY much! Now I would love it to actually work too 🥇

mix assets.build and assets.deploy fail

Am I using mix assets.build and mix assets.deploy correctly? They both output the same error message.

mix assets.build

Rebuilding...

Done in 1772ms.
✘ [ERROR] Could not resolve "../svelte/**/*.svelte"

    js/app.js:25:28:
      25 │ import * as Components from "../svelte/**/*.svelte"

build.js for esbuild 0.17+

Thank you for updating build.js to use svelte-preprocess!

I ran mix live_svelte.setup with live_svelte version 0.11.0. build.js only works with esbuild version 0.16.x and earlier because the 'watch' implementation changed.

If you don't pin esbuild to version 0.16.x in package.json, build.js should look something like this.

Simplify setup process

I think there should be an easer way to install LiveSvelte:

  • We might not need a config.exs record as we can get the server file path directly from within the js file
  • Maybe we can avoid having to manually set the otp_name on the NodeJS.Supervisor entry

Add Support button in Github repo

Awesome stack.
Loving every bit of it. Allow us to support this project by becoming a patron.
I believe this Phoenix + Svelte combo has a lot of potential. Cheers

Disable SSR for ~V

Need an option to disable SSR for a Svelte implemented with the ~V sigil.

Improve performance SSR rendering

Currently SSR takes about 8ms each render in production, and about 20-40ms in dev, and this is being executed synchronously.
So let's say you have 10 components inside a LiveView, it'll end up taking 80ms!

When turning off SSR it's super fast, you can easily render a 100 components and not feel any delay.

The culprit is the call to NodeJS.

Doing the following things will probably do the trick.

  • Reduce the amount of time to call NodeJS
  • Run asynchronously somehow, I'm not sure how to do this inside a HEEx template.

Maybe Bun is the answer here, or a better way of calling Node.

Get rid of morpdom for svelte templates

I love the idea of having a dedicated sigil for the templates but I just looked at the payload with the svelte template and it sends the whole props for the todo list.
Maybe removing the morphdom from the svelte templates may be a good idea and just consume the messages directly - I think live view native allows created a common library for different types of clients - https://native.live/

You may also have a look at
https://github.com/hansihe/live_data - https://www.youtube.com/watch?v=I4vVxtrow-E
https://github.com/Miserlou/live_json

Feature: Run SSR with deno_ex

There are many benefits of Deno over NodeJS (e.g., it seems like it might be lighter weight since some of the legacy libraries have been removed), but there may be compatibility issues.

deno_ex might be the best vehicle to get there.

Use sigil for rendering Svelte Component

I'd love to be able to just do the following and render Svelte directly from a LiveComponent:

defmodule App.LiveComponent do
  use LiveSvelte.LiveComponent

  attr(:foo, :string, default: "")
  attr(:bar, :string)

  def render(assigns) do
    ~v"""
    <script>
        export let foo = "foo";
        export let bar = "bar"
        export let pushEvent;
    </script>

    <h1>It's working!</h1>
    """
  end
end

No package.json on Windows

Not a super big issue but when following the installation steps of the readme, no package.json gets generated.
The easy fix was to copy and paste the one from the example_project/assets and correcting the paths.

{
"devDependencies": {
"@types/lodash": "^4.14.192",
"dynamic-marquee": "^2.6.2",
"esbuild": "^0.16.17",
"esbuild-plugin-import-glob": "^0.1.1",
"esbuild-svelte": "^0.7.4",
"lodash": "^4.17.21",
"stylus": "^0.55.0",
"svelte": "^4.1.2",
"svelte-preprocess": "^5.0.4",
"typescript": "^4.9.5"
},
"dependencies": {
"live_json": "file:../deps/live_json",
"live_svelte": "file:../deps/live_svelte",
"phoenix": "file:../deps/phoenix",
"phoenix_html": "file:../deps/phoenix_html",
"phoenix_live_view": "file:../deps/phoenix_live_view",
"svelvet": "^8.1.0"
}
}

Thought that some other "'weirdos" working on Windows like me might find it useful.

Slot Support

Slots are not supported by LiveSvelte because of issues in Svelte itself. I don't have the issue number but once it's resolved, this usage can be officially supported.

A working named slot example is in the following files. Timeline.svelte optionally accepts a slot named 'toast.' Other use cases might not work.

Note: The Svelte way to specify slot content is something like < span slot='slot_name'> . This doesn't work in Heex templates. Use the Phoenix <: slot_name> way instead.

Another downside is that Elixir warns when compiling:

warning: undefined slot "toast" for component LiveSvelte.svelte/1
  lib/kantan_web/controllers/page_html/timeline.html.heex:6
  1. https://github.com/dev-guy/phoenix-ash-svelte-flowbite/blob/main/lib/kantan_web/controllers/page_html/timeline.html.heex

  2. https://github.com/dev-guy/phoenix-ash-svelte-flowbite/blob/main/assets/svelte/Timeline.svelte

Support LiveView 0.19

Getting this dependency error when trying to update to LiveView 0.19:

Because your app depends on live_svelte ~> 0.7.0 which depends on phoenix_live_view ~> 0.18.3, phoenix_live_view ~> 0.18.3 is required.

SSR crash

I filed this issue previously but I have since disabled SSR because I've had so many problems with it. Today even the 'counter' example wasn't working at all with SSR enabled (I'm using NodeJS 20.2.0) -- but it inexplicably started working again. The following scenario is consistent, however:

  1. git clone https://github.com/dev-guy/phoenix-ash-svelte-flowbite.git
  2. cd phoenix*
  3. git checkout add-ssr
  4. Follow the Usage section in README.md (ending with mix phx.server). Hopefully you have Postgres installed already.
  5. Go to http://localhost:4000/svelte/mermaid
  6. Go to http://localhost:4000/svelte/mermaid again (refresh the browser)

Result: Error in browser. The following is sent to the console:

[error] #PID<0.1282.0> running Phoenix.Endpoint.SyncCodeReloadPlug (connection #PID<0.802.0>, stream id 51) terminated
Server: localhost:4000 (http)
Request: GET /svelte/mermaid
** (exit) an exception was raised:
    ** (NodeJS.Error) got {:node_js_worker_exit, {{:badarg, [{:erlang, :port_command, [#Port<0.70>, "[[\"server/server\",\"ssrRenderComponent\"],[\"Mermaid\",{},{}]]\n"], [error_info: %{module: :erl_erts_errors}]}, {NodeJS.Worker, :handle_call, 3, [file: 'lib/nodejs/worker.ex', line: 102]}, {:gen_server, :try_handle_call, 4, [file: 'gen_server.erl', line: 1113]}, {:gen_server, :handle_msg, 6, [file: 'gen_server.erl', line: 1142]}, {:proc_lib, :init_p_do_apply, 3, [file: 'proc_lib.erl', line: 241]}]}, {GenServer, :call, [#PID<0.1217.0>, {{"server/server", "ssrRenderComponent"}, ["Mermaid", %{}, %{}], [binary: false, timeout: 30000]}, 30000]}}} while retrieving Exception.message/1 for %NodeJS.Error{message: {:node_js_worker_exit, {{:badarg, [{:erlang, :port_command, [#Port<0.70>, "[[\"server/server\",\"ssrRenderComponent\"],[\"Mermaid\",{},{}]]\n"], [error_info: %{module: :erl_erts_errors}]}, {NodeJS.Worker, :handle_call, 3, [file: 'lib/nodejs/worker.ex', line: 102]}, {:gen_server, :try_handle_call, 4, [file: 'gen_server.erl', line: 1113]}, {:gen_server, :handle_msg, 6, [file: 'gen_server.erl', line: 1142]}, {:proc_lib, :init_p_do_apply, 3, [file: 'proc_lib.erl', line: 241]}]}, {GenServer, :call, [#PID<0.1217.0>, {{"server/server", "ssrRenderComponent"}, ["Mermaid", %{}, %{}], [binary: false, timeout: 30000]}, 30000]}}}, stack: nil} (expected a string)
        (nodejs 2.0.0) lib/nodejs/supervisor.ex:80: NodeJS.Supervisor.call!/3
        (live_svelte 0.5.1) lib/ssr.ex:19: LiveSvelte.SSR.render/3
        (live_svelte 0.5.1) lib/component.ex:56: LiveSvelte."render (overridable 1)"/1
        (phoenix_live_view 0.18.18) lib/phoenix_live_view/tag_engine.ex:68: Phoenix.LiveView.TagEngine.component/3
        (kantan 0.1.0) lib/kantan_web/controllers/page_html/mermaid.html.heex:1: anonymous fn/2 in KantanWeb.PageHTML.mermaid/1
        (phoenix_live_view 0.18.18) lib/phoenix_live_view/engine.ex:137: Phoenix.HTML.Safe.Phoenix.LiveView.Rendered.to_iodata/1
        (phoenix_live_view 0.18.18) lib/phoenix_live_view/engine.ex:153: Phoenix.HTML.Safe.Phoenix.LiveView.Rendered.to_iodata/3
        (phoenix 1.7.2) lib/phoenix/controller.ex:1010: anonymous fn/5 in Phoenix.Controller.template_render_to_iodata/4
        (telemetry 1.2.1) /Users/dg/agle/202308/phoenix-ash-svelte-flowbite/deps/telemetry/src/telemetry.erl:321: :telemetry.span/3
        (phoenix 1.7.2) lib/phoenix/controller.ex:976: Phoenix.Controller.render_and_send/4
        (kantan 0.1.0) lib/kantan_web/controllers/page_controller.ex:1: KantanWeb.PageController.action/2
        (kantan 0.1.0) lib/kantan_web/controllers/page_controller.ex:1: KantanWeb.PageController.phoenix_controller_pipeline/2
        (phoenix 1.7.2) lib/phoenix/router.ex:430: Phoenix.Router.__call__/5
        (kantan 0.1.0) lib/kantan_web/endpoint.ex:1: KantanWeb.Endpoint.plug_builder_call/2
        (kantan 0.1.0) deps/plug/lib/plug/debugger.ex:136: KantanWeb.Endpoint."call (overridable 3)"/2
        (kantan 0.1.0) lib/kantan_web/endpoint.ex:1: KantanWeb.Endpoint.call/2
        (phoenix 1.7.2) lib/phoenix/endpoint/sync_code_reload_plug.ex:22: Phoenix.Endpoint.SyncCodeReloadPlug.do_call/4
        (plug_cowboy 2.6.1) lib/plug/cowboy/handler.ex:11: Plug.Cowboy.Handler.init/2
        (cowboy 2.10.0) /Users/dg/agle/202308/phoenix-ash-svelte-flowbite/deps/cowboy/src/cowboy_handler.erl:37: :cowboy_handler.execute/2
        (cowboy 2.10.0) /Users/dg/agle/202308/phoenix-ash-svelte-flowbite/deps/cowboy/src/cowboy_stream_h.erl:306: :cowboy_stream_h.execute/3

Other Items of Interest

  1. http://localhost:4000/svelte/counter is the classic counter example
  2. http://localhost:4000/svelte/timeline crashes because it says < Accordion> doesn't support SSR. However, SSR works fine with this component when running under SvelteKit. It's also a devDependency (regular dependencies cause problems with SSR). No idea what's going on! Maybe it's esbuild's fault. I need to experiment with vite.

Make goto work

  • goto without props
  • goto actually transitions
  • make sure the SSR keeps working

Cannot read properties of undefined (reading 'render')

I'm getting the following error when trying to SSR a component, the node version i'm running is v19.9.0, any ideas of how I can dig into this further? Thanks for creating this :)

[error] #PID<0.18745.0> running Phoenix.Endpoint.SyncCodeReloadPlug (connection #PID<0.17637.0>, stream id 35) terminated
Server: localhost:4000 (http)
Request: GET /organizations
** (exit) an exception was raised:
    ** (NodeJS.Error) Cannot read properties of undefined (reading 'render')
TypeError: Cannot read properties of undefined (reading 'render')
    at render (/Users/vento/Documents/projects/solosoftware/wut/priv/static/assets/server/server.js:450:20)
    at callModuleFunction (/Users/vento/Documents/projects/solosoftware/wut/deps/nodejs/priv/server.js:32:23)
    at getResponse (/Users/vento/Documents/projects/solosoftware/wut/deps/nodejs/priv/server.js:44:26)
    at Interface.onLine (/Users/vento/Documents/projects/solosoftware/wut/deps/nodejs/priv/server.js:53:39)
    at Interface.emit (node:events:513:28)
    at Interface._onLine (node:readline:491:10)
    at Interface._normalWrite (node:readline:665:12)
    at Socket.ondata (node:readline:272:10)
    at Socket.emit (node:events:513:28)
    at addChunk (node:internal/streams/readable:315:12)
        (nodejs 2.0.0) lib/nodejs/supervisor.ex:80: NodeJS.Supervisor.call!/3
        (live_svelte 0.9.0) lib/ssr.ex:19: LiveSvelte.SSR.render/3
        (live_svelte 0.9.0) lib/component.ex:73: LiveSvelte."svelte (overridable 1)"/1
        (phoenix_live_view 0.19.4) lib/phoenix_live_view/tag_engine.ex:68: Phoenix.LiveView.TagEngine.component/3
        (wut 0.1.0) lib/wut_web/components/layouts/app.html.heex:30: anonymous fn/2 in WutWeb.Layouts.app/1
        (phoenix_live_view 0.19.4) lib/phoenix_live_view/diff.ex:386: Phoenix.LiveView.Diff.traverse/7
        (phoenix_live_view 0.19.4) lib/phoenix_live_view/diff.ex:136: Phoenix.LiveView.Diff.render/3
        (phoenix_live_view 0.19.4) lib/phoenix_live_view/static.ex:252: Phoenix.LiveView.Static.to_rendered_content_tag/4
        (phoenix_live_view 0.19.4) lib/phoenix_live_view/static.ex:135: Phoenix.LiveView.Static.render/3
        (phoenix_live_view 0.19.4) lib/phoenix_live_view/controller.ex:39: Phoenix.LiveView.Controller.live_render/3
        (phoenix 1.7.7) lib/phoenix/router.ex:430: Phoenix.Router.__call__/5
        (wut 0.1.0) lib/wut_web/endpoint.ex:1: WutWeb.Endpoint.plug_builder_call/2
        (wut 0.1.0) deps/plug/lib/plug/debugger.ex:136: WutWeb.Endpoint."call (overridable 3)"/2
        (wut 0.1.0) lib/wut_web/endpoint.ex:1: WutWeb.Endpoint.call/2
        (phoenix 1.7.7) lib/phoenix/endpoint/sync_code_reload_plug.ex:22: Phoenix.Endpoint.SyncCodeReloadPlug.do_call/4
        (plug_cowboy 2.6.1) lib/plug/cowboy/handler.ex:11: Plug.Cowboy.Handler.init/2
        (cowboy 2.10.0) /Users/vento/Documents/projects/solosoftware/wut/deps/cowboy/src/cowboy_handler.erl:37: :cowboy_handler.execute/2
        (cowboy 2.10.0) /Users/vento/Documents/projects/solosoftware/wut/deps/cowboy/src/cowboy_stream_h.erl:306: :cowboy_stream_h.execute/3
        (cowboy 2.10.0) /Users/vento/Documents/projects/solosoftware/wut/deps/cowboy/src/cowboy_stream_h.erl:295: :cowboy_stream_h.request_process/3
        (stdlib 5.0.2) proc_lib.erl:241: :proc_lib.init_p_do_apply/3

js/render module not found on server

https://elixirforum.com/t/livesvelte-e2e-reactivity-in-liveview-with-svelte/54822/4

Hi @woutdp thanks for creating this project! I’ve used it successfully in a DEV environment, but I can’t figure out how to get SSR to work when I deploy it to fly.io.

Request: GET /demo/select_tickets
** (exit) an exception was raised:
** (NodeJS.Error) Cannot find module 'js/render'
Require stack:
- /app/lib/nodejs-2.0.0/priv/server.js
Error: Cannot find module 'js/render'
Require stack:
- /app/lib/nodejs-2.0.0/priv/server.js
at Function.Module._resolveFilename (node:internal/modules/cjs/loader:1021:15)
at Function.resolve (node:internal/modules/cjs/helpers:114:19)
at requireModule (/app/lib/nodejs-2.0.0/priv/server.js:10:34)
at requireModuleFunction (/app/lib/nodejs-2.0.0/priv/server.js:25:15)
at callModuleFunction (/app/lib/nodejs-2.0.0/priv/server.js:31:14)
at getResponse (/app/lib/nodejs-2.0.0/priv/server.js:44:26)
at Interface.onLine (/app/lib/nodejs-2.0.0/priv/server.js:53:39)
at Interface.emit (node:events:513:28)
at Interface._onLine (node:readline:491:10)
at Interface._normalWrite (node:readline:665:12)
(nodejs 2.0.0) lib/nodejs/supervisor.ex:80: NodeJS.Supervisor.call!/3
(live_svelte 0.3.5) lib/ssr.ex:19: LiveSvelte.SSR.render/3
(live_svelte 0.3.5) lib/component.ex:56: LiveSvelte."render (overridable 1)"/1
(phoenix_live_view 0.18.18) lib/phoenix_live_view/tag_engine.ex:68: Phoenix.LiveView.TagEngine.component/3
(camp 0.1.1) lib/camp_web/live_demo/demo_select_tickets_live.ex:112: anonymous fn/2 in CampWeb.DemoSelectTicketsLive.render/1
(phoenix_live_view 0.18.18) lib/phoenix_live_view/diff.ex:398: Phoenix.LiveView.Diff.traverse/7
(phoenix_live_view 0.18.18) lib/phoenix_live_view/diff.ex:544: anonymous fn/4 in Phoenix.LiveView.Diff.traverse_dynamic/7

I’ve checked that I’ve installed NodeJS on both the builder and runner images, and I’ve tried both 16.x and 18.x versions.

When I remote console into the running application, I get:

NodeJS.call("console.log", ["helloworld"])
{:error,
 "Cannot find module 'console.log'\nRequire stack:\n- /app/lib/nodejs-2.0.0/priv/server.js\nError: Cannot find module 'console.log'\nRequire stack:\n- /app/lib/nodejs-2.0.0/priv/server.js\n    at Function.Module._resolveFilename (node:internal/modules/cjs/loader:1021:15)\n    at Function.resolve (node:internal/modules/cjs/helpers:114:19)\n    at requireModule (/app/lib/nodejs-2.0.0/priv/server.js:10:34)\n    at requireModuleFunction (/app/lib/nodejs-2.0.0/priv/server.js:25:15)\n    at callModuleFunction (/app/lib/nodejs-2.0.0/priv/server.js:31:14)\n    at getResponse (/app/lib/nodejs-2.0.0/priv/server.js:44:26)\n    at Interface.onLine (/app/lib/nodejs-2.0.0/priv/server.js:53:39)\n    at Interface.emit (node:events:513:28)\n    at Interface._onLine (node:readline:491:10)\n    at Interface._normalWrite (node:readline:665:12)"}
I couldn’t find any solutions on the [elixir-nodejs 1](https://github.com/revelrylabs/elixir-nodejs) docs either.

It works well when I remove the NodeJS.Supervisor from application.ex.

Any guidance would be much appreciated!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.