Skip to content

FAQ

Frizzante intentionally uses guards instead of middleware.

Middleware have some limitations.

  • All middleware must be invoked for each request
  • Some middleware may contain path-checking logic while others may not, which introduces ambiguity and more details to remember as a developer
  • Managing middleware execution order across different routes is complex

While guards have some advantages.

  • Efficient - each route has a defined slice of guards and only those guards will execute each time the route is matched
  • Explicit - since each route explicitly defines its guards, you can see exactly which guards execute for any route just by looking at the slice
  • Composable - in order to add a new guard you can just add a guard to the route’s guards slice
  • Easy to order - it’s easy to define the order in which guards execute, you can simply move them around in the route’s guards slice

For more details see the guards page.

If you really want middleware-like behavior, you can easily implement it in your own project.

lib/middlewares/types.go
package middlewares
import "main/lib/core/clients"
type Hook func(client *clients.Client, next func()) // Defines a hook function type which will be used by the middleware.
type Middleware struct { // Defines a structure holding multiple hooks.
Hooks []Hook // Defines the actual hooks slice.
}
lib/middlewares/apply.go
package middlewares
import (
"main/lib/core/clients"
"main/lib/core/routes"
)
func Apply(middleware *Middleware, routes []routes.Route) {
for _, route := range routes { // For each route...
handler := r.Handler // ...saves the route handler for later use.
route.Handler = func(client *clients.Client) { // Assigns a new wrapper route handler.
var quit bool // Creates flag used to interrupt the chain.
for _, hook := range middleware.Hooks { // Iterate over hooks.
quit = true // Prepares to quit.
if hook(client, func() { quit = false }); quit { // Invokes hook and checks if route should quit.
return // Quits.
}
}
handler(client) // Invokes the actual route handler.
}
}
}
main.go
package main
import (
"embed"
"main/lib/core/clients"
"main/lib/core/routes"
"main/lib/core/servers"
"main/lib/core/view/ssr"
"main/lib/middlewares"
"main/lib/routes/fallback"
"main/lib/routes/todos"
"main/lib/routes/welcome"
"os"
)
//go:embed app/dist
var efs embed.FS
var server = servers.New()
var middleware = &middlewares.Middleware{
Hooks: []middleware.Hook{
func(client *clients.Client, next func()) {
// Hook logic goes here.
},
},
}
func main() {
defer servers.Start(server)
defer middlewares.Apply(middleware, server.Routes) // Applies middleware to server routes.
// Remember that deferred functions are executed in reverse,
// so this line will execute before the server starts.
server.Efs = efs // Sets embedded file system.
server.Routes = []routes.Route{
{Pattern: "GET /", Handler: fallback.View},
{Pattern: "GET /welcome", Handler: welcome.View},
{Pattern: "GET /todos", Handler: todos.View},
{Pattern: "GET /check", Handler: todos.Check},
{Pattern: "GET /uncheck", Handler: todos.Uncheck},
{Pattern: "GET /add", Handler: todos.Add},
{Pattern: "GET /remove", Handler: todos.Remove},
}
}

Can I use Frizzante with other frontend frameworks?

Section titled “Can I use Frizzante with other frontend frameworks?”

Yes you can, as long as Vite supports your framework.

All you need to do is configure your app/app.client.ts and app/app.server.ts to render your framework.

You can find a Vue3 example here.