adamu

adamu

I’m trying to build a project using phx.new’s --no-assets flag. I don’t want a frontend build step - only static JS and CSS files. I don’t want to use Tailwind or Esbuild dependencies, however I do want to use LiveView.

LiveView does not work out of the box with --no-assets, because the required setup is not placed into app.js by the generator. Here is the regular generated app.js, and the one for --no-assets. You can see that the 2nd one doesn’t perform the necessary LiveView setup.

If I generate a new phoenix project without --no-assets, compile the assets, and copy the generated app.js to my --no-assets project, LiveView works. But I want to get LiveView working with just static compile-time JS files, without a build step for the JS.

I have attempted to rebuild the app.js file myself, by manually coping the relevant JS files from the dependencies to /priv/static and altering the import statements to things like:

import { Socket } from "./phoenix.js" // not "phoenix"

The browser does load this file, but it generates this error:

The requested module ‘http://localhost:4000/assets/js/phoenix.js’ doesn’t provide an export named: ‘Socket’

Is there a way to get LiveView working out of the box with the distributed Javascript using only the browser? Or do I need to have at least some kind of step to compile the required ‘runtime’ Javascript?

Showing Posts 1 to 3

netoum

netoum

When you use the --no-assets option, the generator will create a default js in priv/static/js/app.js

It tells you to manually add theLive View JS

// For Phoenix.HTML support, including form and button helpers
// copy the following scripts into your javascript bundle:
// * deps/phoenix_html/priv/static/phoenix_html.js

// For Phoenix.Channels support, copy the following scripts
// into your javascript bundle:
// * deps/phoenix/priv/static/phoenix.js

// For Phoenix.LiveView support, copy the following scripts
// into your javascript bundle:
// * deps/phoenix_live_view/priv/static/phoenix_live_view.js

It also warns you to use it this way in the mix phx.new documentation

--no-esbuild - do not include esbuild dependencies and assets. We do not recommend setting this option, unless for API only applications, as doing so requires you to manually add and track JavaScript dependencies

I believe your goal is to use Live View without JS bundler
You can absolutely do it, the most direct but not recommended is (for learning purposes) :

  1. Copy deps/phoenix/priv/static/phoenix.js to you priv/static/js

  2. Edit your priv/static/js/app.js to add the following (no import needed)

const csrfToken = document.querySelector("meta[name='csrf-token']").getAttribute("content")
const liveSocket = new LiveView.LiveSocket("/live", Phoenix.Socket, {
  longPollFallbackMs: 2500,
  params: {_csrf_token: csrfToken}
})
liveSocket.connect()
window.liveSocket = liveSocket
  1. Add the following to your root.heex.html :
<script defer phx-track-static type="text/javascript" src={~p"/assets/js/phoenix_live_view.js"}>

However a better way is to use Plug.Static to fetch an updated minified version from the Live View deps

  1. Add the following to your `endpoint.ex
  plug Plug.Static,
    at: "/vendor/phoenix_live_view",
    from: {:phoenix_live_view, "priv/static"},
    only: ~w(phoenix_live_view.min.js),
    gzip: not code_reloading?
  1. Edit your priv/static/js/app.js to add the following (no import needed)
const csrfToken = document.querySelector("meta[name='csrf-token']").getAttribute("content")
const liveSocket = new LiveView.LiveSocket("/live", Phoenix.Socket, {
  longPollFallbackMs: 2500,
  params: {_csrf_token: csrfToken}
})
liveSocket.connect()
window.liveSocket = liveSocket
  1. Add the following to your root.heex.html :
<script phx-track-static type="text/javascript" src="/vendor/phoenix_live_view/phoenix_live_view.min.js"></script>

But once again the recommended approach is to use the --asset option (by default) of mix phx.new

Hope this helps

adamu

adamu OP

Thank you for the response!

The suggestion to use the fully-qualified module names worked, thank you!

The other requirement was that app.js needs to come after the includes to the phoenix scripts in root.html.heex:

<script defer phx-track-static type="text/javascript" src={~p"/assets/js/phoenix.js"} />
<script defer phx-track-static type="text/javascript" src={~p"/assets/js/phoenix_html.js"} />
<script defer phx-track-static type="text/javascript" src={~p"/assets/js/phoenix_live_view.js"} />
<script defer phx-track-static type="text/javascript" src={~p"/assets/js/app.js"} />

Do you have any idea why the import statement was not working, even though the browser could load the script? Perhaps that only works with esbuild, not when running directly in the browser?

netoum

netoum

“To import or not to import, this is the question” :laughing:
Javascript has different module formats and each require different type of setup and imports

Phoenix JS is exported in the following formats: ESM, CJS and IIFE.
https://github.com/phoenixframework/phoenix/blob/main/config/config.exs
You can use any depending on your needs

A possible reason the import statement is not working is that your script is not loaded as a module.
Try adding `type=“module” to your script import

You can read more about Javascript modules history and differences
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules

The general advise it to use ESM whenever possible as it offers the latest and more complete features

— All posts loaded —

Where Next? Top

Trending in Questions Top

Blokh
Hey guys, I’ve got a huge CSV ( around 10 GB ) that needs to be processed hourly Do you guys have any suggestions what is the best prac...
New
RSP87
I’m working on a project that simulates the bumbl example in the programming phoenix book. It acts almost like an email client. We have a...
New
kszambelanczyk
Hello! Could someone please give me a help/sample code, how to delete a file from s3 using waffle/waffle_ecto from Phoenix app. I creat...
New
RemyXRenard
I’m seeing that a list inside a Kino.DataTable will be interpreted as a charlist, even if the Kino.configure() is set to charlists: :as_l...
New
velrest
So my question is quite simple and i have found no conclusive answer on forum, google or AI. Should we use :erlang.float for Integer to ...
New
samoloth
Hi, I’ve just set up an application with ash_authentication. There is only magic link strategy for now, so there is no confirmation add o...
New
FlyingNoodle
If a change or preparation module uses Ash.Changeset.get_argument/2 or Ash.Query.get_argument/2 (or any of the other get_argument functio...
New

Other Trending Topics Top

mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
garrison
Hobbes is a low-level distributed database for the Elixir programming language. Hobbes provides a simple, safe, and scalable storage lay...
New
marciok
Hi there! We created Gust: A task orchestrator inspired by Airflow. For those who have never heard about Aiflow, it’s a Python-based wor...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
Damirados
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge &amp; Solve. They are GUI (Emerge) and State management (S...
New
netoum
Corex is an accessible, unstyled UI component library for Phoenix that integrates Zag.js state machines using Vanilla JavaScript and Live...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews