Add hot reload for development
All checks were successful
CI / build (pull_request) Successful in 32s
All checks were successful
CI / build (pull_request) Successful in 32s
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:
85
host/builder.go
Normal file
85
host/builder.go
Normal file
@@ -0,0 +1,85 @@
|
||||
package host
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// Builder compiles Go source to WASM.
|
||||
type Builder struct {
|
||||
sourceDir string
|
||||
outputPath string
|
||||
|
||||
mu sync.Mutex
|
||||
building bool
|
||||
}
|
||||
|
||||
// BuildResult contains the result of a build operation.
|
||||
type BuildResult struct {
|
||||
Success bool
|
||||
Output string
|
||||
Error error
|
||||
}
|
||||
|
||||
// NewBuilder creates a new WASM builder.
|
||||
// sourceDir is the directory containing Go source files.
|
||||
// outputPath is the target WASM file path.
|
||||
func NewBuilder(sourceDir, outputPath string) *Builder {
|
||||
return &Builder{
|
||||
sourceDir: sourceDir,
|
||||
outputPath: outputPath,
|
||||
}
|
||||
}
|
||||
|
||||
// Build compiles the Go source to WASM.
|
||||
func (b *Builder) Build() BuildResult {
|
||||
b.mu.Lock()
|
||||
if b.building {
|
||||
b.mu.Unlock()
|
||||
return BuildResult{
|
||||
Success: false,
|
||||
Output: "Build already in progress",
|
||||
Error: fmt.Errorf("build already in progress"),
|
||||
}
|
||||
}
|
||||
b.building = true
|
||||
b.mu.Unlock()
|
||||
|
||||
defer func() {
|
||||
b.mu.Lock()
|
||||
b.building = false
|
||||
b.mu.Unlock()
|
||||
}()
|
||||
|
||||
cmd := exec.Command("go", "build", "-o", b.outputPath, b.sourceDir)
|
||||
cmd.Env = append(cmd.Environ(), "GOOS=js", "GOARCH=wasm")
|
||||
|
||||
var stdout, stderr bytes.Buffer
|
||||
cmd.Stdout = &stdout
|
||||
cmd.Stderr = &stderr
|
||||
|
||||
err := cmd.Run()
|
||||
output := stdout.String() + stderr.String()
|
||||
|
||||
if err != nil {
|
||||
return BuildResult{
|
||||
Success: false,
|
||||
Output: output,
|
||||
Error: err,
|
||||
}
|
||||
}
|
||||
|
||||
return BuildResult{
|
||||
Success: true,
|
||||
Output: output,
|
||||
}
|
||||
}
|
||||
|
||||
// IsBuilding returns true if a build is currently in progress.
|
||||
func (b *Builder) IsBuilding() bool {
|
||||
b.mu.Lock()
|
||||
defer b.mu.Unlock()
|
||||
return b.building
|
||||
}
|
||||
Reference in New Issue
Block a user