Angular SSR with Fiber v3
This recipe demonstrates how to put Go Fiber v3 in front of an Angular Server-Side Rendering (SSR) application. The Angular app in web/ was created with ng new web --ssr and trimmed to a single page that tells you where it was rendered.
Architecture
- Static Browser Assets: Built frontend files (
*.js,*.css,favicon.ico, ...) are served directly by Fiber fromweb/dist/web/browserviamiddleware/static. Only paths with a file extension are treated as assets, so every page (including/) reaches SSR. - Page Routes: All other requests are forwarded via
middleware/proxyto the Angular SSR Node.js server (http://127.0.0.1:4000) with a bounded timeout. Its responses, including its own 404 pages, are passed through. - Backend API Endpoints: Fiber handles native Go API routes under
/api/*. - Resilience / Fallback: If the SSR server is offline or answers with a 5xx, Fiber serves Angular's client-side rendering shell
index.csr.htmlinstead, and the page renders in the browser.
Prerequisites
Project Structure
.
├── web/ # Angular workspace (ng new web --ssr)
│ ├── angular.json
│ ├── package.json
│ └── src/
│ ├── app/ # App component and SSR route config
│ ├── main.ts # Browser entry point
│ ├── main.server.ts # SSR entry point
│ └── server.ts # Node.js (Express) SSR server
├── go.mod
├── go.sum
├── main.go # Fiber server & SSR proxy configuration
├── main_test.go
├── Makefile
└── README.md
Running the Application
All commands run in the angular-ssr directory.
1. Build
make build
This installs the npm dependencies, builds the Angular app into web/dist/web (browser/ for the client bundle, server/ for the SSR server) and builds the Go binary.
2. Start the Angular SSR server
node web/dist/web/server/server.mjs
It listens on port 4000 (set PORT to change it). Angular only accepts requests whose Host header is listed in security.allowedHosts in web/angular.json. The Fiber proxy sends the host of SSR_ENDPOINT, so 127.0.0.1 is allowed there; add your host if you point SSR_ENDPOINT elsewhere.
3. Start Fiber
# Optional: custom SSR backend (an empty value serves only the client-side shell) and port
export SSR_ENDPOINT="http://127.0.0.1:4000"
export PORT="3000"
go run .
Open http://localhost:3000. The HTML comes back server-rendered:
curl -s http://localhost:3000/ | grep "Rendered on"
# <p>Rendered on the <strong>server</strong>.</p>
In the browser the page switches to "browser" once Angular has hydrated it. Stop the Node.js server and reload: Fiber falls back to index.csr.html and the page is rendered in the browser only.
- Health check:
http://localhost:3000/api/health - Static assets:
http://localhost:3000/favicon.icoand the hashedmain-*.js/styles-*.cssfiles
Running Tests
The Go tests use a temporary directory as browser bundle and a mock SSR server, so they do not need Node.js:
go test -v ./...