Skip to content

tinywasm is a lightweight toolbox designed to streamline the compilation of Go packages to WebAssembly (WASM) using the TinyGo compiler.

License

Notifications You must be signed in to change notification settings

tinywasm/client

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

tinywasm

Project Badges

Go package for intelligent WebAssembly compilation with automatic file detection and 3-mode compiler system.

Features

  • 3-Mode Compiler System: Large ("L"), Medium ("M"), Small ("S")
  • DevTUI Integration: FieldHandler interface for interactive mode switching
  • Smart file detection via prefixes (frontend/backend separation)
  • Triple compiler support: Go standard (fast dev), TinyGo debug (-opt=1), TinyGo production (-opt=z)
  • VS Code auto-configuration for WASM development
  • Dual Output Architecture: WASM binaries in src/web/public/, watchable JS in src/web/ui/js/

Quick Start

// Basic usage
config := tinywasm.NewConfig() // Pre-configured with defaults
config.SourceDir = "src/cmd/webclient"
config.OutputDir = "src/web/public"
config.WasmExecJsOutputDir = "src/web/ui/js"

tw := tinywasm.New(config)
tw.NewFileEvent("src/cmd/webclient/main.go", ".go", "src/cmd/webclient/main.go", "write")

// DevTUI Integration - 3 Mode System
fmt.Println("Current mode:", tw.Value()) // "L" (coding / large build)

// New API: Change now reports progress via a channel instead of returning (msg, err).
// Create and consume a progress channel before calling Change to avoid blocking.
progress := make(chan string)
go func() {
	for p := range progress {
		fmt.Println("Status:", p)
	}
}()
tw.Change("M", progress) // Switch to medium (debug) mode; messages arrive on the progress channel

// Advanced configuration
config := &tinywasm.Config{
    AppRootDir:          "/path/to/project",
    SourceDir:           "src/cmd/webclient",
    OutputDir:           "src/web/public",
    WasmExecJsOutputDir: "src/web/ui/js",
    MainInputFile:       "main.go",
    OutputName:          "main",
	BuildLargeSizeShortcut:   "L",  // Customizable shortcuts (default: L = Large/fast with go)
	BuildMediumSizeShortcut:    "M",
	BuildSmallSizeShortcut: "S",
    Logger:              logger,
}

DevTUI FieldHandler Interface

WasmClient implements the DevTUI FieldHandler interface for interactive development:

// DevTUI Integration
label := tw.Label()           // "Compiler Mode"
current := tw.Value()         // Current mode shortcut ("L", "M", "S")
canEdit := tw.Editable()      // true
timeout := tw.Timeout()       // 0 (no timeout)

// Interactive mode change with the new Change API
// Change now has signature: Change(newValue string, progress chan<- string)
// All validation messages, warnings (e.g. auto-compilation failed) and success
// messages are sent through the provided channel. The channel is closed when
// the operation completes.
progress := make(chan string)
go func() {
	for p := range progress {
		// Handle progress messages (show in TUI, log, etc.)
		fmt.Println("Progress:", p)
	}
}()
tw.Change("M", progress)
// No return values; read errors and status from the progress channel above.

VS Code Integration

Auto-creates .vscode/settings.json with WASM environment:

{"gopls": {"env": {"GOOS": "js", "GOARCH": "wasm"}}}

API

Core:

  • New(config *Config) *WasmClient
  • NewConfig() *Config - Pre-configured with sensible defaults
  • NewFileEvent(fileName, ext, path, event string) error
  • ShouldCompileToWasm(fileName, path string) bool

DevTUI FieldHandler Interface:

  • Label() string - Returns "Compiler Mode"
  • Value() string - Current mode shortcut ("L", "M", "S")
  • Editable() bool - Returns true (field is editable)
  • Change(newValue string, progress chan<- string) - Switch compiler mode and report progress via the provided channel. Validation errors, auto-compilation warnings and success messages are sent to the channel; the implemention closes the channel when finished.
  • Timeout() time.Duration - Returns 0 (no timeout)

Legacy Compiler Methods (deprecated):

  • TinyGoCompiler() bool - Use Value() instead
  • SetTinyGoCompiler(bool) error - Use Change() instead
  • VerifyTinyGoInstallation() error

Utils:

  • MainInputFileRelativePath() string
  • UnobservedFiles() []string
  • JavascriptForInitializing() (string, error)

Config

type Config struct {
	AppRootDir          string        // application root directory (absolute), defaults to "."
	SourceDir           string        // directory containing Go source (relative) eg: "src/cmd/webclient"
	OutputDir           string        // directory for WASM binary output (relative) eg: "src/web/public"
	WasmExecJsOutputDir string        // directory for watchable JS runtime (relative) eg: "src/web/ui/js"
	MainInputFile       string        // main input file for WASM compilation (default: "main.go")
	OutputName          string        // output name for WASM file (default: "main")
	Logger              func(message ...any) // For logging output to external systems (e.g., TUI, console)

	// NEW: Shortcut configuration (default: "f", "b", "m")
	BuildLargeSizeShortcut    string // "L" (large/fast) compile fast with go
	BuildMediumSizeShortcut     string // "M" (medium/debug) compile with tinygo debug
	BuildSmallSizeShortcut string // "S" (small/minimal) compile with tinygo minimal binary size

	// gobuild integration fields
	Callback           func(error)     // Optional callback for async compilation
	CompilingArguments func() []string // Build arguments for compilation (e.g., ldflags)

	// DisableWasmExecJsOutput prevents automatic creation of wasm_exec.js file
	// Useful when embedding wasm_exec.js content inline (e.g., Cloudflare Pages Advanced Mode)
	DisableWasmExecJsOutput bool
}

// Pre-configured constructor (recommended)
func NewConfig() *Config

Dual Output Architecture

WasmClient produces two types of outputs that serve different purposes in the build pipeline:

1. WASM Binary Output (OutputDir)

  • Location: src/web/public/main.wasm
  • Purpose: Final compiled WebAssembly binary loaded by the browser
  • Consumed by: Browser at runtime
  • Modes: All three compilation modes produce output here

2. Watchable JavaScript Output (WasmExecJsOutputDir)

  • Location: src/web/ui/js/wasm_exec.js
  • Purpose: Mode-specific JavaScript runtime that:
    • Informs external tools about the current compilation mode (Go vs TinyGo)
    • Triggers file watchers to reload the browser when mode changes
    • Gets compiled together with other JavaScript by external asset bundlers
  • Consumed by: File watchers (e.g., devwatch) and asset bundlers (e.g., assetmin)
  • Important: WasmClient's only responsibility is writing the correct wasm_exec.js according to the active mode. External tools handle final bundling.

Why Two Separate Directories?

  1. Separation of Concerns: Runtime assets vs. build-time integration
  2. Build Pipeline Integration: File watchers track wasm_exec.js changes
  3. No Dev/Prod States: All modes use the same directories
  4. Mode Transparency: External tools detect mode changes via wasm_exec.js

Mode Switching

// Example usage with the new channel-based Change API:
progress := make(chan string)
go func() {
	for p := range progress {
		fmt.Println(p)
	}
}()
tw.Change("S", progress) // production mode with TinyGo -opt=z

// Repeat for other modes as needed (always provide and consume a progress channel)
// tw.Change("M", progress)
// tw.Change("L", progress)

Requirements

  • Go 1.20+
  • TinyGo (optional, required for debug/production modes)
  • DevTUI (optional, for interactive development)

Benefits:

  • 🎯 3 optimized modes instead of binary choice
  • 🔧 DevTUI integration for interactive development
  • 📦 Smaller debug builds with TinyGo -opt=1
  • Auto-recompilation on mode switch
  • 🛠️ Better error handling with validation
  • 🏗️ Dual output architecture for better build pipeline integration

About

tinywasm is a lightweight toolbox designed to streamline the compilation of Go packages to WebAssembly (WASM) using the TinyGo compiler.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 2

  •  
  •