Alpine directive to lazy load js and css assets
APACHE-2.0 License
This package provides directives for lazy loading JavaScript and CSS assets in Alpine.js projects.
Note: This package is specifically designed for lazy loading css/js assets but does not handle lazy loading of Alpine components. You should use Async Alpine for that. However, it is the perfect companion to use alongside Async Alpine to lazy load all the assets required by your Alpine.js components.
Laravel Filament users, see end of page.
<script
src="https://unpkg.com/alpine-lazy-load-assets@latest/dist/alpine-lazy-load-assets.cdn.js"
defer
></script>
npm install alpine-lazy-load-assets -D
To add the x-load-css
and x-load-js
directives to your project, register the plugin with Alpine.js.
import Alpine from 'alpinejs';
import AlpineLazyLoadAssets from 'alpine-lazy-load-assets';
Alpine.plugin(AlpineLazyLoadAssets);
window.Alpine = Alpine;
window.Alpine.start();
import AlpineLazyLoadAssets from 'alpine-lazy-load-assets'
document.addEventListener('alpine:init', () => {
window.Alpine.plugin(AlpineLazyLoadAssets)
})
import { Livewire, Alpine } from '../../vendor/livewire/livewire/dist/livewire.esm';
import AlpineLazyLoadAssets from 'alpine-lazy-load-assets';
Alpine.plugin(AlpineLazyLoadAssets);
Livewire.start();
x-load-js
directive adds a <script>
tag to the head
or body
of your document.data-js-as-module="true"
attribute.//appended to <head>
<div x-load-js="['/path/to/your/js/file.js']"></div>
//prepended to <body>
<div x-load-js.body-start="['/path/to/your/js/file.js']"></div>
//appended to <body>
<div x-load-js.body-end="['/path/to/your/js/file.js']"></div>
//load as module
<div data-js-as-module="true" x-load-js="['/path/to/your/js/file.js']"></div>
//position before an existing script.
<div data-js-before="app.js" x-load-js="['/path/to/your/js/file.js']"></div>
//position after an existing script.
<div data-js-after="app.js" x-load-js="['/path/to/your/js/file.js']"></div>
x-load-css
directive adds a <link>
tag to the <head>
of your document.media
attribute.<div x-load-css="['/path/to/your/css/file.css']"></div>
//or with media attribute
<div media="print" x-load-css="['/path/to/your/css/print-file.css']"></div>
//position before an existing css link.
<div data-css-before="app.css" x-load-css="['/path/to/your/css/file.css']"></div>
//position after an existing css link.
<div data-css-after="app.css" x-load-css="['/path/to/your/css/file.css']"></div>
Both directives support an array of files, allowing you to load multiple assets simultaneously.
Example from a Laravel project in combination with Async Alpine:
<div
x-load-js="[
'https://cdn.jsdelivr.net/npm/flatpickr/dist/l10n/{{ $locale }}.js'
]"
x-load-css="[
'{{ asset('bundles/AlpineFlatPicker/AlpineFlatPicker.css') }}',
'https://cdn.jsdelivr.net/npm/flatpickr/dist/themes/{{ $theme }}.css'
]"
x-ignore
ax-load="visible"
ax-load-src="{{ asset('bundles/AlpineFlatPicker/AlpineFlatPicker.js') }}"
x-data="AlpineFlatPicker(...)"
>
Define a data-dispatch
attribute with an event name, to the same element as the css or js directives to dispatch a window event when the asset has finished loading.
The script will append -css
or -js
to the event name, depending on which directive is used.
<div
data-dispatch="foo-loaded"
x-load-js="['/path/to/your/js/foo.js']"
x-load-css="['/path/to/your/css/foo.css']"
></div>
//listen for the event, observe the -css or -js suffix
<div x-on:foo-loaded-css.window="alert('the CSS file was loaded')"></div>
<div x-on:foo-loaded-js.window="alert('the JS file was loaded')"></div>
In a Laravel blade file
<div data-js-before="app.js"
x-load-js="['{{ asset('js/jsoneditor.js') }}']"
data-dispatch="jsoneditor-loaded"
x-on:jsoneditor-loaded-js.window="start"
x-data="{
editor: null,
destroy() {
this.editor = null;
},
start() {
$nextTick(() => {
if(!this.editor && typeof JSONEditor !== 'undefined') {
const options = {}
this.editor = new JSONEditor($refs.editor, options);
}
});
}
}"
>
The loaded assets are saved in lazyLoadedAssets
global state, allowing you to check
if an asset has already been loaded.
//in any Alpine component
$store.lazyLoadedAssets.check('path/foo.js'); //returns boolean
//you can check multiple files at once
$store.lazyLoadedAssets.check(['path/foo.js', 'path/bar.css']);
Example from a Laravel blade file
<div x-on:loaded-map-css.window="console.info($store.lazyLoadedAssets.check('{{ asset('css/foo.css') }}'))"></div>
This package is included from Filament v3.0.0-alpha102. (No need to do anything).
If you are on an earlier version or for other reasons need to add this manually ...
Add the following code to any service provider register()
method.
$this->app->resolving(AssetManager::class, function () {
FilamentAsset::register([
Js::make('alpine-lazy-load-assets', 'https://unpkg.com/alpine-lazy-load-assets@latest/dist/alpine-lazy-load-assets.cdn.js'),
], 'app'); //change 'app' to a unique key suitable for your project
});
Add the following code to any service providers boot()
method.
Filament::registerScripts([
'https://unpkg.com/alpine-lazy-load-assets@latest/dist/alpine-lazy-load-assets.cdn.js',
], true);
Contributions are welcome! If you find a bug, have an enhancement idea, or want to contribute in any other way, please open an issue or submit a pull request.
This project is licensed under the MIT License.