浏览器运行环境¶
AI 搜索在浏览器本地执行,不需要后端接口。这个设计让 GitHub Pages 这种静态托管也能运行项目,但浏览器环境必须满足几个条件。
HTTP 服务¶
Web Worker、ES module、Wasm 和 Service Worker 都要求稳定的资源来源。file:// 不是正常站点来源,所以本地开发要使用 server.py 提供的 HTTP 地址。
输入是浏览器请求的静态文件。输出是页面、脚本、样式和 Wasm 模块。正常结果是浏览器控制台没有模块加载错误,AI 模式可以启动 Worker。
这里的“资源来源”可以理解成浏览器眼里的站点身份。http://127.0.0.1:8342/ 是一个明确站点,里面的 HTML、JS、CSS、Wasm 都来自同一个地址。file:// 只是本机文件路径,浏览器会对它使用更严格的限制。
本项目里的输入不是网络接口请求,而是静态文件请求。浏览器要拿到 index.html,再继续加载脚本、样式和 Wasm。只要其中一个路径错误,后续链路就会断开。
Web Worker¶
主线程负责界面。如果直接在主线程搜索 4 秒,棋盘动画和点击响应会卡住。项目把搜索交给多个 Worker,每个 Worker 只处理自己分到的根节点候选步。
正常结果是 AI 思考时页面仍然能刷新状态,右侧说明会显示当前 AI 正在搜索。
可以把主线程理解成“负责页面反应的线程”。按钮点击、棋子动画、统计表更新都在主线程上发生。Worker 是浏览器提供的后台线程,不能直接改 DOM,但可以做耗时计算。
本项目传给 Worker 的输入包括棋盘数组、当前行动方、这个 Worker 分到的合法步和时间预算。Worker 的输出是一个对象,里面有落子位置、分数、深度、节点数、耗时和 NPS。主线程只负责合并这些结果,不自己算棋。
跨源隔离¶
coi-serviceworker.js 会为同源资源补充 COOP 和 COEP 响应头。当前并行方式不依赖 Wasm pthread,但跨源隔离让静态托管环境更接近真实生产配置,也为以后使用 SharedArrayBuffer 留出空间。
如果 Service Worker 首次注册后刷新页面,这是正常现象。刷新后页面由 Service Worker 控制,资源响应头会带上跨源隔离相关字段。
Service Worker 可以理解成浏览器站点内部的一层代理。页面请求同源资源时,它有机会接管请求并补充响应头。GitHub Pages 不能直接配置自定义响应头,所以项目用这个方式让静态托管也能得到接近服务器配置的效果。
判断这一层是否正常,不需要记住所有响应头。实际检查方式是:页面第一次访问可能刷新;刷新后 AI 模式能启动;控制台没有关于跨源隔离、Worker 模块加载或 Wasm 初始化的错误。