Plugins
Plugins extend the rfw toolchain. They can add work before, during, or after a build, and they can also extend runtime behavior inside the app.
Lifecycle Hooks
A plugin may implement any combination of lifecycle methods. The CLI discovers hooks by name and invokes them automatically:
func (p *Plugin) PreBuild(cfg json.RawMessage) error { /* optional */ }
func (p *Plugin) Build(cfg json.RawMessage) error { /* optional */ }
func (p *Plugin) PostBuild(cfg json.RawMessage) error { /* optional */ }
func (p *Plugin) Install(a *core.App) { /* optional */ }
func (p *Plugin) Uninstall(a *core.App) { /* optional */ }
Plugins that participate in builds also implement Name, ShouldRebuild, and Priority so the CLI can register and order them.
PreBuild
Runs before compilation. Use it to prepare inputs or fetch resources. Example: download a schema or generate code consumed later in the build.
Build
Runs while producing the Wasm bundle. Often compiles assets, copies files, or emits artifacts.
PostBuild
Fires after the bundle is ready. Useful for minification, hash verification, or cleaning up temporary files.
Install
Called at app startup. Use it to register routes, add components, or inject scripts—this extends runtime behavior.
Uninstall
Runs when the app shuts down or the plugin is removed. Use it to detach watchers or undo Install changes.
Priority and Ordering
Plugins can control execution order with Priority() int. Lower numbers run first.
type first struct{}
func (p *first) Priority() int { return 0 }
type second struct{}
func (p *second) Priority() int { return 10 }
plugins.Register(&second{})
plugins.Register(&first{})
// "first" runs before "second" despite registration order.
Writing a Plugin
A minimal plugin defines a type, implements hooks, and registers itself:
package analytics
import (
"encoding/json"
"github.com/rfwlab/rfw/v2/core"
)
type Plugin struct{}
func New() *Plugin { return &Plugin{} }
func (p *Plugin) Name() string { return "analytics" }
func (p *Plugin) Priority() int { return 0 }
func (p *Plugin) ShouldRebuild(path string) bool { return false }
func (p *Plugin) PreBuild(cfg json.RawMessage) error { return nil }
func (p *Plugin) Build(cfg json.RawMessage) error { return nil }
func (p *Plugin) PostBuild(cfg json.RawMessage) error { return nil }
func (p *Plugin) Install(a *core.App) {}
func (p *Plugin) Uninstall(a *core.App) {}
Register in main.go:
func main() {
core.RegisterPlugin(analytics.New())
}
Official Plugins
rfw ships with several plugins. Example: the i18n plugin for translations:
import "github.com/rfwlab/rfw/v2/plugins/i18n"
core.RegisterPlugin(i18n.New(map[string]map[string]string{
"en": {"hello": "Hello"},
"it": {"hello": "Ciao"},
}))
Use Cases
Plugins are ideal for:
- Analytics integration
- Asset processing
- Internationalization
- Feature flags
By choosing hooks carefully, a plugin can focus on build-time, runtime, or both.
@include:ExampleFrame:{code:“/examples/plugins/plugins_component.go”, uri:“/examples/plugins”}