4

I'm new to Svelte and am trying to import pixi.js into my app. I've tried to import pixi.js into my svelte app following this post Svelte Mount DOM Element from Javascript

I've installed pixi via:

yarn add pixi.js --dev

However, when I try to import pixi.js I get a "ReferenceError: window is not defined" error. Here is a quick example:

<script>
    import * as PIXI from 'pixi.js'
    import { onMount } from 'svelte';
    let view;
    let app;
    onMount(() => {
        app = new PIXI.Application({
        view,
        // ...other props
    });
});

</script>
<canvas bind:this={view}/>

I read somewhere on reddit that I need to solve this using:

  onMount(async ()=>{       
       const PIXI = await import('pixi.js');
        app = new PIXI.Application({
        view,
        // ...other props
        });
    });

But that didn't work either. All is well when I use a global script tag, but I would rather use the import above. What am I doing wrong? Thanks!

**Edit: After some research I have learned that I need to approach this from a non-SSR perspective. https://sapper.svelte.dev/docs#Making_a_component_SSR_compatible

Here's what I tried:

<script>
  import { onMount } from "svelte";

  let MyComponent;
  onMount(async () => {
    const module = await import ('../components/pixi/mycomponent.svelte');
    MyComponent = module.default;
   });
</script>

<svelte:component this={MyComponent}/>

mycomponent.svelte:

<script>
   import * as PIXI from "pixi.js";
   import { onMount } from 'svelte';

   let view;
   let app;
     app = new PIXI.Application({
       view,
        width: 256,         // default: 800
         height: 256,        // default: 600
         antialias: true,    // default: false
         transparent: false, // default: false
         resolution: 1,      // default: 1
         backgroundColor: 0x090f15
       // ...other props
     });
</script>

<style>
 canvas {
    width: 100%;
    margin: 0 auto;
  }
</style>

<div class="content" bp="padding">
  <canvas bind:this={view} />
</div>

Now I'm getting:

TypeError: Failed to resolve module specifier "url". Relative references must start with either "/", "./", or "../".

Apparently pixi.js cannot be found? Is there something wrong with my rollup.config.js?

import resolve from 'rollup-plugin-node-resolve';
import replace from 'rollup-plugin-replace';
import commonjs from 'rollup-plugin-commonjs';
import svelte from 'rollup-plugin-svelte';
import postcss from 'rollup-plugin-postcss';
import babel from 'rollup-plugin-babel';
import { terser } from 'rollup-plugin-terser';
import config from 'sapper/config/rollup.js';
import pkg from './package.json';

const mode = process.env.NODE_ENV;
const dev = mode === 'development';
const legacy = !!process.env.SAPPER_LEGACY_BUILD;

const onwarn = (warning, onwarn) => (warning.code === 'CIRCULAR_DEPENDENCY' && /[/\\]@sapper[/\\]/.test(warning.message)) || onwarn(warning);
const dedupe = importee => importee === 'svelte' || importee.startsWith('svelte/');
const postcssOptions = () => ({
  extensions: ['.scss', '.sass'],
  extract: false,
  minimize: true,
  use: [
    ['sass', {
      includePaths: [
        './src/theme',
        './node_modules',
        // This is only needed because we're using a local module. :-/
        // Normally, you would not need this line.
        //path.resolve(__dirname, '..', 'node_modules')
      ]
    }]
  ]
});

export default {
  client: {
    input: config.client.input(),
    output: config.client.output(),
    plugins: [
      replace({
        'process.browser': true,
        'process.env.NODE_ENV': JSON.stringify(mode)
      }),
      svelte({
        dev,
        hydratable: true,
        emitCss: false,
        css: true
      }),
      resolve({
        browser: true,
        dedupe
      }),
      commonjs(),

      postcss(postcssOptions()),

      legacy && babel({
        extensions: ['.js', '.mjs', '.html', '.svelte'],
        runtimeHelpers: true,
        exclude: ['node_modules/@babel/**'],
        presets: [
          ['@babel/preset-env', {
            targets: '> 0.25%, not dead'
          }]
        ],
        plugins: [
          '@babel/plugin-syntax-dynamic-import',
          ['@babel/plugin-transform-runtime', {
            useESModules: true
          }]
        ]
      }),

      !dev && terser({
        module: true
      })
    ],

    onwarn,
  },

  server: {
    input: config.server.input(),
    output: config.server.output(),
    plugins: [
      replace({
        'process.browser': false,
        'process.env.NODE_ENV': JSON.stringify(mode)
      }),
      svelte({
        generate: 'ssr',
        dev
      }),
      resolve({
        dedupe
      }),
      commonjs(),

      postcss(postcssOptions())
    ],
    external: Object.keys(pkg.dependencies).concat(
      require('module').builtinModules || Object.keys(process.binding('natives'))
    ),

    onwarn,
  },

  serviceworker: {
    input: config.serviceworker.input(),
    output: config.serviceworker.output(),
    plugins: [
      resolve(),
      replace({
        'process.browser': true,
        'process.env.NODE_ENV': JSON.stringify(mode)
      }),
      commonjs(),
      !dev && terser()
    ],

    onwarn,
  }
};
TheKernel
  • 113
  • 1
  • 9

4 Answers4

4

Apparently I needed to:

preferBuiltins: false,

In my client resolve.

TheKernel
  • 113
  • 1
  • 9
0

I had the same issue above, but the provided answer did not solve my problem entirely.

The whole problem (for me):

My problem was two-fold. The heart of the issues does come down to SSR.

First, I had to set preferBuiltins: false and tweak the commonjs resource loader, similar to the answer given above.

Second, I was running polka@version:next (polka is Sapper's default microserver), which apparently was not stable/compatible in some regard. I don't know the exact incompatibility, but this intuitive fix solved my problem in the end. I simply changed my package.json and ran npm install. See below for exact details.

The whole solution (for me):

I had to make the following changes to rollup.config.js as well as package.json to fix the problem:

  1. I had to make 2 changes my rollup.config.js:
export default {
    client: {
        ...,
        plugins: [
            ...,
            resolve({
                ...
                preferBuiltins: false // ADD THIS
            }),
            commonjs({
              ...,
              namedExports: {
                "resource-loader": ["Resource"] // ADD THIS
              }
            })
        ],
        ...,
    },
    ...,
};

  1. In package.json, I had to change polka: 'next' -> polka: '^0.5.2 (latest version of polka).

Here is my final package.json:

{
  "name": "TODO",
  "description": "TODO",
  "version": "0.0.1",
  "scripts": {
    ...
  },
  "dependencies": {
    "polka": "^0.5.2", // THIS
    ...,
  },
  "devDependencies": {
    ...
  }
}

clockelliptic
  • 455
  • 4
  • 14
0

Currently my solutions is using dynamic import inside onMount.

<script>
  import {onMount} from 'svelte'

  onMount(async () => {
    const PIXI = await import('pixi.js')
    let type = "WebGL"
    if(!PIXI.utils.isWebGLSupported()){
      type = "canvas"
    }

    PIXI.utils.sayHello(type)
  })
</script>

"sapper": "^0.28.0"
"svelte": "^3.17.3"
"pixi.js": "^5.3.3"

0

In your rollup.config search for resolve

paste this there

resolve({
      preferBuiltins: false,
      browser: true,
      dedupe: ["svelte"],
    })
Rudrak Patra
  • 31
  • 1
  • 6