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>
86 lines
1.5 KiB
Go
86 lines
1.5 KiB
Go
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
|
|
}
|