Async Alpine
repository·main·Indexed 42 days ago
https://github.com/accudio/async-alpineA performance-oriented wrapper for Alpine.js version 2.0.3 that enables asynchronous, on-demand loading of components. It supports code splitting and lazy loading through various strategies including eager, event, idle, media, and visible loading to reduce initial bundle sizes.
What's inside Async Alpine
- Async Alpine is a wrapper for the Alpine.js framework designed to enable code splitting and lazy-loading of components. It allows you to split your Alpine.js components into multiple files and load them asynchronously on-demand, which helps reduce initial bundle sizes and improves performance for large sites.
Install Async Alpine via CDN
mainTo use Async Alpine via a CDN, include the Async Alpine script and the Alpine.js script in your HTML. Ensure both use the
deferattribute. Note that Async Alpine should be loaded alongside Alpine.js.<script defer src="https://cdn.jsdelivr.net/npm/async-alpine@2.x.x/dist/async-alpine.script.js"></script> <script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>Install Async Alpine via npm
mainIf you are using a module bundler, you can install Async Alpine using npm:
npm install async-alpineConfigure Playwright for async-alpine
mainThe
playwright.config.jsfile defines the testing environment forasync-alpine. It configures the test directory, parallelization, reporting, and the local web server used to host the application during tests.Key configuration settings include:
testDir: Set to./tests.fullyParallel: Enabled (true) to run tests in parallel.reporter: Set to'html'for HTML-based test reports.use.baseURL: Configured tohttp://localhost:3000.use.trace: Set to'on-first-retry'to capture traces only when a test fails and is retried.webServer: Automatically starts a local server usingnpx http-server . -p 3000at the specifiedurlbefore running tests.
import { defineConfig, devices } from '@playwright/test'; const port = 3000 export default defineConfig({ testDir: './tests', fullyParallel: true, reporter: 'html', use: { baseURL: `http://localhost:${port}`, trace: 'on-first-retry', }, projects: [ { name: 'chromium', use: { ...devices['Desktop Chrome'] }, }, { name: 'firefox', use: { ...devices['Desktop Firefox'] }, }, { name: 'webkit', use: { ...devices['Desktop Safari'] }, }, ], webServer: { command: `npx http-server . -p ${port}`, url: `http://localhost:${port}` }, });Configure Playwright test projects
mainThe Playwright configuration defines multiple browser projects to ensure cross-browser compatibility. The current setup includes:
- chromium: Uses
Desktop Chromedevice emulation. - firefox: Uses
Desktop Firefoxdevice emulation. - webkit: Uses
Desktop Safaridevice emulation.
projects: [ { name: 'chromium', use: { ...devices['Desktop Chrome'] }, }, { name: 'firefox', use: { ...devices['Desktop Firefox'] }, }, { name: 'webkit', use: { ...devices['Desktop Safari'] }, }, ],- chromium: Uses
Await component requirements with awaitRequirements()
mainUse
awaitRequirements(component)to pause the initialization of a component until its specifiedstrategyrequirements are met.Requirements are defined using a JS-like syntax within the component's
strategyproperty. The function parses this expression and resolves the underlying asynchronous strategies. It supports logical operators for complex dependency management:&&(AND): All requirements must resolve successfully (usesPromise.all).||(OR): At least one requirement must resolve successfully (usesPromise.any).|: A legacy alias for&&.
Individual requirements are defined as
methodName(argument)and are resolved using the registered strategies available in the project.import { awaitRequirements } from 'async-alpine'; // Example component structure const component = { strategy: 'someMethod(arg) && (otherMethod() || thirdMethod(val))' }; await awaitRequirements(component);Use the media loading strategy
mainThe
mediastrategy delays component loading until a specific CSS media query condition is met. It useswindow.matchMediaand triggers only once.- The
argumentmust be a media query string (e.g.,'min-width: 768px'). - If no
argumentis provided, it defaults to theeagerbehavior. - If the media query is already satisfied when the strategy is called, it resolves immediately.
// Load when the screen is at least 768px wide media({ argument: 'min-width: 768px' })- The
Use the visible loading strategy
mainThe
visiblestrategy delays component loading until the component's element enters the viewport using theIntersectionObserverAPI.- The
argumentallows you to specify arootMarginstring (e.g.,'100px') to trigger the load before the element actually enters the viewport. - If no
argumentis provided, it defaults to'0px 0px 0px 0px'.
// Load when the element is 200px away from entering the viewport visible({ component, argument: '200px' }) // Load exactly when the element enters the viewport visible({ component })- The
Use the idle loading strategy
mainTheidlestrategy delays component loading until the browser is in an idle state. It useswindow.requestIdleCallbackif available; otherwise, it falls back to asetTimeoutof 200ms.idle()Use the event loading strategy
mainThe
eventstrategy delays component loading until a specific DOM event is dispatched on thewindowobject.- If an
argumentis provided, the strategy listens for that specific custom event name. - If no
argumentis provided, it listens for theasync-alpine:loadevent and checks ifevent.detail.idmatches the component's ID.
// Listen for a custom event event({ component, argument: 'my-custom-event' }) // Listen for the default async-alpine:load event event({ component })- If an
Use the eager loading strategy
mainTheeagerstrategy causes the component to load immediately without waiting for any specific condition or event. It returnstrueinstantly.eager()