Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Phaser doesn't work with Webpack and require #1974

Closed
mkristo opened this issue Aug 3, 2015 · 39 comments
Closed

Phaser doesn't work with Webpack and require #1974

mkristo opened this issue Aug 3, 2015 · 39 comments

Comments

@mkristo
Copy link
Contributor

mkristo commented Aug 3, 2015

Earlier I made an (ugly) pull request #1923 that made Phaser work with Webpack, but since 7a6de81 I'm sorry to say that this doesn't work anymore.

I'm getting

Uncaught ReferenceError: PIXI is not defined

from https://github.com/photonstorm/phaser/blob/6139071ebc918ddd8a1201279ebc7c70e645de8e/src/Phaser.js#L357

For repro you can use the Webpack boilerplate found here #1924

@photonstorm
Copy link
Collaborator

Yes the way it was previously bundled was completely wrong - PIXI should never have been inside the Phaser UMD, so it's now properly split out. The grunt custom build task has a new flag --split true which will generate Phaser, Pixi, P2 and Creature to their own stand-alone build files, each with the wrappers they need. So you can now bundle them together however you want. As long as they're allowed to exist globally they will be much happier. PIXI needs to come before Phaser in any requirement chain.

@mkristo
Copy link
Contributor Author

mkristo commented Aug 3, 2015

I understand now. Yes, this makes much more sense.

But when installing Phaser 2.4.2 via npm it seems like PIXI is still bundled with (at least) the no-physics build. I think it would be desirable to provide the split up modules as well.

Also, we should probably update the Webpack boilerplate to require both PIXI and Phaser. I'd be happy to do this, but the PIXI module needs to be available before this is done.

@the-simian
Copy link

FYI, I can currently get Phaser to build by doing this:

global.PIXI = require('pixi.js');
global.p2 = require('p2');
global.Phaser = require('phaser');

In this case, PIXI is set to version

"pixi.js": "2.2.x",

I will add, though that this no longer works in 2.4.3. because the CanvasPool mixin is not defined on PIXI. If you require the CanvasPool file in between PIXI and Phaser, of course, it mixies in correctly, and works.

I'm aware that this involves setting some globals, which isn't ideal- but ti does allow you to use npm to serve all the modules.

I'm going to update my slush generator with these changes as soon as 2.4.3 is on master

@photonstorm
Copy link
Collaborator

Just to say that I've got a guide to setting up Phaser with Webpack which I'll publish shortly.

I'd just like to add one thing though: don't ever use any version of Pixi that you find in npm with Phaser, as it won't work. You have to use the version we've built specifically or so much will break.

p2 on the other hand should be safe to pull in from npm instead of the build included with Phaser as long as you use the exact same version that Phaser bundles with it, any deviation from that is highly likely to break it.

@the-simian
Copy link

I noticed that the mixins you were using with PIXI were located in the utils directory. My question is, could we still use the npm version, as long as we mix in all the addons (like the CanvasPool). Are you actually changing the source code itself, currently - or are you modifying PIXI entirely by adding new properties?

If you're doing the latter, it could be possible to still use the npm PIXI and then just require a file you provide in the source that then mixes in all your modifications to PIXI. Of course, the same rules apply - you have to match the right version. I know PIXI is well into v3, but you are (last I checked) locking pixi on v 2.2.8. This could be useful because that way you'd really only have to maintain the parts that deviate from pixi.js source. So to be clear, I am imagining that you could require pixi with npm, and then require a file that basically requires all the addons in the right order, and just plug all the functionality you need right in. You would have the latitude to update or replace existing methods if you needed to. If I knew more specifically the parts that deviate from PIXI I would be happy submit a PR that basically works this way.

If I'm way off, and this wouldn't work in your opinion, I'd like to know more. Any amount you can elaborate on what's different about this PIXI from the core pixi (of the same version) I'd love to know.

In the meantime, is the most correct file to include from the Phaser source for PIXI currently

src/pixi/Pixi.js

right? You'd still need the CanvasPool and stuff like that afterwards, I would assume.

Thank you for taking time to respond to all these issues, I really appreciate the work you're putting in on Phaser!

@photonstorm
Copy link
Collaborator

The PIXI source in the Phaser repo is vastly different to the last published version of Pixi 2. We've added and fixed so much that isn't in the official repo it's not even close any more.

@photonstorm
Copy link
Collaborator

Here's how to use Phaser with Webpack:

  1. You have to use a custom build of Phaser. You cannot use one of the builds from the dist folder. Here is the grunt custom task I used:

grunt custom --exclude p2,creature,ninja --split true

This will create phaser.js and pixi.js files in the dist folder. Copy those over to your project folder.

  1. In Webpack you need to install the script-loader:

npm install script-loader --save-dev

  1. In your webpack.config.js flag Phaser and Pixi to use the script loader. There are various ways of doing this, but I used this approach:
module.exports = {

    entry: "./src/entry.js",

    output: {
        path: __dirname,
        filename: "bundle.js"
    },

    module: {
        loaders: [
            { test: /pixi.js/, loader: "script" },
            { test: /phaser.js/, loader: "script" }
        ]
    }

};
  1. In my entry.js I just have this:
require('../lib/pixi.js');
require('../lib/phaser.js');
require('./main.js');

main.js contains my test game, which is just a basic Phaser example.

  1. Then build it.

Using the split Phaser / PIXI libs and the Webpack script loader I was able to bundle my game up quite happily without any changes to the core Phaser source.

@the-simian
Copy link

Thank you for responding so quickly!

I will try this out as soon as possible

@lslima91
Copy link

I'm getting the error Phaser.game is not a function,

@photonstorm
Copy link
Collaborator

Check you followed the instructions above exactly as written. If it still doesn't work post your project structure and conf file up.

@lslima91
Copy link

Ok I got it now it works after cleaning my project folder. I didn't bother to check what script loader does..

@mkristo
Copy link
Contributor Author

mkristo commented Sep 2, 2015

I'm happy with the solution provided above.

@photonstorm: Should I close the issue, or do you want it to be open?

@photonstorm
Copy link
Collaborator

I'll leave it for now until I've moved the above instructions somewhere more public.

@webcaetano
Copy link

I had the same problem days ago. With Webpack + Bower.
To be able to use commonJS-style i did this simple config

var webpackConfig = {
    // ...
    externals: {
        "phaser": "Phaser"
    }
    // ...
};

and then

var phaser = require('phaser');

In my opnion. The bower should keep the main like that, but still export all submodules sources.
To easly make custom builds from bower overrides.

Or like lodash, exporting allsubmodules in npm. E.g. : https://www.npmjs.com/package/lodash.shuffle

Currently, the only way to do custom build is from grunt

@seand88
Copy link

seand88 commented Dec 4, 2015

could we get a more full set of instructions for this in a public place?

@amowu
Copy link

amowu commented Dec 6, 2015

I try to write a shim module for ES6 and webpack..
https://github.com/amowu/phaser-shim

@kinday
Copy link

kinday commented Dec 6, 2015

Thanks, @amowu! It works!

@webcaetano
Copy link

@amowu nice.
You guys also may like my phaserjs boilerplate.
It's ES6+Gulp+Webpack

Phaser also are called by require(); And stats.js too.

@amowu
Copy link

amowu commented Dec 7, 2015

@webcaetano 👍

@dlindenkreuz
Copy link

@photonstorm using script-loader prevents minification because the module is loaded as a string and then evaluated (see webpack-contrib/script-loader#1).

i used following webpack config to load pixi with imports-loader, then directly provided as PIXI variable to phaser. files in lib/are built using @photonstorm's method described above #1974 (comment). no probs with minification during build.

{
  resolve: {
    alias: {
      "pixi": path.join(__dirname, "lib/pixi.js"),
      "phaser": path.join(__dirname, "lib/phaser.js")
    }
  },
  module: {
    loaders: [
      {test: /phaser\.js$/, include: path.join(__dirname, 'lib'), loader: 'imports?PIXI=pixi'},
    ]
  }
}

no need to require pixi in my code files:

var Phaser = require("phaser");
// ES6
import Phaser from "phaser"

@smr-el
Copy link
Contributor

smr-el commented Jan 8, 2016

None of these are solutions, just leaking bandages. Phaser must evolve accordingly to maintain relevance in an ES6 world. If jQuery can do it, so can Phaser.

@hayesmaker
Copy link

^^

@tjpalmer
Copy link

Yes, the following should just work: npm install --save phaser followed by import Phaser from "phaser". I've used many other libs this way, and anything else isn't good enough.

@crisu83
Copy link

crisu83 commented Feb 9, 2016

Thanks @dlindenkreuz, your solution worked perfectly for me.

@photonstorm
Copy link
Collaborator

None of these are solutions, just leaking bandages. Phaser must evolve accordingly to maintain relevance in an ES6 world. If jQuery can do it, so can Phaser.

That is what Lazer is for. I have no intention of ever making that change to Phaser, it's too close to end-of-life to be worth the effort.

Given 2.4.5 now has a webpack build option built in, and the README updated to reflect that I'm going to close this issue off now.

@pk-nb
Copy link

pk-nb commented Feb 21, 2016

Taking @dlindenkreuz's approach a different direction—you can also expose the files from node_modules in Phaser 2.4.5+ so you don't have to make a custom build and still get minification. Unfortunately all the files have to be global due to a circular reference (Phaser file pulls PIXI global var, and pixi.js references Phaser from a function). The expose-loader works well here (I could not get the ProvidePlugin to work).

npm install --save phaser expose-loader
var path = require('path');

// Phaser webpack config
var phaserModule = path.join(__dirname, '/node_modules/phaser/');
var phaser = path.join(phaserModule, 'build/custom/phaser-split.js');
var pixi = path.join(phaserModule, 'build/custom/pixi.js');
var p2 = path.join(phaserModule, 'build/custom/p2.js');

module.exports = {
  ...
  module: {
    loaders: [
      { test: /pixi\.js/, loader: 'expose?PIXI' },
      { test: /phaser-split\.js$/, loader: 'expose?Phaser' },
      { test: /p2\.js/, loader: 'expose?p2' },
      ...
    ]
  },
  resolve: {
    alias: {
      'phaser': phaser,
      'pixi': pixi,
      'p2': p2,
    }
  }
};

Then in your entry file:

// commonjs
require('pixi');
require('p2');
require('phaser');

// or es2015
import 'pixi';
import 'p2';
import "phaser";

This is similar to making it an webpack external, but at least webpack can bundle it together and minify it now.

Flet added a commit to Flet/phaser-es6-webpack that referenced this issue Apr 15, 2016
@supermrji
Copy link

supermrji commented Aug 22, 2016

npm install --save phaser expose-loader
var path = require('path');

// Phaser webpack config
var phaserModule = path.join(__dirname, '/node_modules/phaser/');
var phaser = path.join(phaserModule, 'build/custom/phaser-split.js');
var pixi = path.join(phaserModule, 'build/custom/pixi.js');
var p2 = path.join(phaserModule, 'build/custom/p2.js');
module.exports = {
  ...
  module: {
    loaders: [
      { test: /pixi\.js/, loader: 'expose?PIXI' },
      { test: /phaser-split\.js$/, loader: 'expose?Phaser' },
      { test: /p2\.js/, loader: 'expose?p2' },
      ...
    ]
  },
  resolve: {
    alias: {
      'phaser': phaser,
      'pixi': pixi,
      'p2': p2,
    }
  }
};

// main.js
import 'pixi';
import 'p2';
import "phaser";

Hi there,
it makes a alot of comment with author (look at http://imgur.com/a/WamqO mini map yellow comment),
does any one know this problem ?

@dlindenkreuz
Copy link

@supermrji these comment blocks contain @license and are not removed by uglifyjs. you can pass a config object to webpack.optimize.UglifyJsPlugin with comments: false, this should remove all comments.

@donaldpipowitch
Copy link

It would be nice, if phaser could be used without specific configuration for webpack. I often share a generic webpack configuration between multiple projects and it would ease development.

@dmassiani
Copy link

dmassiani commented Sep 9, 2016

I use Phaser from npm and nom I would adding Box2D Plugin but I have many errors from "goog" and goog.global.CLOSURE_UNCOMPILED_DEFINES

var path = require('path')
var webpack = require('webpack')
var BrowserSyncPlugin = require('browser-sync-webpack-plugin')

// Phaser webpack config
var phaserModule = path.join(__dirname, '/node_modules/phaser/')
var phaser = path.join(phaserModule, 'build/custom/phaser-split.js')
var pixi = path.join(phaserModule, 'build/custom/pixi.js')
var p2 = path.join(phaserModule, 'build/custom/p2.js')
var box2D = path.join(__dirname, '/src/libs/box2d-plugin-full.js')

var definePlugin = new webpack.DefinePlugin({
  __DEV__: JSON.stringify(JSON.parse(process.env.BUILD_DEV || 'true'))
})

module.exports = {
  entry: {
    app: [
      'babel-polyfill',
      path.resolve(__dirname, 'src/main.js')
    ]
  },
  devtool: 'source-map',
  output: {
    pathinfo: true,
    path: path.resolve(__dirname, 'dist'),
    publicPath: './dist/',
    filename: 'bundle.js'
  },
  watch: true,
  plugins: [
    definePlugin,
    new BrowserSyncPlugin({
      host: process.env.IP || 'localhost',
      port: process.env.PORT || 3000,
      open: false,
      server: {
        baseDir: ['./', './build']
      }
    })
  ],
  module: {
    loaders: [
      { test: /\.js$/, loader: 'babel', include: path.join(__dirname, 'src') },
      { test: /pixi\.js/, loader: 'expose?PIXI' },
      { test: /phaser-split\.js$/, loader: 'expose?Phaser' },
      { test: /p2\.js/, loader: 'expose?p2' }
    ]
  },
  node: {
    fs: 'empty'
  },
  resolve: {
    alias: {
      'phaser': phaser,
      'pixi': pixi,
      'p2': p2,
      'box2D': box2D
    }
  }
}

Can you help me please?

insert-username added a commit to insert-username/lights-out-dont-bite that referenced this issue Oct 2, 2016
@YuraBaev
Copy link

YuraBaev commented Dec 9, 2016

  test: box2d,
  loader: 'imports?this=>window'

@ElegantSudo
Copy link

ElegantSudo commented Dec 12, 2016

@photonstorm any plans on making phaser more native to ES6? I know you said that you're not planning on doing this, but I'm asking because it's often the case that plans change from year to year. This is a convenience I and the community would really love to have. Thanks in advance, I really appreciate the work you do.

@photonstorm
Copy link
Collaborator

@ElegantSudo the issue here (in this thread) isn't to do with not being ES6, it's to do with Phaser being one giant global single var, with no module capability at all, with dependencies to other global based libs. Which makes it a pain to ingest in a module based workflow. Which is why Phaser 3 is fully modular, and itself built with webpack2. The code is still ES5, the module format CJS, but it should make threads like this a thing of the past. ES6 will follow, but first the module based version needs completing. One leads to the other.

@ElegantSudo
Copy link

@photonstorm ah, that's what I meant (albeit, didn't communicate correctly). Thanks, and on that note, I'm really looking forward to Phaser 3!

@johnborges
Copy link

@pk-nb Thanks! expose-loader solution is what I'll work with for now. Looking forward to Phaser 3.

@josfaber
Copy link

I got it working alrite, but the bundle is a whopping 3.9mb. Has anyone managed to create a webpack config and/or 'require scheme' that can separate phaser into chunks for preloading purpose?

@photonstorm
Copy link
Collaborator

Not sure if you're talking about Phaser 2 or 3, but it sounds too large in either case unless it's including the source map and comments, in which case it sounds about right. Exclude those and it should be significantly smaller. In Phaser 2 you cannot separate the modules out on their own, in V3 you can.

@umeboshi2
Copy link

@josfaber Yes. I have been able too keep it chunked in a view. I'm using expose loader as mentioned above, and require.ensure: https://github.com/umeboshi2/infidel/blob/2f23c9a978f6bf0c619f6095439c12ee3bc0b1b8/client/applets/phaserdemo/controller.coffee#L9

@josfaber
Copy link

josfaber commented Nov 4, 2017

Thanks for your replies. I managed to get phaser into a separate bundle, which compresses to 800kb when compiling for production. That will thus be browser-cached inbetween the various pages I'll use it in. I can live with that :)

# webpack.config.js

var path = require("path");
var webpack = require('webpack');

var WebpackUtilsPlugin = require('./plugins/webpackutilsplugin');

// Phaser webpack config
var phaserModule = path.join(__dirname, '/node_modules/phaser-ce/')
var phaser = path.join(phaserModule, 'build/custom/phaser-split.js')
var pixi = path.join(phaserModule, 'build/custom/pixi.js')
var p2 = path.join(phaserModule, 'build/custom/p2.js')

function isExternal(module) {
  var context = module.context;
  if (typeof context !== 'string') {
    return false;
  }
  console.log(context);
  return context.indexOf('node_modules') !== -1;
}

module.exports = {

    entry: {
      "main": "./app/main.js",
      "challenge1": "./app/challenge1/main.js",
      "challenge2": "./app/challenge2/main.js",
    },

    output: {
        path: path.join(__dirname, "web/js"),
        filename: '[name].bundle.js',
        // chunkFilename: '[id].chunk.js'
    },

    plugins: [
      new webpack.optimize.CommonsChunkPlugin({
        name: "vendor",
        filename: 'phaser.bundle.js',
        minChunks: function(module, count) {
          return module.resource && /phaser|pixi|p2/.test(module.resource) && count >= 1
        },
      })
    ],

    module: {
        rules: [
          { test: /pixi\.js/, use: ['expose-loader?PIXI'] },
          { test: /phaser-split\.js$/, use: ['expose-loader?Phaser'] },
          { test: /p2\.js/, use: ['expose-loader?p2'] },
          {
            'test': /\.js$/,
            'loader': 'babel-loader',
            'exclude': /node_modules/,
            'query': {
              'presets': ['env']
            }
          },
        ]
    },

    node: {
      fs: 'empty',
      net: 'empty',
      tls: 'empty'
    },

    resolve: {
      alias: {
        'phaser': phaser,
        'pixi': pixi,
        'p2': p2
      }
    },

    watch: true
};

juliendasilva pushed a commit to juliendasilva/Fun-Lympic that referenced this issue Mar 26, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests