MeteorCat / Godot版本Web部署

Created Tue, 04 Jun 2024 18:34:49 +0800 Modified Wed, 29 Oct 2025 23:24:59 +0800
1139 Words

Godot版本Web部署

需要注意目前版本号: Godot4.2.2.stable, 听说后续版本会优化修复

这里采用了简单空项目用来检查显示鼠标的项目, 打出来的包大小为 wasm 单个文件大小竟然达到 47.0 MB(开启调试导出) | 34.0MB(不导出调试)!

或许你接触到日常游戏就会感觉到这个容量没什么, 但是可要知道这是 Web浏览器 受限于 Web 的权限导致资源大部分都是直接访问加载.

可以想象打开网页每次需要下载 48|34 MB 资源才能进游戏黑屏加载, 移动端网络环境特别复杂3G/4G/宽带网等情况

在没有分包加载情况, wasm 和 worker.js 加载及其恐怖且伴随兼容性问题, 目前已知某些浏览器是无法支持:

  • 微信H5内核浏览器
  • 部分Chromium打包浏览器
  • 部分FireFox浏览器

之前安全性问题导致 SharedArrayBuffer 被禁用, 知道后续修改规范要求强制 https 同源访问才放出.

这里提供测试的 Godot 测试地址方便查看:

测试地址, 点击左边连接可以测试访问(服务器在国外可能速度比较慢)

这里可以看出其加载的异常状态:

wasm

这恐怖的包体是必须预先下载总合计 48|34 MB, 服务器哪怕开启大量的资源压缩技术( cf/gzip/br 等, 但是本身 wasm 也是压缩过了 ) 也没办法避免庞大胞体, 这也是不得不放弃开发 GodotWeb 版本原因, 其他还有大量国内浏览器带来的兼容问题.

官方GitHub也有人讨论 这个问题

本地测试脚本

Godot 导出项目之后需要在本地测试样例项目是否运行成功, 这里依靠 Python 挂载服务( serve.py 文件 ):

#!/usr/bin/env python3

import argparse
import contextlib
import os
import socket
import subprocess
import sys
from http.server import HTTPServer, SimpleHTTPRequestHandler, test  # type: ignore
from pathlib import Path


# See cpython GH-17851 and GH-17864.
class DualStackServer(HTTPServer):
    def server_bind(self):
        # Suppress exception when protocol is IPv4.
        with contextlib.suppress(Exception):
            self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, 0)
        return super().server_bind()


class CORSRequestHandler(SimpleHTTPRequestHandler):
    def end_headers(self):
        self.send_header("Cross-Origin-Opener-Policy", "same-origin")
        self.send_header("Cross-Origin-Embedder-Policy", "require-corp")
        self.send_header("Access-Control-Allow-Origin", "*")
        super().end_headers()


def shell_open(url):
    if sys.platform == "win32":
        os.startfile(url)
    else:
        opener = "open" if sys.platform == "darwin" else "xdg-open"
        subprocess.call([opener, url])


def serve(root, port, run_browser):
    os.chdir(root)

    if run_browser:
        # Open the served page in the user's default browser.
        print("Opening the served URL in the default browser (use `--no-browser` or `-n` to disable this).")
        shell_open(f"http://127.0.0.1:{port}")

    test(CORSRequestHandler, DualStackServer, port=port)


if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("-p", "--port", help="port to listen on", default=8060, type=int)
    parser.add_argument(
        "-r", "--root", help="path to serve as root (relative to `platform/web/`)", default="../../bin", type=Path
    )
    browser_parser = parser.add_mutually_exclusive_group(required=False)
    browser_parser.add_argument(
        "-n", "--no-browser", help="don't open default web browser automatically", dest="browser", action="store_false"
    )
    parser.set_defaults(browser=True)
    args = parser.parse_args()

    # Change to the directory where the script is located,
    # so that the script can be run from any location.
    os.chdir(Path(__file__).resolve().parent)

    serve(args.root, args.port, args.browser)

直接运行该脚本确认项目正确:

python serve.py --root . # 启动时候设置 root 项目根目录路径 

这里就能测试运行就能跑起测试环境.

Nginx 配置

这里 Nginx 提交包部署的方法, 可以参考以下范本:

server {
        # HTTPS 配置
        listen       443 ssl;
        # 其他略
        index   index.html index.htm;
        root    /data/godot/h5;
        
        # 最主要访问配置
        location / {
            # 启用安全源访问
            add_header Access-Control-Allow-Origin *;
            add_header Cross-Origin-Resource-Policy same-origin;
            add_header Cross-Origin-Opener-Policy same-origin;
            add_header Cross-Origin-Embedder-Policy require-corp;
        }
}

这里就是常规的配置, 后续可以按照自己需要优化处理.

Cloudflare 配置

Cloudflare托管 Https 的时候推荐配置访问规则, 追加响应头:

  • Access-Control-Allow-Origin
  • Cross-Origin-Resource-Policy
  • Cross-Origin-Opener-Policy
  • Cross-Origin-Embedder-Policy

这里进域名配置界面设置就行:

cloudflare_1

cloudflare_2

cloudflare_3

同理需要把 wasm 一起加入头信息:

cloudflare_4

这里追加条件后响应的头信息都带上这几个头信息方便直接支持 sharedArrayBuffer, 新版本 Godot 提出了:

The issue is that during the development of Godot 4, we bet on the wrong horse: we went all-in with using threads with SharedArrayBuffers. We thought it was mainly a question of browser support (which took a step back due to the aforementioned security issues), so when all browsers finally shipped stable releases with SharedArrayBuffer, we streamlined everything around multi-threading.

Godot4 押宝 sharedArrayBuffer 但是这个特性导致网站请求强制必须是同源请求, 如果要唤起第三方支付会直接因为安全特性导致禁止且拉低了浏览器的兼容性.

这篇博客 的 Web 篇章值得一看, 里面提出选用到掉坑全过程