ryloric

ryloric

Hi!,

What’s the best way to sprinkle bits of javascript for use inside EEx templates, just simple things like handling button clicks, hiding tags etc. I’ve been using a <script> tag at the bottom of the template with some common functions in a global object created in assets/js/app.js.

Is this a reasonable pattern? What are recommended/best-practices around this?

Sorry if this question is a bit naive, I’m pretty new to web-dev and js in general.

Showing Posts 1 to 10

peerreynders

peerreynders

Welcome to the forum!

A vanilla phoenix project is structured around modular javascript.

If you don’t want to use a bundler you can always specify:

mix phx.new PATH --no-webpack

Any additional assets are then kept directly under priv/static.

It may be necessary to adjust the endpoint to pick up assets under non-standard directories.


That being said npm is currently the de facto mechanism for publishing JavaScript libraries (essentially making bower redundant) - so there is significant drive towards adopting a bundler that works with npm.

adrianrl

adrianrl

Hi, you can create helper functions into separate files, it’s a very common and modular approach, something like:

helpers/buttons.js - Handle clicks for buttons
helpers/inputs.js - Handle events for inputs
helpers/animations.js - Handle animations for elements

Then you just import those files inside your main script to include them in your bundle.

Also I’d recommend using the defer attribute rather than putting <script> at the bottom. With defer the browser will download the script while the HTML is being parsed. If you put <script> at the bottom, the browser will parse the HTML and when it hits the <script> tag, it will download the script, so technically is slower.

Here’s a nice article about this: https://flaviocopes.com/javascript-async-defer/

I’d definitively not recommend async if you split your bundle.

peerreynders

peerreynders

And defer seems to be well supported these days.

The problem with a plain or async head script is that it delays FCP (first contentful paint).

You still have to be careful in some situations:

Use async or defer

sfusato

sfusato

Take a look at Stimulus. This is exactly its use case.

Stimulus is a JavaScript framework with modest ambitions. It doesn’t seek to take over your entire front-end—in fact, it’s not concerned with rendering HTML at all. Instead, it’s designed to augment your HTML with just enough behavior to make it shine. Stimulus pairs beautifully with Turbolinks to provide a complete solution for fast, compelling applications with a minimal amount of effort.

sync08

sync08

I think this is a pretty reasonable way to start for your use case. The only possible issue is that your JS doesn’t go through the webpack pipeline if you do it page by page so any transformation / optimisation / minification will have to be done manually.

There is also the option of adding more entrypoints to the webpack config file. I tend to do this when I have shared JS relating to a feature spanning multiple pages. So instead of just app.js or sprinkles at the bottom of the page I’ll have blog.js, store.js, admin.js e.t.c.

ryloric

ryloric OP

Thanks for taking the time to reply!

I think I understand webpack a little better now, but what I’m a little unclear about is why we need to use a bundler at all with phoenix apps.

If my understanding is correct, SPA apps send a big blob of JS to the client, which once parsed and initialized creates markup, and handles everything client-side. So, it makes sense for them to pack everything into a single app.js and send when the page first loads.

In phoenix though, everything is handled on the server, so I’m confused as to why we’re sending the whole app.js bundle on each page load. It’s not like we send all our HTML each page load, we only send the layout and what’s required for that page to render, why not do the same with JS? Load common libraries in the layout template and load page specific js in their respective templates.

I feel like I’m missing something obvious, but not sure what it is.

NobbZ

NobbZ

You are not “sending”, you only specify the resources source. The browser then chooses to cache or not to cache this resource and is free to not download it again in the future.

This way you can massively decrease the number of requests made to your server. Also a single large request is usually more effecient regarding the payload/header ratio than many small ones.

Of course you are totally free to use many entry points and separate your scripts that way you describe.

peerreynders

peerreynders

Also bundling makes it possible to use modular JavaScript in the browser.

The bundler organizes the code in such a way that the various modules only interact with one another in a well defined manner. Browserify started doing this in 2011. It’s only since about 2017 that browsers started supporting ECMAScript modules natively - and even then using them tends to lead to a lot of additional requests because the aren’t bundled.

ryloric

ryloric OP

Thanks! It makes sense now, I was naively assuming browsers download it everytime.

syukronrm

syukronrm

Hi everyone, newcomer here

Is there any pattern or library that has a similar pattern to Laravel’s blade templating [1]?

I think it is very straightforward when we want to add css or js on a single page.

@extends('layouts.app')

@section('title', 'Page Title')

@section('css')
  .foo {
    margin: 0px;
  }
@endsection

@section('js')
  var foo = "bar";
@endsection

[1] Blade Templates | Laravel 5.8 - The clean stack for Artisans and agents

Where Next? Top

Trending in Questions Top

stjefim
Hello! Suppose you are building workflow (order / task / payment) processing system with the following requirements: Each workflow con...
New
itzmidinesh
Hi all, I’m working on a Phoenix project where I need to make external HTTP requests and I’m trying to choose between Req and HTTPoison....
New
yarrichar
I’m very new to Elixir, so sorry if this is a silly question: I am wondering what happens to the mailbox of a process when the machine i...
New
pragdave
How do I tell Hologram not to escape HTML when substituting into templates? {Textile.render(@product.long_description)} escapes the HTM...
New
Fl4m3Ph03n1x
Background When trying to execute mix release on a Windows 11 machine for a Phoenix project I get the following error: * assembling mark...
New
leoschweizer
Hi, we run different LLM models across a cluster, with each node loading a configurable subset. Model-specific queues let nodes consume ...
New
rlipscombe
I’d like to create a file with 600 permissions (rw-------), but there’s a race condition if I create it and then change the permissions. ...
New

Other Trending Topics Top

dominicletz
Hey there, I haven’t seen a list of useful Elixir specific skills for the popular AI tools yet so I’m starting one here with my first. ...
New
raa-ziq
Hi everyone :waving_hand: I wanted to share something I’ve been building — NowBlind, a random chat app designed to help people discover ...
New
mudasobwa
I fully migrated to my own harness from Anthropic/Gemini and I think it’s time to share it. Welcome DSH, the DeepSeek Harness, fully writ...
New
KristerV
Hey. Is there anyone here who creates agents in their apps? Not talking about using agents, but creating them. I’m finding it pretty diff...
New
OndrejValenta
(I just needed to vent somewhere and LinkedIn is full of hope, or hype, I’m not sure which exactly) AI dream has many faces, but general...
New
kip
Localize is the next generation localisation library for Elixir. Think of it as ex_cldr version 3.0. The first version will be released ...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews