pixijs: 'Self is not defined', SSR (Sveltekit)

I am using pixi.js in Sveltekit. Sveltekit is a flexible framework where you can do SSR, SSG, and SPAs (and mix).

Since pixi.js is a browser only library it gets into trouble with SSR.

What surprises me is that merely importing the module will crash it, even if nothing is instantiated. This forces you to use dynamic imports. It is an extra step which creates problems when using Typescript since you can’t import types without crashing everything (or at least I haven’t figured out how).

Is this something that is being worked on? Or is this fundamentally not possible to solve?

Related?

Totally random “ReferenceError: self is not defined” in “isMobile.ts” during tests “window is undefined” in nextjs

I created a new ticket since I’m not sure how/if these relate, and I wanted to contribute with a minimal reproducible example.

Expected Behavior

I expect it to be possible to import the module, but not being able to instantiate classes that depend on browser context.

Current Behavior

Just the act of importing pixi.js crashes in a non-browser environment, whether you do something with it or not.

Possible Solution

Don’t know really.

Maybe there are workarounds. I’m new to pixi.js.

Steps to Reproduce

npm init svelte@next my-app
cd my-app
nvm use 16
npm i
npm i pixi.js

and then import pixi.js in index.svelte

<script>
    import { onMount } from 'svelte'
    
    // 1. **********************
    // This does not work.
    // Even though the Application never is being instansiated. 
    // Just importing anything from 'pixi.js' will crash the app.
    // import { Application } from 'pixi.js'

    onMount(async () => {
        // 2. ****************
        // This do work, but creates unnecessary hassle, 
        // especially when you start using Typescript and want to be able to import types
        const { Application } = (await import('pixi.js'))
    })
</script>

<h1>Hello world</h1>

Environment

  • pixi.js version: 6.1.2
  • Browser & Version: NA
  • OS & Version: Ubuntu 18.04
  • Running Example:

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Reactions: 4
  • Comments: 19 (9 by maintainers)

Most upvoted comments

I have found a way to make this a little better, instead of using self or window by itself, it might actually be better to use globalThis because in a node environment, it is usually declared. I have started on a fix on my fork, and I will make a PR on this

I did a quick check importing pixi.js into Node.js directly, and there are only a handful of few places internally that will need to be fixed in order to not error on import. These are:

  • polyfills
  • settings: isMobileCall(self.navigator);
  • core : Texture.EMPTY and Texture.WHITE creation
  • loader useXdr : !!(self.XDomainRequest && !('withCredentials' in (new XMLHttpRequest())));
  • loader : var Url = self.URL || self.webkitURL;
  • text : TextMetrics._canvas & TextMetrics._context creation
  • compressed-textures : CompressedTextureLoader.add

This is a very solvable problem, if we don’t statically do these things.

PRs welcome to fix, this is not a high priority for the project but if anyone here wants to champion this, I’m sure other folks would find it useful.

I’ll add another +1 for interest in getting this patched correctly in this repository.

That said, I went ahead and put together a shim that stubs out everything pixi.js tries to do when you import it. As long as the shim gets imported before any Pixi dependencies, everything works (with just a few usage limitations, see the READMEs). Note that this kind of solution is brittle since it depends on the packaging/bundling to not reorder a Pixi dependency ahead of the shim, and at least for SvelteKit this seems like it’s under active development. Having the use of self, window, document.createElement,canvas.getContext(), etc. made conditional in this library would be much better.

edit: Just to be clear regarding the discussion up-thread, this lets SSR processing import Pixi without blowing up - it doesn’t let you actually use Pixi to render graphics on the server.

npm library: @mszu/pixi-ssr-shim example SvelteKit app: https://github.com/mszu/svelte-kit-pixi-sample

Hope this helps!

It will never work with static imports since pixijs is tightly coupled to the browser env.

Use a dynamic import inside onMount to load pixijs or a dynamically imported component that wraps pixijs to enforce pixijs to stay away from SSR.

https://svelte.dev/repl/16b375da9b39417dae837b5006799cb4?version=3.25.0