Skybolt Ruby
Ruby adapter for Skybolt - High-performance asset caching for multi-page applications.
Installation
Add to your Gemfile:
gem "skybolt"Then run:
bundle installPrerequisites
- Install and configure the Vite plugin:
npm install @skybolt/vite-plugin - Build your project:
npm run build - Ensure
render-map.jsonis generated in your build output
Usage
require "skybolt"
sb = Skybolt::Renderer.new(
"public/dist/.skybolt/render-map.json",
cookies: request.cookies
)<!DOCTYPE html>
<html>
<head>
<%= raw sb.css("src/css/critical.css") %>
<%= raw sb.launch_script %>
<%= raw sb.css("src/css/main.css") %>
</head>
<body>
<h1>Hello Skybolt!</h1>
<%= raw sb.script("src/js/app.js") %>
</body>
</html>API
Skybolt::Renderer.new(render_map_path, cookies: nil, cdn_url: nil)
Create a new Skybolt renderer.
-
render_map_path- Path torender-map.jsongenerated by Vite plugin -
cookies:- Cookie hash (defaults tonil) -
cdn_url:- Optional CDN URL prefix (e.g.,'https://cdn.example.com')
# Basic usage
sb = Skybolt::Renderer.new(
"public/dist/.skybolt/render-map.json",
cookies: request.cookies
)
# With CDN
sb = Skybolt::Renderer.new(
"public/dist/.skybolt/render-map.json",
cookies: request.cookies,
cdn_url: "https://cdn.example.com"
)css(entry, 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 toallon load - Repeat visit: Uses
<link rel="preload">withonload
# 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(entry, is_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", is_module: false)launch_script -> String
Render the Skybolt client launcher. Call once in <head> before other assets.
<head>
<%= raw sb.launch_script %>
</head>asset_url(entry) -> String?
Get the URL for an asset (for manual use cases).
url = sb.asset_url("src/css/main.css")
# "/assets/main-Pw3rT8vL.css"asset_hash(entry) -> String?
Get the content hash for an asset.
hash = sb.asset_hash("src/css/main.css")
# "Pw3rT8vL"preload(entry, as_type:, type: nil, crossorigin: nil, fetchpriority: nil) -> String
Render preload link for critical resources like fonts and images.
# Preload hero image with high priority
sb.preload("images/hero.jpg", as_type: "image", fetchpriority: "high")
# Preload font
sb.preload("fonts/inter.woff2", as_type: "font", type: "font/woff2", crossorigin: "anonymous")
# Preload a Vite-built asset (resolved from render-map)
sb.preload("src/css/main.css", as_type: "style")Parameters:
-
entry- Source file path or direct URL -
as_type:- 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. Configure your web server:
Nginx:
location = /skybolt-sw.js {
alias /path/to/public/dist/skybolt-sw.js;
}Apache (.htaccess):
RewriteRule ^skybolt-sw\.js$ public/dist/skybolt-sw.js [L]Framework Integration
Rails
# app/helpers/skybolt_helper.rb
module SkyboltHelper
def skybolt
@skybolt ||= Skybolt::Renderer.new(
Rails.root.join("public/dist/.skybolt/render-map.json").to_s,
cookies: cookies.to_h
)
end
end<%# app/views/layouts/application.html.erb %>
<!DOCTYPE html>
<html>
<head>
<%= raw skybolt.css("app/assets/stylesheets/critical.css") %>
<%= raw skybolt.launch_script %>
<%= raw skybolt.css("app/assets/stylesheets/application.css") %>
</head>
<body>
<%= yield %>
<%= raw skybolt.script("app/javascript/application.js") %>
</body>
</html>Sinatra
require "sinatra"
require "skybolt"
helpers do
def skybolt
@skybolt ||= Skybolt::Renderer.new(
"public/dist/.skybolt/render-map.json",
cookies: request.cookies
)
end
end
get "/" do
erb :index
end<%# views/index.erb %>
<!DOCTYPE html>
<html>
<head>
<%= raw skybolt.css("src/css/critical.css") %>
<%= raw skybolt.launch_script %>
<%= raw skybolt.css("src/css/main.css") %>
</head>
<body>
<h1>Hello Skybolt!</h1>
<%= raw skybolt.script("src/js/app.js") %>
</body>
</html>Hanami
# app/actions/home/index.rb
module MyApp
module Actions
module Home
class Index < MyApp::Action
def handle(request, response)
sb = Skybolt::Renderer.new(
"public/dist/.skybolt/render-map.json",
cookies: request.cookies
)
response.render(view, sb: sb)
end
end
end
end
endRequirements
- Ruby 3.0+
- Vite with
@skybolt/vite-plugin
License
MIT