Giter Site home page Giter Site logo

hexops / vecty Goto Github PK

View Code? Open in Web Editor NEW
2.8K 80.0 142.0 791 KB

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

License: BSD 3-Clause "New" or "Revised" License

Go 100.00%
gopherjs go frontend vecty responsive dynamic javascript webassembly tinygo react

vecty's Introduction

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.19 5.9M 1.3M 952K
todomvc.wasm go 1.15 2.9M 825K 617K

You can find these examples under the example directory along with a readme on how to go about running a vecty project.

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.

vecty's People

Contributors

bzub avatar damz avatar dave avatar dmitshur avatar fanan avatar gernest avatar ilmanzo avatar kigamittsu avatar marwan-at-work avatar mewmew avatar nathanhack avatar neelance avatar nyiyui avatar pdf avatar slimsag avatar soypat avatar tbruyelle avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

vecty's Issues

vecty.Render into non-body component

Currently Render is restricted to a body component; i.e. Vecty must own the whole page effectively. We should allow rendering directly into an element that we own, e.g. vecty.RenderInto("elem-id") or something.

root works, but not todo example

when i go to localhost:8080, it works, and no errors on the bash shell
when i try the path the todo it fails

gedw99-MacBook-Pro:~ apple$ go get -u github.com/gopherjs/gopherjs github.com/neelance/dom
gedw99-MacBook-Pro:~ apple$ gopherjs serve
serving at http://localhost:8080 and on port 8080 of any available addresses
../../usr/local/go/src/time/zoneinfo.go:286:9: undeclared name: loadLocation

go version go1.5beta3 darwin/amd64

Only one event handler called when multiple are specified

Reported by @glight2000 via Slack:

I found if add more than one event.Event(handler), all event will use the last handler.
like:

        event.MouseEnter(func(e *vecty.Event) {
            print("a")
        }),
        event.MouseLeave(func(e *vecty.Event) {
            print("b")
        }),

the MouseEnter and MouseLeave event all call print("b")

Incorrect Unmounter behavior in certain situations

I believe the current behaviour for Unmounter is incorrect. In the case where two components return the same HTML tag, the previous component will be replaced without Unmount being called.

Only way I can see to produce the correct behaviour here is via reflection. I've implemented this in 3df8654, and I'm now seeing consistent Mount/Unmount behaviour when I'd expect it.

debugging

I am curious about debugging the example.
I am using Delve.

example.go is the main starting point.

func main() {
    attachLocalStorage()

but it immediately jumps to runtime.go, line 506

//go:nosplit
func startpanic() {
    systemstack(startpanic_m)
}

Because this is dependent on the DOM for rendering, does it mean its basically not possible to debug it as golang ?

The reason i am doing this is to see basically see how easy it is to debug and test golang code that is destined to be compiled to JS, before its JS

Improve render errors with more information

Specifically,

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

Would be great if it included some information about which component was at fault, and maybe what illegal variable was returned.

Needs a license

It would be great if you could provide a license so it is clear how it can be used.

Documentation

This should include extensive documentation, including at least:

  • A tutorial / walkthrough.
  • DOM Operations
  • Components
  • Rendering (+rendering nothing)
  • Diffing
  • Safety
  • Sharing code between frontend/backend
  • Communicating with a REST endpoint.
  • FAQ (Why Vecty doesn't support SSR, whether or not it's being used in production).
  • Recommendation about server<->browser data transfer
  • How to test Vecty projects
  • Styling components (if we use non-std-CSS architecture)
  • Live code reloading / asset embedding
  • Redux pattern standard, dispatcher package usage.

Things that commonly trip people up which would also be good to discuss somewhere:

  • An example about DefaultValue for <input>.

browser DOM refs

The TodoMVC example currently does not select the text input when double clicking on an item. This is because we don't have any way to call theInputElement.focus() which in React would look something like:

ReactDOM.findDOMNode(this.refs.theInputElement).focus(); 

Need to figure out the right design for this.

Error when view TagName changes

Consider the modified todomvc example in the replacechild branch of github.com/davelondon/vecty.

go get -u github.com/davelondon/vecty
cd $GOPATH/src/github.com/davelondon/vecty
git checkout replacechild
gopherjs serve
open http://localhost:8080/github.com/davelondon/vecty/examples/todomvc/

The example is a simple TestView that returns an elem.Div or elem.Paragraph. Buttons control the tag that is emitted and a counter. Changing the tag causes a Javascript error:

Uncaught TypeError: Cannot read property 'replaceChild' of null

This can be fixed by this commit in the replacechild-fixed branch. However I think there may be a better way. By the time this reconcile has finished, newChild has already replaced oldChild in the parent element, so oldNode.Get("parentNode") is null. I'm not entirely sure why this is, but stopping this may be better than preventing the replaceChild operation?

live code reloading (asset package based on vfsgen)

I've long considered that running Vecty code as part of a Go webserver is a common use case, as opposed to a purely client-side application (which can be easily ran via gopherjs serve).

I think that an asset loading package which can provide the basics of:

  • Perform live code recompiling (as gopherjs serve does), easily via a nearly one-liner call.
  • Easily package the client-side JS code bundle into your Go server binary for serving in a production environment.
  • Potentially enable packaging other smaller assets into the binary, too.

Would do us a world of wonders. I've prototyped this a while back mostly successfully at https://github.com/slimsag/vecty/tree/master/asset

Inspiration for this idea is drawn by a lot of fine work by @shurcooL around these projects:

The goal is to make starting a Vecty application backed by a Go server a super-simple process without any real involvement or understanding about what is going on behind the scenes (e.g. what vfsgen does, or how gopherjslib does things).

Support for fine-grained internal event handling (element creation, re-creation, removal)

Finding vecty pretty interesting, just working through a PoC to get my head around it, and one thing I'm butting up against is trying to integrate with 3rd-party JavaScript that expects to have access to elements in the DOM. There doesn't currently appear to be any way to know when elements are actually rendered.

We have the Unmount handler, which is great for one direction, but what about support for a Mounted event? Or am I missing something and thinking about this all wrong? I'm sure there are some caveats to doing DOM manipulation outside the framework, as elements may get replaced, etc, but there are times when you really need to get at the rendered element.

Preserve selection range across element replacements

As a follow-on from #47 - we can preserve the cursor position by recording and replacing the selectionStart and selectionEnd properties:

start := e.node.Get("selectionStart").Int()
end := e.node.Get("selectionEnd").Int()
e.node.Set(name, value)
e.node.Call("setSelectionRange", start, end)

This isn't ideal - if text is added to the start of the textbox, the cursor position / selected text changes. Is this is better than moving the cursor to the end of the textbox?

Perhaps we could check to see if the selected text would change?

if name == "value" {
    start := e.node.Get("selectionStart").Int()
    end := e.node.Get("selectionEnd").Int()

    if end != start {
        // we have a selected block. Only preserve the selection
        // if the selected text is unchanged.
        if oldValue.(string)[start:end] != value.(string)[start:end] {
            // if the selected text would change, we should
            // place the cursor without a selection at the
            // position of the start of the selection.
            end = start
        }
    }

    e.node.Set(name, value)
    e.node.Call("setSelectionRange", start, end)

} else {
    e.node.Set(name, value)
}

You can see this in action here. It isn't ideal. The cursor position still moves backwards if it's after inserted text. I fear simple universal solution is impossible.

Perhaps this is a solution to a problem that doesn't exist. If the text in a textbox changes, moving the cursor to the end of the text might not be the end of the world.

However, quite a common use-case I can see is validation where the entry of certain characters is forbidden... preserving the cursor position in that case would be essential...

prop: add more / all properties

We might consider auto-generating the prop package like we do for event and elem so that we get access to all properties.

Server-side rendering

Useful for two reasons:

  1. Needed for quicker page loads (other option is code splitting).
  2. Needed for compatability with web scrapers such as search engines etc.

Reconcile input element causes cursor to move

If a textbox has focus, then the Reconcile method results in the cursor moving to the end of the text. The cursor moves when we set the "value" property, here.

I've worked around the problem in my fork by not updating the value property if the element has focus, but this isn't a universal solution. If the value is updated without input from the user, the textbox won't be updated if it has focus.

This seems to be quite a common problem in the React world. I was wondering if anyone had any good solutions or ideas?

templating

i played around with vecty on the weekend.
Really great feel to it.

I am now thinking about Templating. The Render command for React is great because its so simple.
Does anyone have any thoughts so this ?
Is there gopherjs support for doing templating in the browser ?

Element that renders no markup?

Several times it's I've wanted to return nothing from my view render function. This doesn't seem to be supported currently. Usually I've kludged it by returning an empty DIV, but that's not ideal.

Here's a stab at a vecty.Nil(). I'll continue dog-fooding it and see if there's any problems.

prop: naming inconsistencies

Creating this as an issue and not a PR because I'm not sure we should do anything about it..

We might consider renaming these to match the elem and style naming schemes (of not using short-hand versions or acronyms):

  1. prop.Href -> prop.HypertextReference
  2. prop.Id -> prop.Identity
  3. prop.Src -> prop.Source

The first two are by far much less digestible to me as an end-user.

"Getting started" does not exist (TodoMVC example panics when not running with GopherJS..)

Hi there,

I'm considering using gopherJS and vecty for a small webpage I need to write, my first experience was pretty disappointing:

$ go get github.com/gopherjs/vecty/examples/todomvc
$ todomvc
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x71242]

goroutine 1 [running]:
panic(0xc55e0, 0x15a030)
    /Users/campoy/src/golang.org/x/go/src/runtime/panic.go:496 +0x1a0
github.com/gopherjs/gopherjs/js.(*Object).Get(0x0, 0xe172c, 0xc, 0xe7b40)
    /Users/campoy/src/github.com/gopherjs/gopherjs/js/js.go:32 +0x22
main.attachLocalStorage()
    /Users/campoy/src/github.com/gopherjs/vecty/examples/todomvc/example.go:39 +0x74
main.main()
    /Users/campoy/src/github.com/gopherjs/vecty/examples/todomvc/example.go:17 +0x26

I have really not much of an idea of how to make it work, maybe some instructions on a README.md in the todomvc directory might help?

Francesc

EventListener is limiting

I've noticed when working on a project that EventListener can be limiting in regard to the fact that we don't expose the raw *js.Object event OR similiar functionality.

For example, in one scenario I wanted to call preventDefault on the event object within the event handler, i.e. dependent upon a condition within my event handler. Particularly, if a specific key was pressed I would call preventDefault but if it wasn't a specific key then I would retain the default behavior by not calling preventDefault. Right now, however, it is only possible to call PreventDefault as a blanket-statement for the entire event handler -- not conditionally -- because we don't expose the raw event nor such a method to do it conditionally (it can only be done on the EventHandler object, which the callback has no access to).

panic when DOM is not present

Hi, I wanted to do a quick preview for Vecty but seems like I can't get the markdown demo to run.

➜  markdown git:(master) ✗ gopherjs run markdown.go
gopherjs: Source maps disabled. Use Node.js 4.x with source-map-support module for nice stack traces.
/Users/hemantasapkota/go/src/vecty/examples/markdown/markdown.go.063081130:1475
        throw err;
        ^

TypeError: Cannot set property 'title' of undefined
    at Object.$packages.github.com/gopherjs/vecty.SetTitle (/Users/hemantasapkota/go/src/vecty/examples/markdown/markdown.go.063081130:18621:26)
    at $packages.main.main (/Users/hemantasapkota/go/src/vecty/examples/markdown/markdown.go.063081130:36062:9)
    at $packages.main.$init (/Users/hemantasapkota/go/src/vecty/examples/markdown/markdown.go.063081130:36127:9)
    at $goroutine (/Users/hemantasapkota/go/src/vecty/examples/markdown/markdown.go.063081130:1466:19)
    at $schedule (/Users/hemantasapkota/go/src/vecty/examples/markdown/markdown.go.063081130:1523:5)
    at $go (/Users/hemantasapkota/go/src/vecty/examples/markdown/markdown.go.063081130:1499:3)
    at Object.<anonymous> (/Users/hemantasapkota/go/src/vecty/examples/markdown/markdown.go.063081130:36138:1)
    at Object.<anonymous> (/Users/hemantasapkota/go/src/vecty/examples/markdown/markdown.go.063081130:36141:4)
    at Module._compile (module.js:425:26)
    at Object.Module._extensions..js (module.js:432:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:313:12)
    at Function.Module.runMain (module.js:457:10)
    at startup (node.js:138:18)
    at node.js:974:3
➜

formally standardize on Redux pattern + a dispatcher package

The Redux React pattern is IMO the most logical, sane, and extremely simple to understand pattern for store management in applications. I think we could do very good by standardizing on this pattern -- and likewise on a single dispatcher package in the Vecty root -- instead of asking people to decide and write their own dispatcher.

This means that people get a fuller picture from the beginning, and don't need to research "should I use redux or flux?" etc. and try to figure out how it relates to Vecty first. Instead, we present a unified front by adopting Redux patterns formally in documentation etc.

Note that this doesn't really lock us into one or the other -- it just says "unless you have good reason, stick with the redux pattern we recommend" and as a plus makes all Vecty applications pretty easy to reason about in comparison to React apps.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.