Add hot reload for development

Implement automatic rebuild and browser reload during development:

- File watcher monitors .go files for changes with configurable extensions
- Builder compiles Go source to WASM on file changes
- LiveReload WebSocket server notifies connected browsers to reload
- DevServer combines all components for easy development setup
- HTML injection adds reload script automatically

Usage:
  dev := host.NewDevServer("public", "index.html", ".", "public/app.wasm")
  dev.ListenAndServe(":8080")

Closes #9

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-09 17:03:28 +01:00
parent 9642fd008e
commit 89efc9b41d
9 changed files with 1244 additions and 15 deletions

View File

@@ -36,9 +36,9 @@ myapp/
The server serves files from the specified public directory. Any request path maps directly to files:
- `/` `public/index.html`
- `/app.wasm` `public/app.wasm`
- `/styles.css` `public/styles.css`
- `/` -> `public/index.html`
- `/app.wasm` -> `public/app.wasm`
- `/styles.css` -> `public/styles.css`
**SPA Fallback**: Unknown paths and directories fall back to `index.html`, enabling client-side routing.
@@ -68,28 +68,109 @@ Gzip compression is automatically applied to compressible content types when the
Binary assets (PNG, JPEG, etc.) are served uncompressed since they're already compressed.
## Development vs Production
## Hot Reload (Development)
### Development
The `DevServer` provides automatic rebuild and browser reload during development:
```go
package main
import (
"git.flowmade.one/flowmade-one/iris/host"
)
func main() {
// Create dev server with hot reload
dev := host.NewDevServer(
"public", // Static files directory
"index.html", // Index file
".", // Source directory to watch
"public/app.wasm", // WASM output path
)
// Start watching and serving
dev.ListenAndServe(":8080")
}
```
### How It Works
1. **File Watcher**: Monitors `.go` files in the source directory for changes
2. **Auto Build**: Runs `GOOS=js GOARCH=wasm go build` when changes are detected
3. **Browser Reload**: Injects a WebSocket client into HTML pages that triggers reload on build success
### Directory Structure for Development
```
myapp/
├── main.go # WASM application entry point
├── server/
│ └── main.go # Dev server (code above)
└── public/
├── index.html
├── app.wasm # Generated by dev server
└── wasm_exec.js
```
### Workflow
1. Start the dev server: `go run ./server`
2. Open `http://localhost:8080` in your browser
3. Edit your Go source files
4. Save - the browser automatically reloads with your changes
### Custom Watch Configuration
```go
// Watch additional file types
watcher := host.NewWatcher(
".",
onChangeCallback,
host.WithExtensions(".go", ".html", ".css"),
host.WithInterval(100*time.Millisecond),
)
```
### Manual Components
For advanced use cases, you can use the individual components:
```go
// File watcher
watcher := host.NewWatcher(".", func() {
log.Println("Files changed")
})
watcher.Start()
defer watcher.Stop()
// WASM builder
builder := host.NewBuilder(".", "public/app.wasm")
result := builder.Build()
if result.Success {
log.Println("Build succeeded")
}
// Live reload (WebSocket notifications)
lr := host.NewLiveReload()
http.Handle("/__livereload", lr)
lr.NotifyReload() // Triggers reload in all connected browsers
```
## Production
For production, use the standard `Server` instead of `DevServer`:
```go
func main() {
server := host.New("public", "index.html")
http.ListenAndServe(":8080", server)
log.Fatal(http.ListenAndServe(":8080", server))
}
```
Run with:
```bash
go run server.go
```
### Production
For production, compile the server and run as a binary:
Compile and deploy:
```bash
go build -o server ./server.go
go build -o server ./server
./server
```