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.jsversion: 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)
I have found a way to make this a little better, instead of using
selforwindowby itself, it might actually be better to useglobalThisbecause in a node environment, it is usually declared. I have started on a fix on my fork, and I will make a PR on thisI 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:
isMobileCall(self.navigator);Texture.EMPTYandTexture.WHITEcreation!!(self.XDomainRequest && !('withCredentials' in (new XMLHttpRequest())));var Url = self.URL || self.webkitURL;TextMetrics._canvas&TextMetrics._contextcreationCompressedTextureLoader.addThis 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.jstries 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 ofself,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