如何使用 Go (Golang) 和 React.js 创建具有完整代码保护功能的 macOS 原生应用 — 第一部分
由 Mux 主办的 DEV 全球展示挑战赛:展示你的项目!
介绍
欢迎来到“操作指南”系列的下一篇文章!这一次,我们将分析如何为苹果 macOS 创建原生桌面应用程序,并使用 Go (Golang) 和 React.js 编写一些代码,该应用程序将具有防复制功能。
我们会尽量不用魔法就能做到!😉
文章组成部分
✅第一部分:第三方 Go 包管理器(您当前所在位置)
🕓 第二部分:使用 Go 模块的全新 Go-way
作者注:本文(最初)写于大约半年前,因此我使用的
dep是 Go 的包管理器。我正在准备本文的第二部分,介绍如何使用 Go Modules 进行现代编码。
本文的目标
- 展示使用 Golang 为 macOS 创建原生桌面应用程序的最简单方法之一。
- 显示保护应用程序代码免受第三方修改的选项(例如,在商业分发期间)。
工作环境
- 去
v1.12.5 - Node.js
v12.3.1
操作系统
- Apple macOS 10.14.5 Mojave (
darwin/amd64)
软件包和依赖项管理器
- (
v0.5.3Go) - npm
v6.9.0(Node.js)
已使用包裹
去
net/http- 用于创建 Web 服务器的标准软件包(godoc)gobuffalo/packr- 用于将所有必要的源代码打包成一个可执行二进制文件的软件包(GitHub)zserge/webview- 用于创建带有内置浏览器的原生操作系统窗口的跨平台软件包(GitHub)
Node.js
理论基础
为了更好地理解正在发生的事情,我建议您检查一下我们将依赖和使用的一些软件包的工作情况。
net/http
一个提供 HTTP 客户端和服务端实现的软件包。它包含在标准的 Go 软件包中,无需单独安装和配置。
我们觉得它很有趣,因为它很容易理解,有很好的文档,而且功能齐全http.FileServer()。
更多详情请参阅官方文档。
http.FileServer()
此函数至关重要,它赋予 Web 服务器对指定文件夹及其所有文件的完全访问权限。也就是说,该http.FileServer()函数允许您将文件夹挂载到 Web 服务器的任何指定地址(路由)。
例如,挂载根文件夹./static/images/photos,使其可通过以下路径访问http://localhost:8000/photos:
http.Handle("/photos", http.FileServer("./static/images/photos"))
gobuffalo/packr
一个带有会说话的标题的软件包。正是他让我们能够将所有必要的文件打包成一个二进制文件。
请注意:我们目前使用的是
packrv1 分支。
假设我们有以下项目目录结构:
$ tree .
.
├── main.go
└── templates
├── admin
│ └── index.html
└── index.html
文件./main.go内容如下:
package main
import (
"fmt"
"log"
"github.com/gobuffalo/packr"
)
func main() {
// Folder with templates that are needed
// to add to binary file
box := packr.NewBox("./templates")
// Search file inside folder
s, err := box.FindString("amdin/index.html")
if err != nil {
log.Fatal(err)
}
fmt.Println(s)
}
现在让我们把项目编译成可执行的二进制文件。同时,packr 包会将./templates文件夹中的所有内容打包到该文件中:
$ packr build ./main.go
如果您想为当前使用的操作系统或架构以外的其他操作系统或架构创建二进制文件,请按packr如下方式调用(适用于 GNU/Linux、x64):
$ GOOS=linux GOARCH=amd64 packr build ./main.go
zserge/webview
一款用于创建现代图形界面的轻量级跨平台网页浏览软件包。
请注意:本文介绍了如何使用
v0.1.0。
文件./main.go内容如下:
package main
import "github.com/zserge/webview"
func main() {
// Open Google into a desktop webview window,
// 1024x768 px, without resize
webview.Open("Google", "https://google.com", 1024, 768, false)
}
项目结构
$ tree .
.
├── vendor
├── ui
│ ├── build
│ ├── node_modules
│ ├── public
│ ├── src
│ ├── package-lock.json
│ └── package.json
├── helloworld.app
├── Gopkg.lock
├── Gopkg.lock
├── Makefile
└── main.go
主要文件和文件夹的描述
vendor所有使用 dep 安装的软件包都将存储在这里。ui— 包含 React.js 应用程序(前端)的文件夹ui/build— 构建完成后,包含 React 应用生产版本的文件夹ui/src— 包含 React 应用源代码的文件夹ui/package.json— 依赖文件npmhelloworld.app— macOS 应用程序(专门准备的文件夹)Gopkg.toml— 依赖文件depMakefile— 编写脚本,以便轻松构建应用程序main.go— Golang 应用程序源代码(后端)
编写代码
理论就到此为止。正如我们这个时代最伟大的程序员之一, Linus Torvalds所说(毫不夸张):
光说不练假把式,拿出代码来。
——林纳斯·托瓦兹
让我们按照这个建议编写一些代码。
我不会逐行分析代码,因为我认为这样做是多余的,而且适得其反。所有代码清单都附有详细注释。
正在寻找“完整代码”示例?
没问题!👌 我特意在我的 GitHub 上为你创建了一个仓库:
koddr / example-go-react-macos-app-1
使用 Go (Golang) 和 React.js 开发的 macOS 原生应用示例
只是git clone和make。
新手备忘录/复制粘贴开发者
太好了,文章末尾附有完整的代码清单,对吧?你可以直接复制所有程序代码,无需阅读正文,就能查看其运行结果……在此,我想对所有不想在理论上浪费时间的读者说:
不要盲目地从网上复制代码!
这既不能帮助你(理解代码和文章主题),也不能帮助作者(在评论中解释/提供帮助)。
应用前端
React.js 是一个功能强大且易于学习的 JavaScript 库,用于创建用户界面,非常适合我们实现应用程序的前端部分。
请注意:本文将仅使用标准的 React.js 页面。
与现代前端开发中的所有内容一样,我们首先要安装 React.js 和所有必要的辅助库。
- 创建一个用于存放应用程序的文件夹,然后进入该文件夹。
- 根据已完成应用程序的结构,在
./ui以下目录中安装 React.js:
$ npx create-react-app ui
- 请转到文件夹并检查所有功能是否正常:
$ cd ui && npm start && open http://localhost:3000
- 停止开发服务器(按
Ctrl+C),然后安装axios库:
$ npm i --save axios
- 好的!👍 文件源代码
./ui/src/App.js:
// Import React and React Hooks
import React, { useState, useEffect } from "react";
// Import axios
import axios from "axios";
// Import logo and CSS
import logo from "./logo.svg";
import "./App.css";
function App() {
// Define storage for data
const [state, setState] = useState([]);
// Retrieving data from an AJAX request.
// Remember that the function passed to useEffect will run,
// after render is fixed on the screen.
// See https://reactjs.org/docs/hooks-reference.html#useeffect
useEffect(() => {
axios
.get("/hello") // GET request to URL /hello
.then(resp => setState(resp.data)) // save response to state
.catch(err => console.log(err)); // catch error
});
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>Hello, {state.text}!</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
</div>
);
}
export default App;
应用后端
- 安装必要的 Go 软件包:
$ dep ensure -add github.com/gobuffalo/packr
$ dep ensure -add github.com/zserge/webview
- 此外,我们还需要 packr 工具,该工具应该可以通过控制台调用
$GOPATH/bin/packr:
$ go get -u github.com/gobuffalo/packr/packr
- 文件源代码
./main.go:
package main
import (
"encoding/json"
"net/http"
"github.com/gobuffalo/packr"
"github.com/zserge/webview"
)
// Message : struct for message
type Message struct {
Text string `json:"text"`
}
func main() {
// Bind folder path for packaging with Packr
folder := packr.NewBox("./ui/build")
// Handle to ./static/build folder on root path
http.Handle("/", http.FileServer(folder))
// Handle to showMessage func on /hello path
http.HandleFunc("/hello", showMessage)
// Run server at port 8000 as goroutine
// for non-block working
go http.ListenAndServe(":8000", nil)
// Let's open window app with:
// - name: Golang App
// - address: http://localhost:8000
// - sizes: 800x600 px
// - resizable: true
webview.Open("Golang App", "http://localhost:8000", 800, 600, true)
}
func showMessage(w http.ResponseWriter, r *http.Request) {
// Create Message JSON data
message := Message{"World"}
// Return JSON encoding to output
output, err := json.Marshal(message)
// Catch error, if it happens
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
// Set header Content-Type
w.Header().Set("Content-Type", "application/json")
// Write output
w.Write(output)
}
构建原生 macOS 应用 🏗
- 创建 macOS 应用的目录结构:
$ mkdir -p helloworld.app/Contents/MacOS
- 编译
./main.go到应用程序文件夹:
$ go build -o helloworld.app/Contents/MacOS/helloworld
- 运行应用程序:
$ open helloworld.app
- 结果:
适用于 Windows 和 GNU/Linux 的交叉编译
本文提供的理论框架和代码也适用于开发其他操作系统上的类似应用程序。在这种情况下,代码无需修改。
编写一次代码,到处运行!
这是由于其跨系统特性而实现的。
- GNU/Linux — 可执行二进制文件
- Microsoft Windows — 可执行文件
.exe .appApple macOS — 位于结构体内部的二进制文件
我们将在后续文章中探讨这个问题。
敬请关注,欢迎评论,并且请只编写优质代码!
固定材料
文章已读完。现在你比8分钟前了解得更多了。
恭喜你! 🎉
留出 10-15 分钟时间,回忆阅读文本并复习文章中学习过的代码。接下来,尝试回答问题并完成练习,以便更好地巩固所学内容。
是的,你可以窥探,但前提是你记不起来了。
问题
net/http用于将文件夹挂载到指定地址(路由)的标准 Go 包的功能是什么?- 标准 Go 包中的 Marshal 函数是做什么的
encoding/json? - 全高清应用程序的源代码中需要更改哪些参数?
- 如果你想启动一个没有问号的 Web 服务器
goroutine? - 命令是什么
packr build ./main.go?
练习
showMessage()为函数( )编写测试./main.go。- 为前端应用程序编写测试(
./ui/src/App.js)。 - 重写前端应用程序中的 AJAX 请求代码,不要使用 axios 库。提示:使用Fetch API功能。
- 在函数中向前端输出添加更多 JSON 数据
showMessage()。例如:向 `theMessage` 结构添加一个新的 `Emoji` 属性,并在 `Text` 属性之后输出该属性(包含您喜欢的表情符号)。 - 尝试改进应用程序的外观。提示:使用 Material UI 可视化组件库(GitHub)。
照片由
[标题] Jantine Doornbos https://unsplash.com/photos/HvYy5SEefC8
[1] 马天一https://unsplash.com/photos/WiONHd_zYI4
[2] Fabian Grohs https://unsplash.com/photos/XMFZqrGyV-Q
[3] Priscilla Du Preez https://unsplash.com/photos/XkKCui44iM0
[演示] Vic Shóstak(文章作者)
PS
如果你想在这个博客上看到更多类似的文章,请在下方留言并订阅我。谢谢!😻
❗️您可以通过Boosty平台支持我,既可以长期支持,也可以一次性支持。所有收益都将用于支持我的开源软件项目,并激励我为社区创作新的产品和文章。
当然,您也可以帮助我让开发者的工作变得更好!只需以贡献者的身份加入我的项目即可。很简单!
我最需要你帮助(和点赞)的项目👇
- 🔥 gowebly:一款新一代 CLI 工具,可轻松使用 Go 在后端创建出色的 Web 应用程序,使用 htmx、hyperscript 或 Alpine.js 以及最流行的 CSS 框架在前端进行开发。
- ✨ create-go-app:通过运行一条 CLI 命令,创建一个包含 Go 后端、前端和部署自动化功能的新生产就绪项目。
我的其他一些小项目:yatr、gosl、json2csv、csv2api。
文章来源:https://dev.to/koddr/how-to-create-a-native-macos-app-on-go-golang-and-react-js-with-full-code-protection-part-1-463k


