Dear Phoenix community,
Phoenix 1.5.3. LiveView 0.13.2. Is there a way to use LiveView without webpack or is it considered a bad idea ?
I do not like webpack for different reasons (opacity, too much JS, JS doing too much stuff, JS concerned with CSS or other stuff, npm with lot of modules, …) and the web part of my project being relatively small, I do not need a builder to manage dependencies and tons of JS files. I need to load CSS and JS per web page, not as one single big blob of code in app.js
, because I need to use different JS/CSS depending on the web page I am currently on. I have the feeling that webpack is more suited to SPAs (single-page applications). I guess that in a bigger project webpack provides some great help and as such becomes mandatory.
I noticed that it is not possible to use --live
with --no-webpack
at project creation time (with mix
).
In particular I have this error :
Uncaught TypeError: Failed to resolve module specifier "morphdom". Relative references must start with either "/", "./", or "../".
I know I don’t use webpack and as such the import mechanism cannot simply use module names because it needs a path (absolute, relative or an URL). I could adapt phoenix_live_view.js
to add a path to import morphdom from "morphdom"
but I don’t even know where morphdom
is located. I did not find it in node_modules
.
I have an app_module.js
file which contains the content of app.js
slightly modified. Note that phoenix.js
and phoenix_live_view.js
are imported with relative paths.
import {Socket} from "./phoenix.js"
import LiveSocket from "./phoenix_live_view.js"
let csrfToken = document.querySelector("meta[name='csrf-token']").getAttribute("content")
let liveSocket = new LiveSocket("/live", Socket, {params: {_csrf_token: csrfToken}})
liveSocket.connect()
window.liveSocket = liveSocket
In my root.html.leex
, I load the module using:
<script type="module" src="<%= Routes.static_path(@conn, "/js/app_module.js") %>"></script>
As a side note, I have a PoC which is working ok but without LiveView. I intend to load some modules dynamically like in the code below or simply by adding a script
element through render_existing
(added below too).
document.addEventListener("DOMContentLoaded", function () {
const body_id = document.getElementsByTagName("body").item(0).getAttribute("id");
console.log(`app_module.js. DOMContentLoaded. body id: ${body_id}`);
if (body_id === "one") {
(async () => {
const module = await import('./one_module.js')
// module.default();
module.init();
})();
}
});
<%= render_existing(view_module(@conn), "css." <> view_template(@conn), assigns) %>
<%= if assigns[:live_module] do %>
<%= render_existing @live_module, "css", assigns %>
<% end %>
and
<%= render_existing(view_module(@conn), "js." <> view_template(@conn), assigns) %>
<%= if assigns[:live_module] do %>
<%= render_existing @live_module, "js", assigns %>
<% end %>