第六章:构建 PWA 与部署
6.1 PWA 特性
Go-App 原生支持渐进式 Web 应用(PWA)的所有核心特性:
| 特性 | 说明 |
|---|
| 离线访问 | Service Worker 缓存资源 |
| 安装到主屏幕 | 像原生应用一样添加到主屏幕 |
| 推送通知 | 支持 Web Push 通知 |
| 后台同步 | 网络恢复后自动同步数据 |
| 响应式设计 | 适配各种屏幕尺寸 |
6.2 PWA 配置
Handler 配置
http.Handle("/", &app.Handler{
Name: "My PWA", // 应用名称
ShortName: "PWA", // 短名称(主屏幕显示)
Description: "A Go-App PWA", // 应用描述
Title: "我的 PWA 应用", // 页面标题
Author: "Your Name", // 作者
// 主题颜色
ThemeColor: "#000000", // 主题色
BackgroundColor: "#ffffff", // 背景色
// 图标配置
Icon: app.Icon{
Default: "/web/logo.png", // 默认图标
Large: "/web/logo-large.png",
AppleTouch: "/web/logo-apple.png",
},
// 启动画面
LoadingLabel: "加载中...",
// 缓存配置
CacheableResources: []string{
"/web/styles.css",
"/web/app.wasm",
"/web/images/",
},
// 预加载资源
Preconnect: []string{
"https://api.example.com",
},
})
图标要求
web/
├── logo.png # 192x192 默认图标
├── logo-large.png # 512x512 大图标
├── logo-apple.png # 180x180 Apple Touch Icon
└── favicon.ico # 网站图标
6.3 编译与构建
开发构建
# 编译 WASM(开发模式)
GOARCH=wasm GOOS=js go build -o web/app.wasm
# 复制 wasm_exec.js
cp "$(go env GOROOT)/misc/wasm/wasm_exec.js" web/
# 运行服务器
go run .
生产构建
#!/bin/bash
# build.sh - 生产构建脚本
set -e
echo "开始构建..."
# 1. 编译 WASM(优化模式)
export GOOS=js
export GOARCH=wasm
go build \
-ldflags="-s -w" \ # 去除符号表和调试信息
-trimpath \ # 去除路径信息
-o web/app.wasm
# 2. 复制支持文件
cp "$(go env GOROOT)/misc/wasm/wasm_exec.js" web/
# 3. 优化 WASM(可选,需要 wasm-opt)
if command -v wasm-opt &> /dev/null; then
echo "优化 WASM..."
wasm-opt -Oz web/app.wasm -o web/app.opt.wasm
mv web/app.opt.wasm web/app.wasm
fi
# 4. 编译服务器
go build -ldflags="-s -w" -o server .
echo "构建完成!"
构建优化选项
# 最小化构建(最小体积)
GOARCH=wasm GOOS=js go build -ldflags="-s -w" -o web/app.wasm
# 带调试信息的构建
go build -o web/app.wasm
# 使用 TinyGo(更小的 WASM 体积)
tinygo build -target wasm -o web/app.wasm
6.4 部署选项
选项 1:传统服务器
// 使用标准 HTTP 服务器
func main() {
http.Handle("/", &app.Handler{
Name: "My App",
})
// 静态文件服务
http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("./static"))))
log.Fatal(http.ListenAndServe(":8080", nil))
}
选项 2:Docker 部署
# Dockerfile
FROM golang:1.21-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN GOOS=js GOARCH=wasm go build -ldflags="-s -w" -o web/app.wasm
RUN go build -ldflags="-s -w" -o server .
FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=builder /app/server .
COPY --from=builder /app/web ./web
EXPOSE 8080
CMD ["./server"]
# docker-compose.yml
version: '3'
services:
goapp:
build: .
ports:
- "8080:8080"
restart: always
选项 3:静态站点部署(GitHub Pages / Netlify / Vercel)
// 生成静态网站
func main() {
app.Route("/", func() app.Composer { return &home{} })
// 生成静态文件
if err := app.GenerateStaticWebsite("dist", &app.Handler{
Name: "My Static App",
}); err != nil {
log.Fatal(err)
}
}
选项 4:云平台部署
Google Cloud Run:
# cloudbuild.yaml
steps:
- name: 'gcr.io/cloud-builders/go'
args: ['build', '-o', 'server']
- name: 'gcr.io/cloud-builders/docker'
args: ['build', '-t', 'gcr.io/$PROJECT_ID/go-app', '.']
images:
- 'gcr.io/$PROJECT_ID/go-app'
AWS Lambda:
// 使用 AWS Lambda 适配器
import (
"github.com/aws/aws-lambda-go/lambda"
"github.com/awslabs/aws-lambda-go-api-proxy/httpadapter"
)
func main() {
http.Handle("/", &app.Handler{
Name: "Lambda App",
})
adapter := httpadapter.New(http.DefaultServeMux)
lambda.Start(adapter.ProxyWithContext)
}
6.5 性能优化
WASM 体积优化
# 1. 使用 ldflags 去除调试信息
go build -ldflags="-s -w" -o web/app.wasm
# 2. 使用 UPX 压缩(可选)
upx --best web/app.wasm
# 3. 使用 wasm-opt 优化(Binaryen 工具)
wasm-opt -Oz web/app.wasm -o web/app.wasm
加载优化
http.Handle("/", &app.Handler{
Name: "Optimized App",
// 预加载关键资源
Preload: []app.Preload{
{
Href: "/web/app.wasm",
As: "fetch",
Type: "application/wasm",
},
{
Href: "/web/styles.css",
As: "style",
},
},
// DNS 预解析
Preconnect: []string{
"https://api.example.com",
},
})
缓存策略
http.Handle("/", &app.Handler{
CacheableResources: []string{
"/web/app.wasm",
"/web/styles.css",
"/web/images/*",
},
})
6.6 SEO 优化
预渲染
type page struct {
app.Compo
}
// 实现 PreRenderer 接口
func (p *page) OnPreRender(ctx app.Context) {
// 设置页面元数据
ctx.Page().SetTitle("页面标题")
ctx.Page().SetDescription("页面描述")
ctx.Page().SetAuthor("作者名")
// 设置 Open Graph 标签
ctx.Page().SetImage("https://example.com/image.png")
ctx.Page().SetURL("https://example.com/page")
}
func (p *page) Render() app.UI {
return app.Div().Body(
app.H1().Text("页面内容"),
)
}
元标签设置
func (p *page) OnPreRender(ctx app.Context) {
// 基础元标签
ctx.Page().SetTitle("My Page | Site Name")
ctx.Page().SetDescription("页面描述,用于搜索引擎摘要")
// 关键词
ctx.Page().SetKeywords("go, webassembly, pwa")
// 规范链接
ctx.Page().SetCanonical("https://example.com/page")
// Robots 指令
ctx.Page().SetRobots("index, follow")
}
6.7 CI/CD 配置
GitHub Actions
# .github/workflows/deploy.yml
name: Build and Deploy
on:
push:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: '1.21'
- name: Build WASM
run: |
GOOS=js GOARCH=wasm go build -ldflags="-s -w" -o web/app.wasm
cp "$(go env GOROOT)/misc/wasm/wasm_exec.js" web/
- name: Build Server
run: go build -ldflags="-s -w" -o server .
- name: Deploy to Server
run: |
# 部署命令
echo "部署到生产服务器"
GitLab CI
# .gitlab-ci.yml
stages:
- build
- deploy
build:
stage: build
image: golang:1.21
script:
- GOOS=js GOARCH=wasm go build -ldflags="-s -w" -o web/app.wasm
- cp "$(go env GOROOT)/misc/wasm/wasm_exec.js" web/
- go build -ldflags="-s -w" -o server .
artifacts:
paths:
- web/
- server
deploy:
stage: deploy
script:
- echo "部署到服务器"
only:
- main
6.8 监控与日志
错误处理
func main() {
defer func() {
if r := recover(); r != nil {
log.Printf("应用崩溃: %v", r)
// 发送错误报告
}
}()
// ... 应用代码
}
性能监控
type metricsComponent struct {
app.Compo
}
func (m *metricsComponent) OnMount(ctx app.Context) {
// 页面加载时间
performance := app.Window().Get("performance")
timing := performance.Get("timing")
loadTime := timing.Get("loadEventEnd").Int() - timing.Get("navigationStart").Int()
fmt.Printf("页面加载时间: %dms\n", loadTime)
}
6.9 完整项目结构
my-go-app/
├── cmd/
│ ├── server/ # 服务器代码
│ │ └── main.go
│ └── wasm/ # WASM 应用代码
│ └── main.go
├── pkg/
│ ├── components/ # 共享组件
│ ├── pages/ # 页面组件
│ └── utils/ # 工具函数
├── web/
│ ├── app.wasm # 编译后的 WASM
│ ├── wasm_exec.js # Go 桥接文件
│ ├── styles.css # 样式文件
│ ├── images/ # 图片资源
│ │ ├── logo.png
│ │ └── logo-large.png
│ └── manifest.json # PWA 配置
├── Dockerfile
├── docker-compose.yml
├── Makefile
├── go.mod
├── go.sum
└── README.md
Makefile
.PHONY: build run clean deploy
# 构建 WASM
wasm:
GOOS=js GOARCH=wasm go build -ldflags="-s -w" -o web/app.wasm ./cmd/wasm
cp "$(shell go env GOROOT)/misc/wasm/wasm_exec.js" web/
# 构建服务器
server:
go build -ldflags="-s -w" -o bin/server ./cmd/server
# 构建全部
build: wasm server
# 运行开发服务器
dev:
go run ./cmd/server
# 清理
clean:
rm -rf bin/
rm -f web/app.wasm
# Docker 构建
docker:
docker build -t go-app .
# 部署
deploy: build
# 部署脚本
@echo "部署到生产环境"
6.10 本章小结
在这一章中,我们学习了:
- ✅ PWA 核心特性和配置
- ✅ 开发构建与生产构建
- ✅ 多种部署选项(服务器、Docker、静态站点、云平台)
- ✅ WASM 体积优化和性能优化
- ✅ SEO 预渲染和元标签设置
- ✅ CI/CD 自动化部署
- ✅ 监控与日志
下一步
现在你已经掌握了 Go-App 的全部核心知识,可以:
- 构建实际项目:从简单的 Todo 应用到复杂的仪表盘
- 贡献开源:参与 Go-App 社区,贡献代码或文档
- 探索高级主题:WebSocket、GraphQL、微前端等
- 阅读源码:深入理解框架实现原理
参考资源
| 资源 | 链接 |
|---|
| Go-App 官方文档 | https://go-app.dev |
| GitHub 仓库 | https://github.com/maxence-charriere/go-app |
| Go WebAssembly | https://github.com/golang/go/wiki/WebAssembly |
| PWA 文档 | https://web.dev/progressive-web-apps/ |
教程完
恭喜你完成了《Go-App框架教程》的全部章节!
回顾学习内容:
- 第一章:框架介绍与快速开始
- 第二章:声明式语法与组件系统
- 第三章:路由与页面导航
- 第四章:状态管理与事件处理
- 第五章:与 JavaScript 和 DOM 交互
- 第六章:构建 PWA 与部署
开始你的 Go-App 之旅吧! 🚀
教程作者:小凯
参考文档:go-app.dev 官方文档
#教程 #Go #GoApp #PWA #WebAssembly #小凯