pixijs / pixi-react

Write PIXI apps using React declarative style
https://pixijs.io/pixi-react/
MIT License
2.33k stars 177 forks source link

pixi build size with webpack #307

Closed AdrienLemaire closed 3 years ago

AdrienLemaire commented 3 years ago

Description

tldr: react-pixi imports all the pixi.js code, which is not friendly to code split chunking tools. Please consider improving this issue.

I've noticed that the webpack chunk containing the pixi code is by far the largest in my codebase at a whooping 630.54 KB when gzipped.

The same core.js file seems to be duplicated 10 times.

When checking other posts, I understand that installing @pixi should take ~316kb, and that installing only the @pixi libs we need can decrease the build size significantly.

My webpack config has this alias:

  resolve: {
    alias: {
      // Check ./pixi.js for canvas fallback
      "pixi.js": path.resolve(__dirname, "./pixi.js"),
      "pixi.js-stable": path.resolve(__dirname, "./node_modules/pixi.js"),
    },
  },

And my pixi.js file:

// Support canvas fallback for browsers with WebGL disabled
// From https://github.com/inlet/react-pixi/issues/126#issuecomment-514184770
export * from "pixi.js-stable";
export * from "pixi.js-legacy";

I'd like to find ways to optimize this setup (and make it public knowledge to the react-pixi community.

What suggestions do you have ?

Steps to reproduce

  1. Set up a react-pixi project with webpack 5
  2. Add the webpack BundleAnalyzerPlugin
  3. build

Additional info

inlet commented 3 years ago

In react-pixi we don’t do import * from 'pixi.js' but only import what’s needed.

Also regarding using legacy pixi, you only have to install pixi-legacy and import your components with import { Stage } from '@inlet/react-pixi/legacy', see https://reactpixi.org/pixi-legacy

React-pixi uses Pixi as a peer dependency.

Hope this helps! Please let me know if I can be of any help

inlet commented 3 years ago

Btw, pixi legacy already does auto detect Webgl support out of the box

AdrienLemaire commented 3 years ago

@inlet your code in useApp shows:

import { Application } from 'pixi.js'

If you import from pixi.js instead of @pixi/app, I believe the pixi.js file is loaded, and the following requires are executed:

require('@pixi/polyfill');
var utils = require('@pixi/utils');
var accessibility = require('@pixi/accessibility');
var interaction = require('@pixi/interaction');
var app = require('@pixi/app');
var core = require('@pixi/core');
var extract = require('@pixi/extract');
var loaders = require('@pixi/loaders');
var compressedTextures = require('@pixi/compressed-textures');
var particles = require('@pixi/particles');
var prepare = require('@pixi/prepare');
var spritesheet = require('@pixi/spritesheet');
var spriteTiling = require('@pixi/sprite-tiling');
var textBitmap = require('@pixi/text-bitmap');
var ticker = require('@pixi/ticker');
var filterAlpha = require('@pixi/filter-alpha');
var filterBlur = require('@pixi/filter-blur');
var filterColorMatrix = require('@pixi/filter-color-matrix');
var filterDisplacement = require('@pixi/filter-displacement');
var filterFxaa = require('@pixi/filter-fxaa');
var filterNoise = require('@pixi/filter-noise');
require('@pixi/mixin-cache-as-bitmap');
require('@pixi/mixin-get-child-by-name');
require('@pixi/mixin-get-global-position');
var constants = require('@pixi/constants');
var display = require('@pixi/display');
var graphics = require('@pixi/graphics');
var math = require('@pixi/math');
var mesh = require('@pixi/mesh');
var meshExtras = require('@pixi/mesh-extras');
var runner = require('@pixi/runner');
var sprite = require('@pixi/sprite');
var spriteAnimated = require('@pixi/sprite-animated');
var text = require('@pixi/text');
var settings = require('@pixi/settings');

This will bundle all these packages in a single chunk, when all we needed was @pixi/app.

inlet commented 3 years ago

Right, thanks! We could optimize this better indeed.

Although this will probably break the legacy support like we have now.

inlet commented 3 years ago

When initiating a <Stage> a PIXI.Application will be created and you’ll need all the things (interaction, loaders, ..)

I believe importing directly from pixi.js isn’t a bad thing after all

See https://github.com/pixijs/pixijs/blob/dev/bundles/pixi.js/src/index.ts

AdrienLemaire commented 3 years ago

According to this article, the minimum required would be:

npm i @pixi/app
npm i @pixi/core
npm i @pixi/loaders
npm i @pixi/sprite
npm i @pixi/ticker

Interaction doesn't seem mandatory, and I actually don't use it myself (using react-use-gesture instead). I understand that this is not a trivial change for @inlet/react-pixi.

inlet commented 3 years ago

Yes we do need interaction, I.e all display events are controlled with the interaction manager. I believe it’s not that simple, if we want to provide a solution that fits all needs we need to stick to the implementation we have. (importing from pixi.js).

Although I do understand that in your situation it would be nicer if it doesn’t bundle other (unused) pixi modules.

inlet commented 3 years ago

I’ll close this issue for now, please let me know if you have a solution to this problem without compromising used features, thanks!