javascriptpixi.jsvitehot-module-replacement

How to use Vite HMR API with Pixi.js


I'm trying to use the Vite HMR API to create a Pixi.js app that hot reloads without resetting its state. The high-level idea:

I got update.js to hot update, but the app doesn't reflect the modified function:

// update.js
if (import.meta.hot) {
    import.meta.hot.accept()
}
export default function update(delta, state) {
    state.bunny.rotation += 0.1 * delta;
}

I think it's because Pixi is still using the old update():

// main.js
app.ticker.add((delta) => { update(delta, state) });

So I tried to accept updates in main.js when update.js was updated:

// main.js
import update from './update.js';

if (import.meta.hot) {
    import.meta.hot.accept('./update.js', (newUpdate) => {
    console.log('Update ticker here.');
  })
}

However this callback is not called when update.js is hot updated. Why is the callback not getting called?


I have tried some other things, like porting this Snowpack HMR example to Vite. I had problems/errors setting the module state (module.setState(import.meta.hot.data)), but I don't think I need to do this.


Solution

  • I think it's because Pixi is still using the old update():

    Your assumption is correct. Vite's job ends when the new module is imported and you get notified through the accept callback. You need to make sure that you don't keep internal references to the original module, since Vite is not able to intercept and replace those references.

    import { update } from './update';
    
    // create your PIXI app
    
    let updateFunction = update;
        
    app.ticker.add((delta) => {
      updateFunction(delta, state);
    });
    
    if (import.meta.hot) {
       import.meta.hot.accept('./update', (newModule) => {
         updateFunction = newModule.update;
       });
    }