使用WebAssembly和围棋编写前端的Web框架

简介:

目录

 ●  介绍
 ●  初始点
 ●  功能注册
 ●  组件
 ●  构建路由器
 ●  一个完整的例子
 ●  挑战前进
 ●  结论

JavaScript前端框架毫无疑问有助于突破以前在浏览器环境中可能实现的界限。更复杂的应用程序已经建立在React,Angular和VueJS之类的基础之上,仅举几例,并且有一个众所周知的笑话,关于新的前端框架似乎每天都会出现。

然而,这种发展速度对全世界的开发者来说都是一个非常好的消息。通过每个新框架,我们可以发现处理状态的更好方法,或者使用shadow DOM等方式有效地渲染。

然而,最新的趋势似乎是在用JavaScript以外的语言编写这些框架并将它们编译成WebAssembly。我们开始看到由于Lin Clark之类的人对JavaScript和WebAssembly进行通信的方式有了重大改进,我们无疑会看到更多重大改进,因为WebAssembly开始在我们的生活中变得更加突出。

介绍

所以,在本教程中,我认为构建一个用Go编写的非常简单的前端框架的基础是一个好主意,它编译成WebAssembly。这至少包括以下功能:

 ●  功能注册
 ●  组件
 ●  超简单路由

我现在警告你,虽然这些将非常简单,并且无法准备好生产。如果这篇文章有点受欢迎,那么我希望能够将它推向前进,并尝试构建满足半正式前端框架要求的东西。

Github: 这个项目的完整源代码可以在这里找到:elliotforbes / oak。如果您喜欢为项目做出贡献,请随意,我很乐意接受任何拉动请求!

初始点

好的,让我们深入选择我们的编辑器并开始编码!我们要做的第一件事就是创建一个非常简单的东西 index.html ,作为我们前端框架的入口点:


1<!doctype html>
2<!--
3Copyright 2018 The Go Authors. All rights reserved.
4Use of this source code is governed by a BSD-style
5license that can be found in the LICENSE file.
6-->
7<html>
8
9<head>
10 <meta charset="utf-8">
11 <title>Go wasm</title>
12 <script src="./static/wasm_exec.js"></script>
13 <script src="./static/entrypoint.js"></script>
14</head>
15<body>
16
17 <div class="container">
18 <h2>Oak WebAssembly Framework</h2>
19 </div>
20</body>
21
22</html>

您会注意到这些js 文件在顶部导入了2个 文件,这使我们可以执行完成的WebAssembly二进制文件。第一个是大约414行,所以,为了保持本教程的可读性,我建议你从这里下载它:https://github.com/elliotforbes/oak/blob/master/examples/blog/static/ wasm_exec.js

第二个是我们的 entrypoint.js 档案。这将获取并运行 lib.wasm 我们即将构建的内容。


1// static/entrypoint.js
2const go = new Go();
3WebAssembly.instantiateStreaming(fetch("lib.wasm"), go.importObject).then((result) => {
4 go.run(result.instance);
5});

最后,既然我们已经解决了这个问题,我们就可以开始深入了解一些Go代码!创建一个新文件 main.go ,其中包含Oak Web Framework的入口点!


1// main.go
2package main
3
4func main() {
5 println("Oak Framework Initialized")
6}

这很简单。我们创建了一个非常简单的Go程序,只需Oak Framework Initialized 打开我们的Web应用程序即可打印出来 要验证一切正常,我们需要使用以下命令编译它:

1$ GOOS=js GOARCH=wasm go build -o lib.wasm main.go

这应该构建我们的Go代码并输出我们在 lib.wasm 文件中引用的 entrypoint.js 文件。

真棒,如果一切正常,那么我们准备在浏览器中试用它!我们可以使用这样一个非常简单的文件服务器:


1// server.go
2package main
3
4import (
5 "flag"
6 "log"
7 "net/http"
8)
9
10var (
11 listen = flag.String("listen", ":8080", "listen address")
12 dir = flag.String("dir", ".", "directory to serve")
13)
14
15func main() {
16 flag.Parse()
17 log.Printf("listening on %q...", *listen)
18 log.Fatal(http.ListenAndServe(*listen, http.FileServer(http.Dir(*dir))))
19}

然后,您可以通过键入满足您的应用程序 go run server.go ,你应该能够从访问你的应用程序 http://localhost:8080

功能注册

好吧,所以我们有一个相当基本的打印声明工作,但在宏观方案中,我不认为它只是作为Web框架的资格。

让我们来看看如何在Go中构建函数并注册这些函数,以便我们可以在我们的函数中调用它们 index.html我们将创建一个新的实用程序函数,它将同时包含 string 我们函数的名称以及它将映射到的Go函数。

将以下内容添加到现有 main.go 文件中:


1// main.go
2import "syscall/js"
3
4// RegisterFunction
5func RegisterFunction(funcName string, myfunc func(i []js.Value)) {
6 js.Global().Set(funcName, js.NewCallback(myfunc))
7}

所以,这就是事情开始变得有用的地方。我们的框架现在允许我们注册函数,以便框架的用户可以开始创建自己的功能。

使用我们框架的其他项目可以开始注册自己的函数,这些函数随后可以在他们自己的前端应用程序中使用。

组件

所以,我想接下来我们需要考虑添加到我们的框架中的是组件的概念。基本上,我希望能够components/ 在项目中定义一个 使用它的目录,并且在该目录中我希望能够构建一个home.go具有我的主页所需的所有代码的 组件。

那么,我们该怎么做呢?

好吧,React倾向于提供具有render() 函数的类,这些 函数返回HTML / JSX /您希望为所述组件呈现的任何代码。让我们窃取它并在我们自己的组件中使用它。

我本质上希望能够在使用此框架的项目中执行此类操作:


1package components
2
3type HomeComponent struct{}
4
5var Home HomeComponent
6
7func (h HomeComponent) Render() string {
8 return "<h2>Home Component</h2>"
9}

因此,在我的 components 包中,我定义了 HomeComponent 一个Render() 返回HTML 的 方法。

为了向我们的框架添加组件,我们将保持简单,并且只需定义 interface 我们随后定义的任何组件必须遵守的组件。components/comopnent.go 在我们的Oak框架中创建一个新文件 


1// components/component.go
2package component
3
4type Component interface {
5 Render() string
6}

如果我们想要为各种组件添加新功能会发生什么?好吧,这让我们可以做到这一点。我们可以oak.RegisterFunction 在init组件功能中使用 调用 来注册我们想要在组件中使用的任何函数!


1package components
2
3import (
4 "syscall/js"
5
6 "github.com/elliotforbes/oak"
7)
8
9type AboutComponent struct{}
10
11var About AboutComponent
12
13func init() {
14 oak.RegisterFunction("coolFunc", CoolFunc)
15}
16
17func CoolFunc(i []js.Value) {
18 println("does stuff")
19}
20
21func (a AboutComponent) Render() string {
22 return `<div>
23 <h2>About Component Actually Works</h2>
24 <button onClick="coolFunc();">Cool Func</button>
25 </div>`
26}

当我们将它与路由器结合起来时,我们应该能够看到我们 HTML 被渲染到我们的页面,我们应该能够点击那个调用的按钮, coolFunc() 它将does stuff 在我们的浏览器控制台中打印出来 

太棒了,让我们看看我们现在如何构建一个简单的路由器。

构建路由器

好的,我们已经components 在我们的Web框架中得到了概念 我们差不多完成了吗?

不完全是,我们可能需要的下一件事是在不同组件之间导航的方法。大多数框架似乎都 <div> 具有特定的特性 id ,它们会绑定并呈现其中的所有组件,因此我们将在Oak中窃取相同的策略。

让我们router/router.go 在我们的橡木框架中创建一个 文件,以便我们可以开始破解。

在这个中,我们想要将string 路径映射 到组件,我们不会进行任何URL检查,我们现在只需将所有内容保存在内存中以保持简单:


1// router/router.go
2package router
3
4import (
5 "syscall/js"
6
7 "github.com/elliotforbes/oak/component"
8)
9
10type Router struct {
11 Routes map[string]component.Component
12}
13
14var router Router
15
16func init() {
17 router.Routes = make(map[string]component.Component)
18}

因此,在此范围内,我们创建了一个新 Router 结构,其中包含 Routes 了我们在上一节中定义的组件的字符串映射。

路由不是我们框架中的强制性概念,我们希望用户在他们希望初始化新路由器时进行选择。因此,让我们创建一个新函数,它将注册一个 Link 函数,并将我们映射中的第一个路径绑定到我们的 <div id="view"/> html标记:


1// router/router.go
2// ...
3func NewRouter() {
4 js.Global().Set("Link", js.NewCallback(Link))
5 js.Global().Get("document").Call("getElementById", "view").Set("innerHTML", "")
6}
7
8func RegisterRoute(path string, component component.Component) {
9 router.Routes[path] = component
10}
11
12func Link(i []js.Value) {
13 println("Link Hit")
14
15 comp := router.Routes[i[0].String()]
16 html := comp.Render()
17
18 js.Global().Get("document").Call("getElementById", "view").Set("innerHTML", html)
19}

您应该注意到,我们已经创建了一个 RegisterRoute 函数,允许我们将a注册 path 到给定的组件。

我们的 Link 功能也非常酷,因为它允许我们在项目中的各个组件之间导航。我们可以指定非常简单的 <button>元素,以允许我们导航到已注册的路径,如下所示:

1<button onClick="Link('link')">Clicking this will render our mapped Link component</button>

很棒,所以我们现在有一个非常简单的路由器,如果我们想在一个简单的应用程序中使用它,我们可以这样做:


1// my-project/main.go
2package main
3
4import (
5 "github.com/elliotforbes/oak"
6 "github.com/elliotforbes/oak/examples/blog/components"
7 "github.com/elliotforbes/oak/router"
8)
9
10func main() {
11 // Starts the Oak framework
12 oak.Start()
13
14 // Starts our Router
15 router.NewRouter()
16 router.RegisterRoute("home", components.Home)
17 router.RegisterRoute("about", components.About)
18
19 // keeps our app running
20 done := make(chan struct{}, 0)
21 <-done
22}

一个完整的例子

将所有这些放在一起,我们可以开始构建具有组件和路由功能的非常简单的Web应用程序。如果你想看一些关于它是如何工作的例子,那么看一下官方回购中的例子:elliotforbes / oak / examples

挑战前进

这个框架中的代码绝不是生产准备好的,但是我希望这篇文章能够开始讨论如何在Go中开始构建更多生产就绪的框架。

如果不出意外,它开始了识别仍需要做什么的旅程,以使其成为React / Angular / VueJS之类的可行替代方案,所有这些都是大规模加速开发人员生产力的现象框架。

我希望这篇文章能激励你们中的一些人开始研究如何在这个非常简单的起点上进行改进。


原文发布时间为:2018-11-9

本文来自云栖社区合作伙伴“Golang语言社区”,了解相关信息可以关注“Golang语言社区”。

相关文章
|
15天前
|
编解码 前端开发 JavaScript
构建高效响应式Web界面:现代前端框架的比较
【4月更文挑战第9天】在移动设备和多样屏幕尺寸盛行的时代,构建能够适应不同视口的响应式Web界面变得至关重要。本文深入探讨了几种流行的前端框架——Bootstrap、Foundation和Tailwind CSS,分析它们在创建响应式设计中的优势与局限。通过对比这些框架的栅格系统、组件库和定制化能力,开发者可以更好地理解如何选择合适的工具来优化前端开发流程,并最终实现高性能、跨平台兼容的用户界面。
|
16天前
|
前端开发 JavaScript 关系型数据库
从前端到后端:构建现代化Web应用的技术探索
在当今互联网时代,Web应用的开发已成为了各行各业不可或缺的一部分。从前端到后端,这篇文章将带你深入探索如何构建现代化的Web应用。我们将介绍多种技术,包括前端开发、后端开发以及各种编程语言(如Java、Python、C、PHP、Go)和数据库,帮助你了解如何利用这些技术构建出高效、安全和可扩展的Web应用。
|
17天前
|
编解码 前端开发 JavaScript
Web 前端开发中的最佳实践
本文将介绍 Web 前端开发中的最佳实践,包括代码组织、性能优化、响应式设计和用户体验等方面。通过遵循这些实践,开发人员可以提高开发效率,优化用户体验,并减少潜在的问题和错误。
|
16天前
|
安全 数据库 C++
Python Web框架比较:Django vs Flask vs Pyramid
【4月更文挑战第9天】本文对比了Python三大Web框架Django、Flask和Pyramid。Django功能全面,适合快速开发,但学习曲线较陡;Flask轻量灵活,易于入门,但默认配置简单,需自行添加功能;Pyramid兼顾灵活性和可扩展性,适合不同规模项目,但社区及资源相对较少。选择框架应考虑项目需求和开发者偏好。
|
1天前
|
开发框架 前端开发 数据库
Python从入门到精通:3.3.2 深入学习Python库和框架:Web开发框架的探索与实践
Python从入门到精通:3.3.2 深入学习Python库和框架:Web开发框架的探索与实践
|
10天前
|
前端开发 搜索推荐 数据安全/隐私保护
HTML标签详解 HTML5+CSS3+移动web 前端开发入门笔记(四)
HTML标签详解 HTML5+CSS3+移动web 前端开发入门笔记(四)
18 1
|
10天前
|
前端开发 数据挖掘 API
使用Python中的Flask框架进行Web应用开发
【4月更文挑战第15天】在Python的Web开发领域,Flask是一个备受欢迎的轻量级Web框架。它简洁、灵活且易于扩展,使得开发者能够快速地构建出高质量的Web应用。本文将深入探讨Flask框架的核心特性、使用方法以及在实际开发中的应用。
|
10天前
|
前端开发 JavaScript vr&ar
前端新技术探索:WebAssembly、Web Components与WebVR/AR
【4月更文挑战第12天】WebAssembly、Web Components和WebVR/AR正重塑Web应用的未来。WebAssembly允许C/C++等语言在Web上高效运行,提供接近原生的性能,如游戏引擎。Web Components通过Custom Elements和Shadow DOM实现可复用的自定义UI组件,提升模块化开发。WebVR/AR(现WebXR)则让VR/AR体验无需额外应用,直接在浏览器中实现。掌握这些技术对前端开发者至关重要。
16 3
|
XML Web App开发 JavaScript
前端入门教程(二)Web前端与HTML简介
一 web1.0时代的网页制作 网页制作是web1.0时代的产物,那个时候的网页主要是静态网页,所谓的静态网页就是没有与用户进行交互而仅仅供读者浏览的网页,我们当时称为“牛皮癣”网页。 例如一篇QQ日志、一篇博文等展示性文章。
2498 0
|
21天前
|
监控 JavaScript 前端开发
《理解 WebSocket:Java Web 开发的实时通信技术》
【4月更文挑战第4天】WebSocket是Java Web实时通信的关键技术,提供双向持久连接,实现低延迟、高效率的实时交互。适用于聊天应用、在线游戏、数据监控和即时通知。开发涉及服务器端实现、客户端连接及数据协议定义,注意安全、错误处理、性能和兼容性。随着实时应用需求增加,WebSocket在Java Web开发中的地位将更加重要。