golang react_如何在React中使用WebAssembly for Go起飞

golang react

by Chris Chuck

克里斯·查克(Chris Chuck)

如何在React中使用WebAssembly for Go起飞 (How to take off with WebAssembly for Go in React)

With Go version 1.11, we now get an experimental version of WebAssembly. If you don’t know what WebAssembly is, don’t fret. In short, WebAssembly aims to bring high performance, assembly-like code into the browser. This allows developers to put more computationally intensive tasks into the browser, be it for a game or making some super cool animations.

使用Go版本1.11,我们现在可以获得WebAssembly的实验版本。 如果您不知道什么是WebAssembly,请不要担心。 简而言之,WebAssembly旨在将高性能的,类似于汇编的代码引入浏览器。 这使开发人员可以将更多计算密集型任务放到浏览器中,无论是用于游戏还是制作一些超酷的动画

So with that, I’m going to show you how to add Go-based WebAssembly to a React app! This guide assumes you have some familiarity with Webpack, Babel, and React. If you’re new to these technologies, I highly recommend you checkout this tutorial.

因此,我将向您展示如何将基于Go的WebAssembly添加到React应用程序! 本指南假定您对Webpack,Babel和React有所了解。 如果您不熟悉这些技术,强烈建议您阅读本教程

This tutorial will show you how to create a basic React app that utilizes WebAssembly for Go. In the near future, I’ll show you how to build a tic-tac-toe game in which the computer is 100% unbeatable and we’ll use WebAssembly to power the minimax algorithm (don’t worry, it sounds harder than it is!) ?

本教程将向您展示如何创建一个利用WebAssembly for Go的基本React应用。 在不久的将来,我将向您展示如何构建井字游戏,在该游戏中计算机100%无与伦比,并且我们将使用WebAssembly来支持minimax算法(别担心,这听起来比它更难是!)

The code for this part (and future parts) will be on Github here.

对于这部分(以及将来的部件)的代码将在Github 这里

先决条件和初始设置 (Prerequisites and Initial Setup)

Make sure you have Go 1.11 (minimum) and Node.js installed.

确保已安装Go 1.11(最低版本)和Node.js。

I am using Chrome version 69 and all current versions of Edge, Firefox, and Safari have WebAssembly support. However, results from this tutorial may vary based on version/browser.

我正在使用Chrome版本69,并且Edge,Firefox和Safari的所有当前版本都具有WebAssembly 支持 。 但是,本教程的结果可能会因版本/浏览器而异。

Jumping right into it, create a folder and cd into it.

跳到该文件夹​​中,创建一个文件夹并cd进入该文件夹。

Inside that folder create a client and a server folder.

在该文件夹内创建一个client和一个server文件夹。

React App (The React App)

Let’s start with building the React App. It’s nothing more than a regular client side rendered app with a few extra bits added in!

让我们从构建React App开始。 它不过是一个普通的客户端渲染应用程序,其中添加了一些额外的功能!

First cd into the client folder and run npm init -y to initialize your package.json.

首先cd进入client文件夹,然后运行npm init -y初始化package.json

After that, run the following:

之后,运行以下命令:

npm install --save react react-dom && npm install --save-dev @babel/core @babel/plugin-proposal-class-properties @babel/plugin-proposal-decorators @babel/plugin-syntax-dynamic-import @babel/polyfill @babel/preset-env @babel/preset-react add-asset-html-webpack-plugin babel-loader html-webpack-plugin webpack webpack-cli webpack-dev-server

Once you do that, change the scripts portion of your package.json to the following:

完成后,将package.jsonscripts部分更改为以下内容:

"scripts": {  "dev": "webpack-dev-server --mode development",  "build": "webpack --mode production"},

Next, in the client folder, create two files, a .babelrc and a webpack.config.js.

接下来,在客户端文件夹中,创建两个文件, .babelrcwebpack.config.js

In the .babelrc paste the following:

.babelrc粘贴以下内容:

{  "presets": [ ["@babel/preset-env", { "modules": false } ],  "@babel/preset-react"],  "plugins": [    "@babel/plugin-proposal-class-properties",    ["@babel/plugin-proposal-decorators", { "legacy": true }],    "@babel/plugin-syntax-dynamic-import"  ]}

And in the webpack.config.js paste the following:

然后在webpack.config.js粘贴以下内容:

Note the AddAssetHtmlPlugin which we are using to inject the wasm_exec.js file and init_go.js file into our app via a script tag. These must be in the order they are shown so that the wasm_exec.js file runs before init_go.js file. The wasm_exec.js simply sets up Go’s runtime on the browser and the init_go.js file gives us a global, workable Go object instance. But more on these files later.

请注意AddAssetHtmlPlugin ,我们将其wasm_exec.js通过脚本标签将wasm_exec.js文件和init_go.js文件注入到我们的应用程序中。 它们必须按照显示顺序排列,以便wasm_exec.js文件在init_go.js文件之前运行。 wasm_exec.js只是在浏览器上设置Go的运行时,而init_go.js文件为我们提供了一个全局的,可行的Go对象实例。 但是稍后会详细介绍这些文件。

Now create a src folder and add an index.js file, index.html file, init_go.js file, wasm_exec.js file, and a components folder with an app.js file in it. Your directory should look like so:

现在创建一个src文件夹,并添加一个index.js文件, index.html文件, init_go.js文件, wasm_exec.js文件以及其中包含app.js文件的components文件夹。 您的目录应如下所示:

From here, add this to your index.html:

在这里,将其添加到您的index.html

In the index.js add this:

index.js添加以下内容:

And in your components/app.js file add the following:

并在components/app.js文件中添加以下内容:

Now we have an extremely basic React app!

现在我们有了一个非常基础的React应用程序!

客户端上的WebAssembly (WebAssembly on the Client)

In the wasm_exec.js file, paste the code from here (omitted for brevity).

wasm_exec.js文件中,从此处粘贴代码(为简洁起见, 此处省略)。

Like we said before, this just instantiates the basic runtime for Go in the client. It provides a global Go constructor that we’ll be using later.

就像我们之前说的,这只是实例化了客户端中Go的基本运行时。 它提供了一个全局的Go构造函数,稍后我们将使用它。

Next we need to actually do something with that Go object. So in your init_go.js file, add the following:

接下来,我们需要对该Go对象进行实际操作。 因此,在您的init_go.js文件中,添加以下内容:

All this does is create a new go object from the Go constructor we made earlier and bind it to global state.

这一切都是从我们之前创建的Go构造函数创建一个新的go对象,并将其绑定到全局状态。

Go ahead and run npm run dev and the navigate to localhost:8080 in the browser and you should see “Hello!” on your webpage. Not very interesting right? But what you don’t see is that we’ve injected our global go object!

继续运行npm run dev并在浏览器中导航到localhost:8080 ,您应该看到“ Hello!”。 在您的网页上。 不是很有趣吧? 但是您看不到的是我们已经注入了全局go对象!

Now change your components/app.js file to the following:

现在,将您的components/app.js文件更改为以下内容:

What did we change? Let’s start with the simple stuff. First we added an isLoading attribute to state. This is so we know that WebAssembly is still loading. In the render function, we use the isLoading attribute from state to conditionally render a div that says “Loading” or a button.

我们改变了什么? 让我们从简单的东西开始。 首先,我们向状态添加了isLoading属性。 因此,我们知道WebAssembly仍在加载。 在render函数中,我们使用isLoading属性有条件地渲染一个表示“ Loading”或buttondiv

You may be asking yourself, “That button has an onClick with a function sayHi, but I don’t see a sayHi function anywhere.” This is where WebAssembly comes in. When we write our Go code, we’ll be defining that function and binding it to global state there. This is why we must wait for WebAssembly to load before we can render our button. But we’ll fill in these blanks later.

您可能会问自己:“该按钮具有一个带有sayHi函数的onClick ,但在任何地方都看不到sayHi函数。” 这就是WebAssembly出现的地方。当我们编写Go代码时,我们将定义该函数并将其绑定到那里的全局状态。 这就是为什么我们必须等待WebAssembly加载后才能呈现按钮。 但是我们稍后将填写这些空白。

Looking at the componentDidMount function, you can see we’re calling WebAssembly.instantiateStreaming which is the optimal way of loading WebAssembly code. It takes a promise that returns a wasm file and an importObject as its parameters. It returns a compiled WebAssembly module. That promise is a fetch request to our API (we’ll build it next!) and that endpoint just returns a wasm file. After we get the module, we use go to run it and then we set isLoading to false.

查看componentDidMount函数,您可以看到我们正在调用WebAssembly.instantiateStreaming ,这是加载WebAssembly代码最佳方法 。 它承诺返回一个wasm文件和一个importObject作为其参数。 它返回一个已编译的WebAssembly模块。 这个承诺是对我们的API的提取请求(我们将在下一个构建它!),该端点仅返回wasm文件。 获取模块后,使用go运行它,然后将isLoading设置为false

But of course, since we have nothing on localhost:3000 this will break.

但是,当然,因为我们在localhost:3000上什么都没有,所以这会中断。

服务器 (The Server)

Now we need to setup the server to serve our wasm file. First, open up a new terminal and cd into the server folder you made earlier and run npm init -y to initialize your package.json.

现在我们需要设置服务器来提供wasm文件。 首先,打开一个新终端,并cd到您之前创建的server文件夹中,然后运行npm init -y初始化package.json

Next, let’s install some packages. Run the following:

接下来,让我们安装一些软件包。 运行以下命令:

npm install --save compression cors express && npm install --save-dev nodemon

Change the scripts portion of your package.json to this:

package.jsonscripts部分更改为此:

"scripts": {  "dev": "nodemon index.js"},

Now in the server directory, create an index.js file and a go folder. In that go folder, create a main.go file.

现在在server目录中,创建一个index.js文件和一个go文件夹。 在该go文件夹中,创建一个main.go文件。

Your folder should look like this:

您的文件夹应如下所示:

In the index.js paste the following:

index.js粘贴以下内容:

This is just a simple express server which serves up a wasm file from the go folder. Let’s make that now!

这只是一个简单的快递服务器,它从go文件夹提供wasm文件。 现在就开始做吧!

服务器上的WebAssembly (WebAssembly on the Server)

In your main.go file add this (big thanks to TutoiralEdge for his tutorial):

在您的main.go文件中添加以下内容(非常感谢TutoiralEdge的教程 ):

Let’s break this down. First we need to import fmt for basic printing and syscall/js so we can use all of Go’s new JavaScript goodies. Next we’ll create our sayHi function with parameters args []js.Value even though we’re not going to pass in any arguments. All this function does is print “Hi!”

让我们分解一下。 首先,我们需要导入fmt进行基本的打印和syscall/js以便可以使用Go的所有新JavaScript好东西 。 接下来,即使我们不传递任何参数,也将使用参数args []js.Value创建我们的sayHi函数。 该功能仅打印“ Hi!”

In the registerCallbacks function, we bind our function to global state in our browser. Now when we call js.Global().Set function we’re going to first name our global variable “sayHi” and then pair it with our sayHi function from above by wrapping it in the js.NewCallback function.

registerCallbacks函数中,我们将函数绑定到浏览器中的全局状态。 现在,当我们调用js.Global().Set函数时,我们将首先命名全局变量“ sayHi”,然后通过将其包装在js.NewCallback函数中,将其与我们的sayHi函数js.NewCallback

Lastly, in our main function, we’re opening up a channel and running registerCallbacks. The channel simply stalls our Go code so it doesn’t finish executing.

最后,在我们的main功能中,我们打开一个通道并运行registerCallbacks 。 该通道只是停顿了我们的Go代码,因此无法完成执行。

Now all that’s left is compiling this Go code into WebAssembly.

现在剩下的就是将Go代码编译为WebAssembly。

cd into the go folder and run the following:

cd进入go文件夹并运行以下命令:

GOOS=js GOARCH=wasm go build -o main.wasm

Notice that our GOOS is set to js and our GOARCH is set to wasm. This means that our target operating system is js and the compilation architecture is wasm.

注意,我们的GOOS设置为js ,我们的GOARCH设置为wasm 。 这意味着我们的目标操作系统是js ,编译架构是wasm

Your folder structure should be this now:

您的文件夹结构应该是这样的:

As you can see, now we have a main.wasm file we can serve.

如您所见,现在我们可以提供一个main.wasm文件。

cd back into the server folder and run npm run dev.

cd返回server文件夹并运行npm run dev

Your server should now be running on localhost:3000. Go back to localhost:8080 (assuming you still have the client running) in your browser and refresh it. After it loads, open up the console and click the button. It should print “Hi!” in the console.

您的服务器现在应该在localhost:3000上运行。 返回到浏览器中的localhost:8080 (假设您仍在运行客户端)并刷新它。 加载后,打开控制台并单击按钮。 它应该打印“嗨!” 在控制台中。

As you probably saw, it’ll say “Loading” for quite some time before our button appears. This is the overhead we incur from using WebAssembly. However, after this initial load, we can bask in low level, high performance glory.

您可能已经看到,在我们的按钮出现之前,它会说“正在加载”一段时间。 这是我们使用WebAssembly产生的开销 。 但是,在此初始负载之后,我们可以享受低水平,高性能的荣耀。

To kill the client and server, just press ctrl + c in your terminals.

要终止客户端和服务器,只需在终端中按ctrl + c

结论 (Conclusion)

Thank you for reading and I hope you enjoyed learning about WebAssembly with me. While this is an extremely basic implementation of WebAssembly in React, in the next part of this series, we’ll be making an AI agent that’s unbeatable at tic-tac-toe. So stay tuned if you’re interested in that!

感谢您的阅读,希望您喜欢和我一起学习WebAssembly。 尽管这是React中WebAssembly的一个极其基本的实现,但是在本系列的下一部分中,我们将制作一个在井字游戏中无与伦比的AI代理。 因此,如果您对此感兴趣,请继续关注!

If you have any comments or questions feel free to leave them below.

如果您有任何意见或疑问,请随时将其留在下面。

Thanks again for reading! Please share, drop a ? (or two), and happy coding.

再次感谢您的阅读! 请分享,删除一个 ? ( 或两个),并且编码愉快。

Add me on LinkedIn!

LinkedIn上加我!

翻译自: https://www.freecodecamp.org/news/taking-off-with-webassembly-for-go-in-react-7c099bd907fa/

golang react

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值