jensroland/skybolt

High-performance asset caching for multi-page applications

Installs: 1

Dependents: 0

Suggesters: 0

Security: 0

Stars: 0

Watchers: 0

Forks: 0

Open Issues: 0

pkg:composer/jensroland/skybolt

v3.4.0 2025-12-01 20:12 UTC

This package is auto-updated.

Last update: 2026-01-31 20:31:54 UTC


README

PHP adapter for Skybolt - High-performance asset caching for multi-page applications.

Installation

composer require jensroland/skybolt

Prerequisites

  1. Install and configure the Vite plugin: npm install @skybolt/vite-plugin
  2. Build your project: npm run build
  3. Ensure render-map.json is generated in your build output

Usage

<?php
require_once __DIR__ . '/vendor/autoload.php';

$sb = new Skybolt\Skybolt(__DIR__ . '/dist/.skybolt/render-map.json');
?>
<!DOCTYPE html>
<html>
<head>
    <?= $sb->css('src/css/critical.css') ?> 
    <?= $sb->launchScript() ?> 
    <?= $sb->css('src/css/main.css') ?> 
</head>
<body>
    <h1>Hello Skybolt!</h1>
    <?= $sb->script('src/js/app.js') ?> 
</body>
</html>

API

new Skybolt(string $renderMapPath, ?array $cookies = null, ?string $cdnUrl = null)

Create a new Skybolt instance.

  • $renderMapPath - Path to render-map.json generated by Vite plugin
  • $cookies - Cookie array (defaults to $_COOKIE)
  • $cdnUrl - Optional CDN URL prefix (e.g., 'https://cdn.example.com')
// Basic usage
$sb = new Skybolt\Skybolt(__DIR__ . '/dist/.skybolt/render-map.json');

// With CDN
$sb = new Skybolt\Skybolt(
    __DIR__ . '/dist/.skybolt/render-map.json',
    cdnUrl: 'https://cdn.example.com'
);

css(string $entry, bool $async = false): string

Render CSS asset.

  • First visit: Inlines CSS with caching attributes
  • Repeat visit: Outputs <link> tag (Service Worker serves from cache)

When $async is true, CSS loads non-blocking:

  • First visit: Uses media="print" trick, swaps to all on load
  • Repeat visit: Uses <link rel="preload"> with onload
// Blocking (default) - for critical CSS
<?= $sb->css('src/css/critical.css') ?>

// Non-blocking - for non-critical CSS
<?= $sb->css('src/css/main.css', async: true) ?>

script(string $entry, bool $module = true): string

Render JavaScript asset.

  • First visit: Inlines JS with caching attributes
  • Repeat visit: Outputs <script> tag (Service Worker serves from cache)
// ES module (default)
<?= $sb->script('src/js/app.js') ?>

// Classic script
<?= $sb->script('src/js/legacy.js', module: false) ?>

launchScript(): string

Render the Skybolt client launcher. Call once in <head> before other assets.

<head>
    <?= $sb->launchScript() ?>
</head>

getAssetUrl(string $entry): ?string

Get the URL for an asset (for manual use cases).

$url = $sb->getAssetUrl('src/css/main.css');
// "/assets/main-Pw3rT8vL.css"

getAssetHash(string $entry): ?string

Get the content hash for an asset.

$hash = $sb->getAssetHash('src/css/main.css');
// "Pw3rT8vL"

preload(string $entry, string $as, ...): string

Render preload link for critical resources like fonts and images.

// Preload hero image with high priority
<?= $sb->preload('images/hero.jpg', as: 'image', fetchpriority: 'high') ?>

// Preload font
<?= $sb->preload('fonts/inter.woff2', as: 'font', type: 'font/woff2', crossorigin: 'anonymous') ?>

// Preload a Vite-built asset (resolved from render-map)
<?= $sb->preload('src/css/main.css', as: 'style') ?>

Parameters:

  • $entry - Source file path or direct URL
  • $as - Resource type ('image', 'font', 'style', 'script', 'fetch')
  • $type - MIME type (e.g., 'font/woff2', 'image/webp')
  • $crossorigin - Crossorigin attribute ('anonymous', 'use-credentials')
  • $fetchpriority - Fetch priority ('high', 'low', 'auto')

Service Worker Setup

The Service Worker must be served from your domain root. Options:

Option 1: Direct file (recommended)

Copy dist/skybolt-sw.js to your public directory, or configure your web server:

Apache (.htaccess):

RewriteRule ^skybolt-sw\.js$ dist/skybolt-sw.js [L]

Nginx:

location = /skybolt-sw.js {
    alias /path/to/dist/skybolt-sw.js;
}

Option 2: PHP endpoint

<?php
// public/skybolt-sw.js (use .htaccess to route .js to PHP, or name it .php)
header('Content-Type: application/javascript');
header('Service-Worker-Allowed: /');
header('Cache-Control: public, max-age=86400');
readfile(__DIR__ . '/../dist/skybolt-sw.js');

Framework Integration

Laravel

// app/Providers/AppServiceProvider.php
public function register(): void
{
    $this->app->singleton(\Skybolt\Skybolt::class, function () {
        return new \Skybolt\Skybolt(public_path('dist/.skybolt/render-map.json'));
    });
}

// app/Providers/AppServiceProvider.php (boot method)
Blade::directive('skyboltCss', function ($entry) {
    return "<?php echo app(\Skybolt\Skybolt::class)->css({$entry}); ?>";
});

Blade::directive('skyboltScript', function ($entry) {
    return "<?php echo app(\Skybolt\Skybolt::class)->script({$entry}); ?>";
});

Blade::directive('skyboltLaunch', function () {
    return "<?php echo app(\Skybolt\Skybolt::class)->launchScript(); ?>";
});
{{-- resources/views/layout.blade.php --}}
<head>
    @skyboltCss('src/css/critical.css')
    @skyboltLaunch
    @skyboltCss('src/css/main.css')
</head>

Symfony

// src/Twig/SkyboltExtension.php
class SkyboltExtension extends AbstractExtension
{
    public function __construct(private Skybolt $skybolt) {}

    public function getFunctions(): array
    {
        return [
            new TwigFunction('skybolt_css', [$this->skybolt, 'css'], ['is_safe' => ['html']]),
            new TwigFunction('skybolt_script', [$this->skybolt, 'script'], ['is_safe' => ['html']]),
            new TwigFunction('skybolt_launch', [$this->skybolt, 'launchScript'], ['is_safe' => ['html']]),
        ];
    }
}
{# templates/base.html.twig #}
<head>
    {{ skybolt_css('src/css/critical.css') }}
    {{ skybolt_launch() }}
    {{ skybolt_css('src/css/main.css') }}
</head>

Requirements

  • PHP 8.1+
  • Vite with @skybolt/vite-plugin

License

MIT