Compiled temapltes.

Benchmark cleanup
This commit is contained in:
2026-01-22 11:10:47 +05:30
parent 714db30a8c
commit 654b45ee10
31 changed files with 2168 additions and 1251 deletions

50
examples/demo/build.zig Normal file
View File

@@ -0,0 +1,50 @@
const std = @import("std");
pub fn build(b: *std.Build) void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
// Get dependencies
const pugz_dep = b.dependency("pugz", .{
.target = target,
.optimize = optimize,
});
const httpz_dep = b.dependency("httpz", .{
.target = target,
.optimize = optimize,
});
// Compile templates at build time using pugz's build_templates
// Generates views/generated.zig with all templates
const build_templates = @import("pugz").build_templates;
const compiled_templates = build_templates.compileTemplates(b, .{
.source_dir = "views",
});
// Main executable
const exe = b.addExecutable(.{
.name = "demo",
.root_module = b.createModule(.{
.root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = optimize,
.imports = &.{
.{ .name = "pugz", .module = pugz_dep.module("pugz") },
.{ .name = "httpz", .module = httpz_dep.module("httpz") },
.{ .name = "tpls", .module = compiled_templates },
},
}),
});
b.installArtifact(exe);
const run_cmd = b.addRunArtifact(exe);
run_cmd.step.dependOn(b.getInstallStep());
if (b.args) |args| {
run_cmd.addArgs(args);
}
const run_step = b.step("run", "Run the demo server");
run_step.dependOn(&run_cmd.step);
}

View File

@@ -0,0 +1,21 @@
.{
.name = .demo,
.version = "0.0.1",
.fingerprint = 0xd642dfa01393173d,
.minimum_zig_version = "0.15.2",
.dependencies = .{
.pugz = .{
.path = "../..",
},
.httpz = .{
.url = "git+https://github.com/karlseguin/http.zig?ref=master#9ef2ffe8d611ff2e1081e5cf39cb4632c145c5b9",
.hash = "httpz-0.0.0-PNVzrIowBwAFr_kqBN1W4KBMC2Ofutasj2ZfNAIcfTzF",
},
},
.paths = .{
"build.zig",
"build.zig.zon",
"src",
"views",
},
}

156
examples/demo/src/main.zig Normal file
View File

@@ -0,0 +1,156 @@
//! Pugz Demo - Interpreted vs Compiled Templates
//!
//! This demo shows two approaches:
//! 1. **Interpreted** (ViewEngine) - supports extends/blocks, parsed at runtime
//! 2. **Compiled** (build-time) - 3x faster, templates compiled to Zig code
//!
//! Routes:
//! GET / - Compiled home page (fast)
//! GET /users - Compiled users list (fast)
//! GET /interpreted - Interpreted with inheritance (flexible)
//! GET /page-a - Interpreted page A
const std = @import("std");
const httpz = @import("httpz");
const pugz = @import("pugz");
// Compiled templates - generated at build time from views/compiled/*.pug
const tpls = @import("tpls");
const Allocator = std.mem.Allocator;
/// Application state shared across all requests
const App = struct {
allocator: Allocator,
view: pugz.ViewEngine,
pub fn init(allocator: Allocator) App {
return .{
.allocator = allocator,
.view = pugz.ViewEngine.init(.{
.views_dir = "views",
}),
};
}
};
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer if (gpa.deinit() == .leak) @panic("leak");
const allocator = gpa.allocator();
var app = App.init(allocator);
const port = 8080;
var server = try httpz.Server(*App).init(allocator, .{ .port = port }, &app);
defer server.deinit();
var router = try server.router(.{});
// Compiled template routes (fast - 3x faster than Pug.js)
router.get("/", indexCompiled, .{});
router.get("/users", usersCompiled, .{});
// Interpreted template routes (flexible - supports extends/blocks)
router.get("/interpreted", indexInterpreted, .{});
router.get("/page-a", pageA, .{});
std.debug.print(
\\
\\Pugz Demo - Interpreted vs Compiled Templates
\\=============================================
\\Server running at http://localhost:{d}
\\
\\Compiled routes (3x faster than Pug.js):
\\ GET / - Home page (compiled)
\\ GET /users - Users list (compiled)
\\
\\Interpreted routes (supports extends/blocks):
\\ GET /interpreted - Home with ViewEngine
\\ GET /page-a - Page with inheritance
\\
\\Press Ctrl+C to stop.
\\
, .{port});
try server.listen();
}
// ─────────────────────────────────────────────────────────────────────────────
// Compiled template handlers (fast - no parsing at runtime)
// ─────────────────────────────────────────────────────────────────────────────
/// GET / - Compiled home page
fn indexCompiled(_: *App, _: *httpz.Request, res: *httpz.Response) !void {
const html = tpls.home(res.arena, .{
.title = "Welcome - Compiled",
.authenticated = true,
}) catch |err| {
res.status = 500;
res.body = @errorName(err);
return;
};
res.content_type = .HTML;
res.body = html;
}
/// GET /users - Compiled users list
fn usersCompiled(_: *App, _: *httpz.Request, res: *httpz.Response) !void {
const User = struct {
name: []const u8,
email: []const u8,
};
const html = tpls.users(res.arena, .{
.title = "Users - Compiled",
.users = &[_]User{
.{ .name = "Alice", .email = "alice@example.com" },
.{ .name = "Bob", .email = "bob@example.com" },
.{ .name = "Charlie", .email = "charlie@example.com" },
},
}) catch |err| {
res.status = 500;
res.body = @errorName(err);
return;
};
res.content_type = .HTML;
res.body = html;
}
// ─────────────────────────────────────────────────────────────────────────────
// Interpreted template handlers (flexible - supports inheritance)
// ─────────────────────────────────────────────────────────────────────────────
/// GET /interpreted - Uses ViewEngine (parsed at runtime)
fn indexInterpreted(app: *App, _: *httpz.Request, res: *httpz.Response) !void {
const html = app.view.render(res.arena, "index", .{
.title = "Home - Interpreted",
.authenticated = true,
}) catch |err| {
res.status = 500;
res.body = @errorName(err);
return;
};
res.content_type = .HTML;
res.body = html;
}
/// GET /page-a - Demonstrates extends and block override
fn pageA(app: *App, _: *httpz.Request, res: *httpz.Response) !void {
const html = app.view.render(res.arena, "page-a", .{
.title = "Page A - Pets",
.items = &[_][]const u8{ "A", "B", "C" },
.n = 0,
}) catch |err| {
res.status = 500;
res.body = @errorName(err);
return;
};
res.content_type = .HTML;
res.body = html;
}

View File

@@ -0,0 +1,15 @@
doctype html
html
head
title #{title}
link(rel="stylesheet" href="/style.css")
body
header
h1 #{title}
if authenticated
span.user Welcome back!
main
p This page is rendered using a compiled template.
p Compiled templates are 3x faster than Pug.js!
footer
p © 2024 Pugz Demo

View File

@@ -0,0 +1,15 @@
doctype html
html
head
title hello
body
p some thing
| ballah
| ballah
+btn("click me ", "secondary")
br
a(href='//google.com' target="_blank") Google 1
br
a(class='button' href='//google.com' target="_blank") Google 2
br
a(class='button', href='//google.com' target="_blank") Google 3

View File

@@ -0,0 +1,7 @@
html
head
block head
script(src='/vendor/jquery.js')
script(src='/vendor/caustic.js')
body
block content

View File

@@ -0,0 +1,10 @@
html
head
title My Site - #{title}
block scripts
script(src='/jquery.js')
body
block content
block foot
#footer
p some footer content

View File

@@ -0,0 +1,5 @@
mixin btn(text, type="primary")
button(class="btn btn-" + type)= text
mixin btn-link(href, text)
a.btn.btn-link(href=href)= text

View File

@@ -0,0 +1,11 @@
mixin card(title)
.card
.card-header
h3= title
.card-body
block
mixin card-simple(title, body)
.card
h3= title
p= body

View File

@@ -0,0 +1,15 @@
extends layout.pug
block scripts
script(src='/jquery.js')
script(src='/pets.js')
block content
h1= title
p Welcome to the pets page!
ul
li Cat
li Dog
ul
each val in items
li= val

View File

@@ -0,0 +1,5 @@
extends layout
append head
script(src='/vendor/three.js')
script(src='/game.js')

View File

@@ -0,0 +1,11 @@
extends layout-2.pug
block append head
script(src='/vendor/three.js')
script(src='/game.js')
block content
p
| cheks manually the head section
br
| hello there

View File

@@ -0,0 +1,9 @@
extends sub-layout.pug
block content
.sidebar
block sidebar
p nothing
.primary
block primary
p nothing

View File

@@ -0,0 +1 @@
p= petName

View File

@@ -0,0 +1,9 @@
extends layout.pug
block content
.sidebar
block sidebar
p nothing
.primary
block primary
p nothing

View File

@@ -0,0 +1,11 @@
doctype html
html
head
title Users
body
h1 User List
ul.user-list
each user in users
li.user
strong= user.name
span.email= user.email