mcpField
P
pixijs-environments

pixijs-environments

github.com/pixijs开发3585.7k 次安装4 周前更新
代码仓库

关于 pixijs-environments

面向 PixiJS 开发者的环境适配技能,介绍如何在浏览器、Web Worker 和自定义环境中替换 DOM 访问方式,并配置严格 CSP 环境。

主要功能

  1. 01通过 DOMAdapter 替换 DOM 访问
  2. 02在 Worker 中使用 OffscreenCanvas
  3. 03选择浏览器或 Worker 子路径导入
  4. 04配置自定义环境适配器
  5. 05在严格 CSP 下运行 PixiJS

适用场景

  1. 01将渲染移至 Web Worker
  2. 02为无头测试或 SSR 配置 PixiJS
  3. 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()。

API 参考

评论

支持 Markdown