Skip to content

本地资源加载

本地资源加载模块允许 WebView 从本地文件系统或嵌入的 embed.FS 加载内容,无需启动 HTTP 服务器。

高层 API(推荐)

LocalLoad 配置

go
wvApp := wv.Init()
wvApp.SetLocalLoad(application.LocalLoad{
    Scheme:     "app",       // URL Scheme
    Domain:     "custom",    // 域名
    ResRootDir: "resources", // 资源目录
    FS:         resources,   // embed.FS(可选)
})

字段说明

字段类型说明
SchemestringURL Scheme 名称(如 "app"、"fs"),默认 "fs"
Domainstring域名(如 "custom"、"energy"),默认 "energy"
ResRootDirstring资源根目录(资源读取目录)
FSemfs.IEmbedFS嵌入的文件系统(可选,不设置则从本地目录读取)
Homestring默认首页,默认 "/index.html"
ProxyIXHRProxyXHR 代理配置(可选)

URL 格式

配置完成后,使用 {Scheme}://{Domain}/{path} 格式访问资源:

go
wvApp.SetOptions(application.Options{
    DefaultURL: "app://custom/index.html", // 加载 resources/index.html
})

嵌入文件系统

go
//go:embed resources/*
var resources embed.FS

wvApp.SetLocalLoad(application.LocalLoad{
    Scheme:     "app",
    Domain:     "custom",
    ResRootDir: "resources",
    FS:         resources,
})

本地文件系统

不设置 FS 字段,从本地目录读取:

go
wvApp.SetLocalLoad(application.LocalLoad{
    Scheme:     "app",
    Domain:     "custom",
    ResRootDir: "./web", // 从 ./web 目录读取
})

自定义 Scheme

Windows WebView2

通过 Loader 的 SetOnGetCustomSchemes 注册:

go
loader := wvWindows.NewLoader(nil)
loader.SetOnGetCustomSchemes(func(sender lcl.IObject, customSchemes *wvWindows.IWVCustomSchemeInfoArrayWrap) {
    tmpCustomSchemes := wvWindows.NewCustomSchemeInfoArrayWrapWithInt(1)
    tmpCustomSchemes.SetValue(0, wvWindows.TWVCustomSchemeInfo{
        SchemeName:            "myscheme",
        TreatAsSecure:         1,
        HasAuthorityComponent: 1,
    })
    *customSchemes = tmpCustomSchemes
})

// 拦截资源请求
browser.AddWebResourceRequestedFilter("myscheme*", wvTypes.COREWEBVIEW2_WEB_RESOURCE_CONTEXT_ALL)
browser.SetOnWebResourceRequested(func(sender, webView wvWindows.ICoreWebView2, args wvWindows.ICoreWebView2WebResourceRequestedEventArgs) {
    // 处理资源请求
    req := args.Request()
    reqUrl, _ := url.Parse(req.Uri())
    data, _ := resources.ReadFile("assets" + reqUrl.Path)
    stream := lcl.NewBytesStream(data)
    adapter := lcl.NewStreamAdapter(stream, types.SoOwned)
    environment.CreateWebResourceResponse(adapter, 200, "OK", "Content-Type: text/html", &response)
    args.SetResponse(response)
})

Linux WebKit2GTK

通过 WebContext.RegisterURIScheme 注册:

go
webview := wvLinux.NewWebview(m)

wkContext := wvLinux.WebContext.Default()
wkContext.RegisterURIScheme("energy", webview.AsSchemeRequestDelegate())

webview.SetOnURISchemeRequest(func(sender lcl.IObject, wkURISchemeRequest wvTypes.WebKitURISchemeRequest) {
    uriSchemeRequest := wvLinux.NewURISchemeRequest(wkURISchemeRequest)
    path := uriSchemeRequest.Path()
    data, _ := resources.ReadFile(filepath.Join("assets", path))
    ins := wvLinux.InputStream.New(uintptr(unsafe.Pointer(&data[0])), int64(len(data)))
    uriSchemeRequest.Finish(ins.Data(), int64(len(data)), "text/html")
})

macOS WKWebView

通过 URLSchemeHandler 注册:

go
webview := wvDarwin.NewWebview(m)

configuration := wvDarwin.WebViewConfiguration.New()
URLSchemeHandler := wvDarwin.NewURLSchemeHandler(webview.AsWKURLSchemeHandlerDelegate())
configuration.SetURLSchemeHandlerForURLScheme(URLSchemeHandler.Data(), "energy")

webview.SetOnStartURLSchemeTask(func(sender lcl.IObject, webView wvTypes.WKWebView, urlSchemeTask wvTypes.WKURLSchemeTask) {
    // 处理资源请求
})

webview.SetOnStopURLSchemeTask(func(sender lcl.IObject, webView wvTypes.WKWebView, urlSchemeTask wvTypes.WKURLSchemeTask) {
    // 停止资源请求
})

XHR 代理

XHR 代理允许 WebView 中的 XMLHttpRequest 通过 Go 端发起 HTTP 请求。

配置

go
wvApp.SetLocalLoad(application.LocalLoad{
    Scheme:     "app",
    Domain:     "custom",
    ResRootDir: "resources",
    FS:         resources,
    Proxy: &application.XHRProxy{
        Scheme: application.LpsHttp,
        IP:     "127.0.0.1",
        Port:   8080,
    },
})

XHRProxy 字段

字段类型说明
SchemeLocalProxyScheme代理协议(LpsHttp / LpsHttps)
IPstring代理 IP 地址,默认 "localhost"
Portint代理端口,默认 80
SSLXHRProxySSLHTTPS 证书配置
HttpClient*HttpClient自定义 HTTP 客户端

HTTPS 代理

go
Proxy: &application.XHRProxy{
    Scheme: application.LpsHttps,
    IP:     "127.0.0.1",
    Port:   8443,
    SSL: application.XHRProxySSL{
        RootDir: "certs",           // 证书文件目录
        Cert:    "server.crt",      // 证书文件路径
        Key:     "server.key",      // 私钥文件路径
        CARoots: []string{"ca.crt"}, // CA 根证书文件路径列表
    },
}

XHRProxySSL 字段

字段类型说明
FSemfs.IEmbedFS证书文件嵌入 FS(可选)
RootDirstring证书文件根目录
Certstring证书文件路径
Keystring私钥文件路径
CARoots[]stringCA 根证书文件路径列表

XHRProxyResponse 响应

字段类型说明
Data[]byte响应数据
DataSizeint数据大小
StatusCodeint32HTTP 状态码
Statusstring状态文本
Headermap[string][]string响应头

JavaScript 端使用

加载本地资源

html
<!-- 直接引用本地资源 -->
<script src="app://custom/scripts/app.js"></script>
<link rel="stylesheet" href="app://custom/styles/main.css">
<img src="app://custom/images/logo.png">

发起代理请求

javascript
// 请求会通过 Go 端的 XHRProxy 代理
fetch("http://127.0.0.1:8080/api/data")
    .then(response => response.json())
    .then(data => {
        console.log(data);
    });

完整示例

go
package main

import (
    "embed"
    "github.com/energye/energy/v3/application"
    "github.com/energye/energy/v3/ipc"
    "github.com/energye/energy/v3/wv"
    "github.com/energye/energy/v3/window"
    "github.com/energye/lcl/lcl"
    "github.com/energye/lcl/types"
)

//go:embed resources/*
var resources embed.FS

type TMainForm struct {
    window.TWindow
    Webview1 wv.IWebview
}

var MainForm TMainForm

func main() {
    wvApp := wv.Init()
    wvApp.SetOptions(application.Options{
        Caption:    "Local Load Demo",
        DefaultURL: "app://custom/index.html",
        Width:      1200,
        Height:     800,
    })
    wvApp.SetLocalLoad(application.LocalLoad{
        Scheme:     "app",
        Domain:     "custom",
        ResRootDir: "resources",
        FS:         resources,
    })

    ipc.On("hello", func(context ipc.IContext) {
        context.Result("world")
    })

    wv.Run(&MainForm)
}

func (m *TMainForm) FormCreate(sender lcl.IObject) {
    m.InternalBeforeFormCreate()
    m.Webview1 = wv.NewWebview(m)
    m.Webview1.SetParent(m)
    m.Webview1.SetAlign(types.AlClient)
    m.Webview1.SetWindow(m)
    m.TWindow.FormCreate(sender)
}

func (m *TMainForm) OnShow(sender lcl.IObject) {
    m.WorkAreaCenter()
    m.Webview1.CreateBrowser()
}

资源目录结构

project/
├── resources/
│   ├── index.html
│   ├── app.js
│   ├── style.css
│   └── images/
│       └── logo.png
├── main.go
└── go.mod

GO
ENERGY