UNPKG

@skybolt/server-adapter

Version:

Skybolt server adapter for Node.js/Bun - High-performance asset caching for multi-page applications

281 lines (204 loc) 6.02 kB
# @skybolt/server-adapter Skybolt server adapter for Node.js and Bun. High-performance asset caching for multi-page applications. ## Installation ```bash npm install @skybolt/server-adapter # or pnpm add @skybolt/server-adapter # or bun add @skybolt/server-adapter ``` ## Quick Start ```javascript import { Skybolt } from '@skybolt/server-adapter' // Create instance with render map path and request cookies const skybolt = new Skybolt( './dist/.skybolt/render-map.json', req.cookies // Your framework's cookies object ) // Generate HTML const html = ` <!DOCTYPE html> <html> <head> ${skybolt.css('src/css/main.css')} ${skybolt.launchScript()} </head> <body> <h1>Hello Skybolt!</h1> ${skybolt.script('src/js/app.js')} </body> </html> ` ``` ## How It Works **First visit:** Assets are inlined directly in the HTML. The Skybolt client script caches them in the browser's Cache API and registers a Service Worker. **Repeat visits:** The server outputs standard `<link>` and `<script>` tags. The Service Worker intercepts these requests and serves assets from cache (~5ms response time). **Zero network requests.** **After rebuilds:** Content hashes change, causing a cache miss. Assets are re-inlined and the cache is updated automatically. ## API ### `new Skybolt(renderMapPath, cookies?, cdnUrl?)` Create a new Skybolt instance. - `renderMapPath` (string) - Path to the `render-map.json` file generated by `@skybolt/vite-plugin` - `cookies` (object | null) - Request cookies object from your framework - `cdnUrl` (string | null) - Optional CDN base URL to prefix asset URLs ### `skybolt.css(entry, options?)` Render a CSS asset. ```javascript // Blocking CSS (in <head>) skybolt.css('src/css/main.css') // Non-blocking CSS (async loading) skybolt.css('src/css/main.css', { async: true }) ``` **Options:** - `async` (boolean, default: `false`) - Load CSS asynchronously ### `skybolt.script(entry, options?)` Render a JavaScript asset. ```javascript // ES module (default) skybolt.script('src/js/app.js') // Classic script skybolt.script('src/js/legacy.js', { module: false }) ``` **Options:** - `module` (boolean, default: `true`) - Use `type="module"` for ES modules ### `skybolt.preload(entry, options?)` Render a preload link for early resource fetching. ```javascript skybolt.preload('src/fonts/Inter.woff2', { as: 'font', type: 'font/woff2', crossorigin: 'anonymous' }) ``` **Options:** - `as` (string) - Resource type (`'font'`, `'image'`, `'script'`, `'style'`) - `type` (string) - MIME type - `crossorigin` (string) - Crossorigin attribute - `fetchpriority` (string) - `'high'`, `'low'`, or `'auto'` ### `skybolt.launchScript()` Render the Skybolt client launcher. **Include this once per page.** ```javascript // In <head> or before </body> skybolt.launchScript() ``` ### `skybolt.getAssetUrl(entry)` Get the URL for an asset (for manual use). ```javascript const url = skybolt.getAssetUrl('src/images/hero.webp') // => '/assets/hero-Abc123.webp' ``` ### `skybolt.getAssetHash(entry)` Get the content hash for an asset. ```javascript const hash = skybolt.getAssetHash('src/css/main.css') // => 'Pw3rT8vL' ``` ### `skybolt.isCached(entry)` Check if the client has an asset cached. ```javascript if (skybolt.isCached('src/css/main.css')) { // Client has current version cached } ``` ## Framework Examples ### Express ```javascript import express from 'express' import cookieParser from 'cookie-parser' import { Skybolt } from '@skybolt/server-adapter' const app = express() app.use(cookieParser()) app.use(express.static('dist')) app.get('/', (req, res) => { const skybolt = new Skybolt('./dist/.skybolt/render-map.json', req.cookies) res.send(` <!DOCTYPE html> <html> <head> ${skybolt.css('src/css/main.css')} ${skybolt.launchScript()} </head> <body> <h1>Express + Skybolt</h1> ${skybolt.script('src/js/app.js')} </body> </html> `) }) app.listen(8080) ``` ### Hono (Bun) ```javascript import { Hono } from 'hono' import { getCookie } from 'hono/cookie' import { serveStatic } from 'hono/bun' import { Skybolt } from '@skybolt/server-adapter' const app = new Hono() app.use('/*', serveStatic({ root: './dist' })) app.get('/', (c) => { const cookies = { sb_digest: getCookie(c, 'sb_digest') } const skybolt = new Skybolt('./dist/.skybolt/render-map.json', cookies) return c.html(` <!DOCTYPE html> <html> <head> ${skybolt.css('src/css/main.css')} ${skybolt.launchScript()} </head> <body> <h1>Hono + Skybolt</h1> ${skybolt.script('src/js/app.js')} </body> </html> `) }) export default app ``` ### Fastify ```javascript import Fastify from 'fastify' import fastifyCookie from '@fastify/cookie' import fastifyStatic from '@fastify/static' import { Skybolt } from '@skybolt/server-adapter' const fastify = Fastify() await fastify.register(fastifyCookie) await fastify.register(fastifyStatic, { root: './dist' }) fastify.get('/', (req, reply) => { const skybolt = new Skybolt('./dist/.skybolt/render-map.json', req.cookies) reply.type('text/html').send(` <!DOCTYPE html> <html> <head> ${skybolt.css('src/css/main.css')} ${skybolt.launchScript()} </head> <body> <h1>Fastify + Skybolt</h1> ${skybolt.script('src/js/app.js')} </body> </html> `) }) await fastify.listen({ port: 8080 }) ``` ## CDN Support Prefix asset URLs with a CDN base URL: ```javascript const skybolt = new Skybolt( './dist/.skybolt/render-map.json', req.cookies, 'https://cdn.example.com' ) // URLs become: https://cdn.example.com/assets/main-Abc123.css ``` ## TypeScript Full TypeScript support is included: ```typescript import { Skybolt, type RenderMap, type Asset } from '@skybolt/server-adapter' const skybolt = new Skybolt('./dist/.skybolt/render-map.json', req.cookies) ``` ## Requirements - Node.js 18+ or Bun - Assets built with `@skybolt/vite-plugin` ## License MIT