Skip to content

Delivering Livewire & Alpine assets together

Caleb Porzio edited this page Nov 28, 2022 · 1 revision

Happy path ideal:

A user installs Livewire, creates a component, includes it in a page, and loads it in the browser.

Internally, Livewire auto-injects it's own JS as well as all the Alpine it needs to run.

Question A: Is Alpine imported? Or it's script tag included.

I think the Alpine code that Livewire needs should be imported into the Livewire bundle.

Question B: Is the version of Alpine locked into the version of Livewire?

Yes, Livewire should depend on a specific Alpine version and ship with it.

Question C: But what if Alpine releases a new version with bugfixes or new features?

Then we would need to update it within Livewire and release a new Livewire version alongside it.

But what if that new version introduces new issues? Then it's a bad version and we should tag a new, fixed, Alpine version and ship that. OR wait a few days to tag a new Livewire version.

Alpine is stable enough that new versions don't get tagged all that often, so this OK.

Question D: What about plugins that Livewire depends on?

Well, we should import them and ship those too.

Question E: What about plugins Livewire DOESN'T depend on?

That would get confusing for developers. If they needed the "intersect" plugin and weren't sure if Livewire includes it out of the box. They would get a devtools warning telling them to include the plugin.

Which is weird and especially if down the road Livewire needs "intersect" and includes it later, then that user would have 2 of the same plugin included and have to change their app.

But if we ship EVERYTHING with Livewire, is the bundle too large? Is there big Alpine code it doesn't need that is just costing users extra bandwidth and slowness?

All the big Alpine stuff (core, navigate, and morph) Livewire would use. The only exception might be "focus" which is 3.5kb. Is it worth it though to NOT include it and create confusion for devs?

Will there be new big plugins that shouldn't be included in Livewire in the future that will create weirdness because they're not included?

This ones tough, but we can just keep the API slim I suppose?

Question F: Should we optimize the JS being delivered?

Like say if a user uses the future hypothetical "" component, should we normally not include the Alpine UI JS, and only include it when it's used?

This would be easy enough, but get difficult when a user doesn't explicitly use "" and instead depends directly on the "x-modal" directive from Alpine UI (or headless Alpine rather)?

Yeah we don't want to get into craziness with regexing for things like that and conditionally including it.

It's hard to say about this one. Currently, headless Alpine is like 11kb or so? the base offering will be like 15kb max? so I don't think it's a huge deal to include them all out of the box.

We "could" make this a separate package when we offer it: like "composer require livewire/ui" and IT would do it's own optimization and such.

But what if someone again, just wanted to use x-dialog itself. They would have to introduce their own package.

Question G: What if a user wants to use Alpine on a non-Livewire page

This one is tough. In that case they can either:

  • A) Manually include Alpine on that page
  • B) Force Livewire assets to load on that page (by using "@livewireScripts" kinda thing)

Problem with "A" is a Livewire component might be conditionally rendered on the page and then that's really confusing for someone...

So does this mean auto-injection is a bad idea? Maybe??? Even so, a user might want to JUST include Alpine on a page using something like "@alpineScripts" you know? And then we would need to provide a separate bundle. Seems like a bad idea...

Proposal

The best way forward is this:

  • import Alpine and all its plugins (including UI) directly into the Livewire bundle
  • auto-inject those assets by default onto pages that include Livewire components (with config to opt-out of this)
  • when Alpine releases a new version, ship a new patch version of Livewire
  • If in the future we decide to ship something that isn't included in the bundle, we will detect it at runtime and console.warn a link to a guide on how to include the Alpine plugin that is necessary.
  • We will also cover the reverse case, if someone depends on something that Livewire doesn't bundle and then later Livewire bundles, we will detect the duplicate inclusion and console.warn to remove the extra Alpine <script>.

Other options:

  • Don't auto-inject anything (less cool, but ok)
  • Force devs to include Alpine themselves (crappy DX, plus Livewire might need to add things to Alpine's core for future versions and this makes that tough)