Skip to content

tanthammar/alpine-lazy-load-assets

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

54 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Alpine.js - lazy load assets

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.

Features

  • Lazily load CSS and JS files on-demand.
  • Prevent redundant loading of the same asset.
  • Saves loaded assets in Alpine global state to avoid reloading them, and to check asset existence.
  • Position scripts in head, body-start or body-end.
  • Optionally dispatch window events when assets have finished loading.

Installation

CDN

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

npm install alpine-lazy-load-assets -D

Script Bundle

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();

Script include

import AlpineLazyLoadAssets from 'alpine-lazy-load-assets'

document.addEventListener('alpine:init', () => {
    window.Alpine.plugin(AlpineLazyLoadAssets)
})

Livewire v3

import { Livewire, Alpine } from '../../vendor/livewire/livewire/dist/livewire.esm';
import AlpineLazyLoadAssets from 'alpine-lazy-load-assets';

Alpine.plugin(AlpineLazyLoadAssets);

Livewire.start();

Usage

x-load-js

  • The x-load-js directive adds a <script> tag to the head or body of your document.
  • The script can be loaded as a module by adding the data-js-as-module="true" attribute.
  • You can also position the script before or after an existing script. You don't have to supply a full path, the script searches for a script tag that contains the given value.
//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

  • The x-load-css directive adds a <link> tag to the <head> of your document.
  • You can add a css link media attribute.
  • Warning: Please note that when the media attribute is added to an element with multiple CSS files, it will be applied to all of them.
  • You can also position the link before or after an existing css link. You don't have to supply a full path, the script searches for a css link that contains the given value.
<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>

Multiple files

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(...)"
>

Window events

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.

  • The event will be dispatched once for each file path
  • Beware that the event may be emitted multiple times. If you have multiple elements that pushes the same asset, on the same page.
<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>

Example handling multiple window events

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);
                    }
                });
            }
        }"
    >

Global state, check if assets are loaded

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>

Filament v3

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
});

Filament v2

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);

Contributing

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.

License

This project is licensed under the MIT License.

About

Alpine directive to lazy load js and css assets

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published