idi527

idi527

Has anyone used lazy loading in a phoenix live view project?

I’m currently in a process of optimising the client part of a liveview app and wondered if anyone had tried using lazy loading with liveview.


My current approach is:

  1. Import heavy dependencies like charting libs with dynamic imports in liveview hooks:
async function createChart(config, el) {
  const [am4core, am4charts] = await Promise.all([
    import(/* webpackChunkName: "amcharts4-core" */ "@amcharts/amcharts4/core"),
    import(/* webpackChunkName: "amcharts4-charts" */ "@amcharts/amcharts4/charts"),
  ]);

  return am4core.createFromConfig(config, el, am4charts.XYChart);
}

const ChartHook = {
  config() {
    return JSON.parse(this.el.dataset.config);
  },

  async mounted() {
    this.chart = await createChart(this.config(), this.el);
  },

  beforeDestroy() {
    this.chart.dispose();
  },
};

export default ChartHook;
  1. Add chunkFilename: "[id].[contenthash].js" option to webpack config to allow for cache busting when the chunks change, note that this doesn’t affect the filenames of the entry points like app.js since the hash there is added by mix phx.digest

  2. (Optional) Compress /\.(js|css|svg)$/ via webpack using brotli, because why not (and in part thanks to #3840). This would mostly affect the chunks.

  3. Update Plug.Static options in endpoint.ex to include gzip: true, brotli: true

First 10 of 11 Posts Switch mode

bglusman

bglusman

I have no experience/knowledge here but it sounds like a great idea! I wonder if there’s even a chance LiveView would welcome the changes upstream as a PR/if it would be easier to accomplish cleanly within LiveView itself if you fork it? Maybe open an issue on LiveView to see if they have thoughts/are open to it in a PR, or as a hook/config option to make it easier to do within a Phoenix app if it adds some complexity? And I’m curious what you find, it seems like a good idea, but I’ve never tried it in general so not sure how much complexity/what the tradeoffs are…

idi527

idi527 OP

I think it’s easy enough to do without any extensions from liveview so I made a small example which roughly follows the steps outlined in OP: https://github.com/syfgkjasdkn/lazy-live-view/commits/master.

sfusato

sfusato

I’ve recently come across asset_import. You might find it interesting.

How do you handle .br (brotli) files since mix phx.digest skips digesting those files? I mean, in the end, you need to have something like:

app.js
app-[hash].js - generated by mix phx.digest
app-[hash].js.gz - generated by mix phx.digest
app.js.br - generated by webpack

What’s the easiest way for the br file generated by Webpack to end up with the same hash as the others?

idi527

idi527 OP

What’s the easiest way for the br file generated by Webpack to end up with the same hash as the others?

I use chunkFilename: "[id].[contenthash].js" in webpack. I don’t think I need the hash to be the same as from mix phx.digest since I don’t reference these files in phoenix. Webpack does all the lazy loading.

I’ve recently come across asset_import. You might find it interesting.

Thanks, will check it out. But I think I like the dynamic import approach better.

sfusato

sfusato

How about your entry file? Or you don’t brotli compress that?

idi527

idi527 OP

How about your entry file? Or you don’t brotli compress that?

That’s right, the entry file is only gzipped by mix phx.digest.

sfusato

sfusato

My entry file as well as the app’s css file would benefit from the brotli compression. I ended up writing a mix task that will add the hash to the .br files generated by Webpack.

idi527

idi527 OP

I’ve just checked and app.js and app.css get returned as brotli compressed in chrome and firefox with the above setup.

sfusato

sfusato

In prod or in dev? In dev it should work as is, as Phoenix is not referencing them by their hash name. But in prod, Phoenix will switch to the digested file from cache_manifest.json. In which case, the brotli equivalents will need to have the same filename in order to be used.

Also, my app is behind Nginx and you can configure Nginx to brotli compress on the fly or/and use static already compressed files. If you also use Nginx in front of your app, maybe you’re seeing the files compressed on the fly.

idi527

idi527 OP

In prod. The file with a hash in its name is compressed. No nginx.

cache_manifest.json includes brotli files. I think it might be thanks to Do not digest Brotli compressed files by jayjun · Pull Request #3840 · phoenixframework/phoenix · GitHub

Where Next?

Trending in Questions Top

stjefim
Hello! Suppose you are building workflow (order / task / payment) processing system with the following requirements: Each workflow con...
New
jonnycharles
I’m in search of an Elixir library that offers PDF generation capabilities similar to Ruby’s Prawn. While there have been discussions abo...
New
spammy
I’m looking to build a personal workflow to quickly deploy web applications written in elixir/phoenix, for local consumption (ie not on t...
New
silverdr
Using Phoenix.LiveView.TagEngine as an EEx.Engine is deprecated! To compile HEEx, use Phoenix.LiveView.TagEngine.compile/2 instead. Sta...
New
dli
Before I dive in myself, did anyone successfully sprinkle Hologram into their existing LiveView app? Looking for hints regarding: Addi...
New
bottlenecked
Hi all, I wanted to ask how the community is dealing with post-release steps. Today we have Ecto migrations, which make sure that the db...
New
michallepicki
I am using Oban and occasionally, shortly after a deployment, a handful of jobs can fail because of dependency on other parts of the syst...
New

Other Trending Topics Top

JesseHerrick
Hey, I’m Jesse and I’m the main contributor behind Dexter, a full-featured, lightning-fast Elixir LSP optimized for large codebases. It s...
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 & Solve. They are GUI (Emerge) and State management (S...
New
ausimian
Emily is an Elixir library that runs Nx computations on Apple’s MLX. Install it as the default Nx backend and Nx, defn, Axon, Nx.Serving,...
New
type1fool
I just stumbled on a newly redesigned elixir-lang.org. :tada: It looks like @Software_Mansion did the work, and I think it is generally a...
New
akoutmos
@hugobarauna and I (Alex Koutmos) have been hard at work on writing a book on Nerves that takes you from simply blinking LEDs to building...
New

We're in Beta

About us Mission Statement