Vecty lets you build responsive and dynamic web frontends in Go using WebAssembly, competing with modern web frameworks like React & VueJS.

Vecty lets you build responsive and dynamic web frontends in Go using WebAssembly, competing with modern web frameworks like React & VueJS.

Build Status PkgGoDev GoDoc codecov

Benefits

  • Go developers can be competitive frontend developers.
  • Share Go code between your frontend & backend.
  • Reusability by sharing components via Go packages so that others can simply import them.

Goals

  • Simple
    • Designed from the ground up to be easily mastered by newcomers (like Go).
  • Performant
    • Efficient & understandable performance, small bundle sizes, same performance as raw JS/HTML/CSS.
  • Composable
    • Nest components to form your entire user interface, seperating them logically as you would any normal Go package.
  • Designed for Go (implicit)
    • Written from the ground up asking the question "What is the best way to solve this problem in Go?", not simply asking "How do we translate $POPULAR_LIBRARY to Go?"

Features

  • Compiles to WebAssembly (via standard Go compiler).
  • Small bundle sizes: 0.5 MB hello world (see section below).
  • Fast expectation-based browser DOM diffing ('virtual DOM', but less resource usage).

Vecty vs. Vugu

If you're wondering if you should use Vecty or Vugu, consider reading this Twitter thread for advice from both myself and the creator of Vugu.

Current Status

Vecty is currently considered to be an experimental work-in-progress. Prior to widespread production use, we must meet our v1.0.0 milestone goals, which are being completed slowly and steadily as contributors have time (Vecty is over 4 years in the making!).

Early adopters may make use of it for real applications today as long as they are understanding and accepting of the fact that:

  • APIs will change (maybe extensively).
  • A number of important things are not ready:
    • Extensive documentation, examples and tutorials
    • URL-based component routing
    • Ready-to-use component libraries (e.g. material UI)
    • Server-side rendering
    • And more, see milestone: v1.0.0
  • The scope of Vecty is only ~80% defined currently.
  • There are a number of important open issues.

For a list of projects currently using Vecty, see the doc/projects-using-vecty.md file.

Near-zero dependencies

Vecty has nearly zero dependencies, it only relies on reflect from the Go stdlib. Through this, it is able to produce the smallest bundle sizes for Go frontend applications out there, limited only by the Go compiler itself:

Example binary Compiler uncompressed gzip --best brotli
hellovecty.wasm tinygo 0.14.0 252K 97K 81K
hellovecty.wasm go 1.15 2.1M 587K 443K
markdown.wasm go 1.15 3.6M 1010K 745K
todomvc.wasm go 1.15 2.9M 825K 617K

Note: Bundle sizes above do not scale linearly with more code/dependencies in your Vecty project. hellovecty is the smallest base-line bundle that the compiler can produce with just Vecty as a dependency, other examples above pull in more of the Go standard library and you would not e.g. have to pay that total cost again.

Community

Changelog

See the doc/CHANGELOG.md file.

Owner
Hexops
Experiment everywhere
Hexops
Comments
  • Keyed children

    Keyed children

    Initial pass at keyed children. This one was pretty tough due to having to handle keys and insertions for nested List children.

    Working through this did show up some bugs in the existing implementation of List handling, primarily: the *HTML nil type coercion from #138 was not applying to List children, so I've moved that into *HTML.reconcileChildren(), as I need to handle Lists there anyway.

    Fixes #25

  • Stable Children

    Stable Children

    This PR aims to provide stable element children, to enable persistent Components.

    This is not final code, as I'm not really happy with some of this, however I believe it is at least correctly functional unless I've missed something, and I'd like to start getting some feedback. I think we absolutely need to do something about testing here though - this got rather complicated.

    Supercedes #132

  • Design: Determine how to manage component lifecycle

    Design: Determine how to manage component lifecycle

    In the course of #114, issues with current methods for instantiating child components were identified that will result in hard to reason about behaviour for users.

    This issue is to track design discussions on methods to alleviate these issues.

    My preference is to remove the need for the Restorer interface entirely by somehow retaining a reference to a child component between parent renders, though I'm not sure exactly what this looks like at this stage.

  • Always call Render() in the persistent component

    Always call Render() in the persistent component

    (My understanding of the code base is limited, my apologies in advance if this is way off-base.)

    I understand that Vecty aims at supporting a concept of "persistent" component, in which the initial instance of a component is re-used at each rendering... and it does seem like a desirable property for non-trivial applications.

    Unfortunately, it seems to fail pretty quickly. Consider this simple example:

    • The rendering is currently done in the new component, so the event handlers are bound to the new component, and mutate the new component
    • But when the body is re-rendered, it reuses the persistent component, overriding the state that was mutated by the event handler

    This MR changes the render logic to always call the Render() method in the persistent component.

  • Think about how ComponentOrHTML and MarkupOrChild could be made into concrete types

    Think about how ComponentOrHTML and MarkupOrChild could be made into concrete types

    Today these two types are interface{} and easy to mix up. For example of this, see the Slack discussion starting here.

    It'd be good if we could make these types more concrete.

  • Change Component.Render() signature to return ComponentOrHTML

    Change Component.Render() signature to return ComponentOrHTML

    This allows nesting of Components, allowing the creation of wrapper components that implement lifcycle events, but do not directly render HTML.

    BREAKING: This change breaks all existing Component implementations due to change of method signature.

    Fixes #148

  • component architecture changes

    component architecture changes

    Over the past months I've been looking into the component architecture, and in particular, how to document it and explain it to others efficiently. I've tried probably 7+ different approaches at this point, and this is the one that I've settled into / feel the most comfortable with.

    Start by reading the commit message of f91790a to get an idea for motivation, and please compare the todomvc example after that change to the todomvc example before that change.

    I would be very curious to get the opinions of @shurcooL and @neelance here, although I understand this is a more controversial change and probably much less likely to be accepted. I'm okay with that and with this change taking longer to review, potentially not being merged, etc.

  • Is removing strconv feasible?

    Is removing strconv feasible?

    Per https://github.com/gopherjs/gopherjs/wiki/JavaScript-Tips-and-Gotchas the fmt package adds significant size to the transpiled code. Current uses in Vecty appear pretty trivial, and can likely be replaced by https://github.com/cathalgarvey/fmtless or possibly alternative calls and string concat.

  • [tracking PR] Render new

    [tracking PR] Render new

    @pdf I've rebased your branch here (prior PR https://github.com/gopherjs/vecty/pull/107), while I try to decipher the rest of your changes.

    I've dropped the prior commit for namespaced elements, in favor of the now-merged https://github.com/gopherjs/vecty/pull/110

    I've squashed a number of commits into Refactor rendering for reliability and performance. since they were not individual changes really.

    My plan:

    1. Adapt the Unmount change against master.
    2. Make the Mount addition against master.
    3. Try adapting the keyer (logic, anyway) against master.

    Things I have doubts about:

    • I am unsure about the Keyer implementation, but need to look further into it. I don't know why it needs to be a Component method instead of just Markup.
    • I'm not convinced that splitting up Restorer into two separate Updater methods is a good idea.
    • I think providing an implicit reflection-based Clone would be a mistake, currently.
    • I have many other concerns in general, but the change is prohibitively large for me to be able to effectively communicate them currently
  • proposal: Consider moving Vecty under its own GitHub organization

    proposal: Consider moving Vecty under its own GitHub organization

    Currently, Vecty lives under the GopherJS organization. This made sense for multiple reasons at the time, which I will go into further here. However, I believe it may be time for Vecty to move under its own organization and live at https://github.com/vecty/vecty

    Vecty: A brief history

    Vecty originally started out as me looking into how a React-like framework could be done in Go, with an interesting twist: I didn't know React (and I still consider myself to not know React). This, I think, gave me an interesting perspective on how to achieve the same goals as React without making it feel like React stuffed into Go, but rather a Go developer's take on how component-based webapps could be written.

    This idea got shared with @dmitshur, who then shared it with @neelance (author of GopherJS) and as it turned out he was also experimenting with the idea of React-in-GopherJS. After meeting up in person in SF, we came to chat about this significantly and he proved to me various flaws and incorrect assumptions that my (documentation-heavy) implementation at the time would have in comparison to his (undocumented) implementation. So after some discussion it made sense: Add documentation and use his implementation, and use the Vecty project name.

    Much experimentation and many significant changes later, and Vecty is ironically not like either of the starting implementations. We're still missing documentation and the actual implementation uses many different core concepts (mainly to remove boilerplate code that was hand-written or auto-generated in @neelance's initial implementation).

    In Go 1.11, @neelance added WebAssembly support to Go and support for it in Vecty has always been planned.

    Today, the Go WebAssembly community is flourishing more and more, with even alternative Go implementations like @aykevl's tinygo popping up (which aims to produce ultra small binaries, making it an even more viable target for producing web applications).

    It makes sense today that Vecty will support three primary compiler targets:

    • GopherJS (as it always has)
    • Go's native WebAssembly support
    • TinyGo

    All of these implementations have various tradeoffs between binary sizes, browser compatibility, standard library support, etc. and Vecty can and should support all of them soon.

    Should we move to a separate organization?

    I think yes, with the main reasons being:

    1. Vecty living under the GopherJS organization implicitly communicates that it is for GopherJS
      • GopherJS is likely to go into a sunsetting state soon, with more and more developers switching over to Go's native WebAssembly support. This may make it look like the "old" technology to newcomers (even if it isn't). Go 2 will be coming eventually and I anticipate there will not be enough developer time spent on GopherJS in the long run to support Go 2 (I would be happy to be wrong about this, however).
    2. Vecty already requires a location to host other related repositories: https://github.com/vecty and putting those in the GopherJS namespace would obviously not make sense (we would pollute it).
    3. My hope is that Vecty can one day be the defacto method of doing web UX's in Go in the long term, and that the Vecty github organization could act as a location for maintaining a set of curated Vecty packages similar to how golang.org/x/ contains curated Go packages.

    Notes

    • None of this indicates my belief around GopherJS being an awesome project has changed. On the contrary, I think GopherJS was just the start of something big. :)
  • Add support for WebAssembly

    Add support for WebAssembly

    This is a fully working implementation of WebAssembly support in Vecty.

    The really nice thing here is that a given code base can be compiled to JavaScript or to WebAssembly with barely any change (the only thing absolutely necessary is to add a select {} at the end of main for the WebAssembly version).

    But there are a number of obvious problems for discussion:

    • This replaces github.com/gopherjs/gopherjs/js with github.com/gopherjs/gopherwasm/js, and as a consequence introduces a large BC break;
    • The new-style javascript interface (syscall/js and github.com/gopherjs/gopherwasm/js) does not have a way to call a Callback synchronously, which the test suite hacks around by sleeping for 10ms (runtime.Gosched() is not enough);
    • github.com/gopherjs/gopherwasm/js doesn't have the minimum support for native (i.e. non-gopherjs and non-wasm) builds, so the test suite fails under go test (but it passes under both GOOS=js GOARCH=wasm go test and under gopherjs test).
  • Add support for adding external scripts to document.

    Add support for adding external scripts to document.

    This PR adds support for adding external scripts to the document.

    Not sure if the way that I implemented 'attributes' to the AddScript function is the most convenient. Let me know what solution could fit better.

    Created tests for AddScript function

  • prop.Value(

    prop.Value("") does not produce the correct html on first render

    These do not produce the correct html on first render. They should add value="" to the select options element but they don't initially do it.

    prop.Value("") vecty.Property("value", "")

    I am using this as a workaround. vecty.Attribute("value", "")

    The problem this causes is that when the select item is used in a form and is specified as required, the form validation does not work unless the first option has value=""

    You can see the impact here in the "try it yourself" page https://www.w3schools.com/tags/att_select_required.asp

    This is what should be produced

    <form>
      <select id="Select option" required="">
          <option value="" selected="true">Select option</option>
          <option value="1">Test 1</option>
          <option value="2">Test 2</option>
          <option value="3">Test 3</option>
          <option value="4">Test etc...</option>
      </select>
    </form>
    

    This is what is initially produced

    <form>
      <select id="Select option" required="">
          <option selected="true">Select option</option>
          <option value="1">Test 1</option>
          <option value="2">Test 2</option>
          <option value="3">Test 3</option>
          <option value="4">Test etc...</option>
      </select>
    </form>
    

    This is an example of the code I am using to produce the html

    
    type ItemView struct { //ItemView
    	vecty.Core
    
    	Index    int               `vecty:"prop"`
    	ID       int64             `vecty:"prop"`
    	Item     *ItemStruct       `vecty:"prop"`
    	Selected bool              `vecty:"prop"`
    	Disabled bool              `vecty:"prop"`
    }
    
    
    func (p *ItemView) Render() vecty.ComponentOrHTML {
      if p.Item == nil {
          return elem.Option(
    	      vecty.Markup(
    		      //prop.Value(""), //doesn't work
    		      //vecty.Property("value", ""), //doesn't work
    		      vecty.Attribute("value", ""), //work-around for the above
    		      vecty.MarkupIf(p.Selected, vecty.Attribute("selected", true)),
    		      prop.Disabled(p.Disabled),
    	      ),
    	      vecty.Text("Select option"),
          )
      } else {
          return elem.Option(
    	      vecty.Markup(
    		      prop.Value(strconv.FormatInt(p.ID, 10)),
    		      vecty.MarkupIf(p.Selected, vecty.Attribute("selected", true)),
    		      prop.Disabled(p.Disabled),
    	      ),
    	      //vecty.Text(text),
    	      vecty.Text(p.Item.Name+" ("+p.Item.Description+")"),
          )
      }
    }
    
    type ListView struct {
    	vecty.Core
    
    	Label            string                 `vecty:"prop"`
    	ValueID          *int64                 `vecty:"prop"`
    	Required         bool                   `vecty:"prop"`
    }
    
    func (p *ListView) Render() vecty.ComponentOrHTML {
      var items vecty.List
      items = append(items, &ItemView{Index: -1, ID: 0, Selected: (*p.ValueID == 0), Disabled: false})
    
      for i, item := range MyItems {
        items = append(items, &ItemView{Index: i, ID: item.ID, Item: item, Selected: (*p.ValueID == item.ID), Disabled: false})
      }
      
      return elem.Div(
          elem.Label(
    	      vecty.Markup(
    		      prop.For(p.Label),
    	      ),
    	      vecty.Text(p.Label),
          ),
          elem.Select(
    	      vecty.Markup(
    		      prop.ID(p.Label),
    		      event.Change(p.onChange),
    		      vecty.MarkupIf(p.Required,
    			      vecty.Property("required", true),
    		      ),
    	      ),
    	      items,
          ),
      )
    }
    
  • Return type of If function

    Return type of If function

    Is it possible to change the return type of func If(cond bool, children ...ComponentOrHTML) MarkupOrChild to List?

    This is my use case:

    type CustomComponent struct {
     	vecty.Core
    	Content vecty.List `vecty:"prop"`
    }
    
    func NewCustomComponent(content ...vecty.ComponentOrHTML) *CustomComponent {
    	return &CustomComponent {Content: content}
    }
    
    func (ch *CustomComponent) Render() vecty.ComponentOrHTML {
    	return elem.Div(
                ch.Content
            )
    }
    
    ---
    
    type View struct {
     	vecty.Core
            Flag bool
    }
    
    func (ch *View) Render() vecty.ComponentOrHTML {
    	return NewCustomComponent(
                    vecty.If(ch.Flag, elem.Div())      // will not compile
            )
    }
    
  • Instrumenting panic messages

    Instrumenting panic messages

    I often get panic messages with vecty and it is quite frustrating to debug since the whole stack is on vecty's side. It would be very nice if instead of

    panic: vecty: next child render must not equal previous child render (did the child Render illegally return a stored render variable?)
    

    We could get rich data on which node failed. I believe this could be done via reflect. I'll start asking around to see how other packages do this rich data printing, meanwhile I can add that these errors are strong deterrents to newcomers who have no idea what they mean.

  • question: What is this prop vs. state idea

    question: What is this prop vs. state idea

    I've noticed component structs sometimes have fields with vecty:"prop" tag. I've also come across the issue https://github.com/hexops/vecty/issues/209 and the generics issue https://github.com/hexops/vecty/issues/277.

    What is this separation?Why is it necessary? I've built vecty apps without it just fine.

A package to build progressive web apps with Go programming language and WebAssembly.
A package to build progressive web apps with Go programming language and WebAssembly.

Go-app is a package for building progressive web apps (PWA) with the Go programming language (Golang) and WebAssembly (Wasm). Shaping a UI is done by

Jan 2, 2023
Vugu: A modern UI library for Go+WebAssembly (experimental)

Vugu: A modern UI library for Go+WebAssembly (experimental)

Jan 3, 2023
Dom - A Go API for different Web APIs for WebAssembly target

Go DOM binding (and more) for WebAssembly This library provides a Go API for dif

Jan 7, 2023
Golang-WASM provides a simple idiomatic, and comprehensive API and bindings for working with WebAssembly for Go and JavaScript developers
Golang-WASM provides a simple idiomatic, and comprehensive API and bindings for working with WebAssembly for Go and JavaScript developers

A bridge and bindings for JS DOM API with Go WebAssembly. Written by Team Ortix - Hamza Ali and Chan Wen Xu. GOOS=js GOARCH=wasm go get -u github.com/

Dec 22, 2022
Go compiler for small places. Microcontrollers, WebAssembly, and command-line tools. Based on LLVM.

TinyGo - Go compiler for small places TinyGo is a Go compiler intended for use in small places such as microcontrollers, WebAssembly (Wasm), and comma

Dec 30, 2022
WebAssembly interop between Go and JS values.

vert Package vert provides WebAssembly interop between Go and JS values. Install GOOS=js GOARCH=wasm go get github.com/norunners/vert Examples Hello W

Dec 28, 2022
WebAssembly for Proxies (Golang host implementation)

WebAssembly for Proxies (GoLang host implementation) The GoLang implementation for proxy-wasm, enabling developer to run proxy-wasm extensions in Go.

Dec 29, 2022
🐹🕸️ WebAssembly runtime for Go
🐹🕸️ WebAssembly runtime for Go

Wasmer Go Website • Docs • Slack Channel A complete and mature WebAssembly runtime for Go based on Wasmer. Features Easy to use: The wasmer API mimics

Jan 2, 2023
🐹🕸️ WebAssembly runtime for Go
🐹🕸️ WebAssembly runtime for Go

Wasmer Go Website • Docs • Slack Channel A complete and mature WebAssembly runtime for Go based on Wasmer. Features Easy to use: The wasmer API mimics

Dec 29, 2022
WebAssembly runtime for wasmer-go
WebAssembly runtime for wasmer-go

gowasmer When compiling Go to WebAssembly, the Go compiler assumes the WebAssembly is going to run in a JavaScript environment. Hence a wasm_exec.js f

Dec 28, 2022
A template project to demonstrate how to run WebAssembly functions as sidecar microservices in dapr
A template project to demonstrate how to run WebAssembly functions as sidecar microservices in dapr

Live Demo 1. Introduction DAPR is a portable, event-driven runtime that makes it easy for any developer to build resilient, stateless and stateful app

Jan 3, 2023
Tiny, blazing fast WebAssembly compute

Sat, the tiny WebAssembly compute module Sat (as in satellite) is an experiment, and isn't ready for production use. Please try it out and give feedba

Jan 5, 2023
WebAssembly Lightweight Javascript Framework in Go (AngularJS Inspired)

Tango Lightweight WASM HTML / Javascript Framework Intro WebAssembly is nice, Go on the web is nice, so I ported Tangu to Go and WebAssembly. Tangu is

Dec 20, 2022
Running a Command line tool written in Go on browser with WebAssembly

Running a command line tool written in Go on browser with WebAssembly This repo contains code/assets from the article Files: . ├── article.md

Dec 30, 2022
This library provides WebAssembly capability for goja Javascript engine

This module provides WebAssembly functions into goja javascript engine.

Jan 10, 2022
A Brainfuck to WebAssembly compiler written in Go.

brainfuck2wasm A Brainfuck to WebAssembly compiler written in Go. I am writing this compiler for a Medium article. When I complete the compiler, I'll

Jun 6, 2022
wazero: the zero dependency WebAssembly runtime for Go developers

wazero: the zero dependency WebAssembly runtime for Go developers WebAssembly is a way to safely run code compiled in other languages. Runtimes execut

Jan 2, 2023
⚙️ Concept of Golang HTML render engine with frontend components and dynamic behavior
⚙️ Concept of Golang HTML render engine with frontend components and dynamic behavior

An HTML render engine concept that brings frontend-like components experience to the server side with native html/template on steroids. Supports any s

Nov 25, 2022
Aes for go and java; build go fo wasm and use wasm parse java response.

aes_go_wasm_java aes for go and java; build go fo wasm and use wasm parse java response. vscode setting config settings.json { "go.toolsEnvVars":

Dec 14, 2021