关于 pixijs-environments
面向 PixiJS 开发者的环境适配技能,介绍如何在浏览器、Web Worker 和自定义环境中替换 DOM 访问方式,并配置严格 CSP 环境。
主要功能
- 01通过 DOMAdapter 替换 DOM 访问
- 02在 Worker 中使用 OffscreenCanvas
- 03选择浏览器或 Worker 子路径导入
- 04配置自定义环境适配器
- 05在严格 CSP 下运行 PixiJS
适用场景
- 01将渲染移至 Web Worker
- 02为无头测试或 SSR 配置 PixiJS
- 03在禁止 unsafe-eval 的环境初始化渲染
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ pixijs/ pixijs-skills --skill pixijs-environments安装后在 Claude Code 中输入/pixijs-environments确认已加载。
详细介绍
DOMAdapter 封装了 PixiJS 进行的所有 DOM 访问(创建画布、加载 Image、fetch、解析 XML),因此该库可以在非浏览器环境中运行。请在 app.init() 之前调用 DOMAdapter.set(...),以切换到其他适配器。
快速开始
// worker.ts — OffscreenCanvas posted from main thread
DOMAdapter.set(WebWorkerAdapter);
self.onmessage = async (event) => {
const app = new Application();
await app.init({
canvas: event.data.canvas,
width: 800,
height: 600,
});
};
对于会阻止 unsafe-eval 的 CSP 环境,请在初始化任何渲染器之前导入 polyfill:
import "pixi.js/unsafe-eval";
相关技能: pixijs-application(标准浏览器初始化)、pixijs-migration-v8(移除设置、更改适配器)。
核心模式
使用 OffscreenCanvas 的 Web Worker
从主线程传输 OffscreenCanvas,然后在 worker 中初始化 PixiJS:
// main.ts
const canvas = document.createElement("canvas");
canvas.width = 800;
canvas.height = 600;
document.body.appendChild(canvas);
const offscreen = canvas.transferControlToOffscreen();
const worker = new Worker("worker.ts", { type: "module" });
worker.postMessage({ canvas: offscreen }, [offscreen]);
// worker.ts
import { Application, DOMAdapter, WebWorkerAdapter } from "pixi.js";
DOMAdapter.set(WebWorkerAdapter);
self.onmessage = async (event) => {
const app = new Application();
await app.init({
canvas: event.data.canvas,
width: 800,
height: 600,
});
};
必须在 new Application() 之前调用 DOMAdapter.set(WebWorkerAdapter)。WebWorkerAdapter 使用 OffscreenCanvas 代替 document.createElement('canvas'),并使用 @xmldom/xmldom 解析 XML。
以下功能在 Web Worker 中无法使用(因为无法访问 DOM):
DOMContainer— 没有可供叠加的真实 DOM 节点。AccessibilitySystem— 依赖实时 DOM 焦点和屏幕阅读器钩子。- 通过 Font Loading API 加载
FontFace— 请改用预先转换的位图字体(BitmapFont.install或.fnt资源)。
特定环境的子路径导入
除了导入 pixi.js,你也可以导入针对各环境精心整理的包:
import "pixi.js/browser"; // accessibility, dom, events, spritesheet, rendering, filters
import "pixi.js/webworker"; // spritesheet, rendering, filters (no DOM-only modules)
pixi.js/webworker 会刻意省略 accessibility、dom 和 events,因为它们需要 DOM。如果你希望以静态、同步的方式注册模块,而不是在渲染器初始化时依赖 loadEnvironmentExtensions 动态导入相应模块集,请使用这些子路径入口。
loadEnvironmentExtensions
import { loadEnvironmentExtensions } from "pixi.js";
await loadEnvironmentExtensions(false); // false = load defaults; true = skip
loadEnvironmentExtensions(skip) 取代了已弃用的 autoDetectEnvironment 辅助函数(自 8.1.6 起)。在引导自定义环境时,传入 true 可选择不自动加载默认浏览器扩展。autoDetectEnvironment(add) 仍作为转发至 loadEnvironmentExtensions(!add) 的兼容接口保留。
符合 CSP 的设置
PixiJS 内部使用 new Function() 编译着色器并同步 uniform。在会阻止 unsafe-eval 的内容安全策略环境中,请导入 polyfill:
import "pixi.js/unsafe-eval";
import { Application } from "pixi.js";
const app = new Application();
await app.init({ width: 800, height: 600 });
导入 pixi.js/unsafe-eval 会用静态 polyfill 替代基于 eval 的代码生成,用于着色器同步、UBO 同步、uniform 同步和粒子缓冲区更新。必须在初始化任何 PixiJS 渲染器之前导入。
命名说明: pixi.js/unsafe-eval 这个名称容易引起误解。它不会启用不安全的 eval,而是消除对它的需求。这个名称指的是它所绕过的 CSP 指令。
自定义适配器
对于非标准环境(Node.js、无头测试、SSR),请实现完整的 Adapter 接口:
import { DOMAdapter } from "pixi.js";
import type { Adapter } from "pixi.js";
import { createCanvas, Image } from "canvas";
import { DOMParser } from "@xmldom/xmldom";
const HeadlessAdapter: Adapter = {
createCanvas: (width, height) => createCanvas(width ?? 0, height ?? 0),
createImage: () => new Image(),
getCanvasRenderingContext2D: () => CanvasRenderingContext2D,
getWebGLRenderingContext: () => WebGLRenderingContext,
getNavigator: () => ({ userAgent: "HeadlessAdapter", gpu: null }),
getBaseUrl: () => "file://",
getFontFaceSet: () => null,
fetch: (url, options) => fetch(url, options),
parseXML: (xml) => new DOMParser().parseFromString(xml, "text/xml"),
};
DOMAdapter.set(HeadlessAdapter);
Adapter 接口要求实现以下方法:createCanvas、createImage、getCanvasRenderingContext2D、getWebGLRenderingContext、getNavigator、getBaseUrl、getFontFaceSet、fetch、parseXML。
检查当前适配器
import { DOMAdapter } from "pixi.js";
const adapter = DOMAdapter.get();
const canvas = adapter.createCanvas(256, 256);
const img = adapter.createImage();
DOMAdapter.get() 会返回当前设置的适配器。在与 PixiJS 相关的代码中进行 DOM 访问时,请使用它,而不要直接调用 document 或 Image。
常见错误
[CRITICAL] 未在 app.init() 前设置适配器
错误:
const app = new Application();
await app.init({ width: 800, height: 600 });
DOMAdapter.set(WebWorkerAdapter); // too late; adapter already read during init
正确:
DOMAdapter.set(WebWorkerAdapter);
const app = new Application();
await app.init({ width: 800, height: 600 });
在非浏览器环境中,必须在 app.init() 之前调用 DOMAdapter.set()。创建渲染器时,PixiJS 会在 app.init() 期间读取适配器。new Application() 本身只会创建 stage Container,不会读取适配器。
[HIGH] 直接使用 document 或 Image
错误:
const img = new Image();
img.src = "texture.png";
正确:
import { DOMAdapter } from "pixi.js";
const img = DOMAdapter.get().createImage();
img.src = "texture.png";
PixiJS 中的所有 DOM 访问都通过 DOMAdapter 进行。直接使用 document、Image 或其他浏览器全局对象,会破坏 Web Worker 和 SSR 兼容性。
[HIGH] CSP unsafe-eval 导入名称易引起误解
错误:
// CSP environment, omitting the import
import { Application } from "pixi.js";
// Throws: "Current environment does not allow unsafe-eval,
// please use pixi.js/unsafe-eval module to enable support."
正确:
import "pixi.js/unsafe-eval";
import { Application } from "pixi.js";
pixi.js/unsafe-eval 导入可避免在着色器编译中使用 eval() / new Function()。尽管名称让人以为它会启用不安全的 eval,但它的作用恰恰相反:它会安装静态 polyfill,使 PixiJS 能在严格的 CSP 下运行。
PixiJS 会在渲染器初始化时检测 CSP 是否阻止了相关操作,并抛出上述错误。在 PixiJS 报告错误之前,浏览器也可能记录自己的 CSP 违规信息;两者都指向同一个解决方法。
[HIGH] 使用旧版 settings.ADAPTER 模式
错误:
import { settings, WebWorkerAdapter } from "pixi.js";
settings.ADAPTER = WebWorkerAdapter;
正确:
import { DOMAdapter, WebWorkerAdapter } from "pixi.js";
DOMAdapter.set(WebWorkerAdapter);
settings 对象已在 v8 中移除。所有适配器配置都使用 DOMAdapter.set()。