phaserjs / phaser

Phaser is a fun, free and fast 2D game framework for making HTML5 games for desktop and mobile web browsers, supporting Canvas and WebGL rendering.
https://phaser.io
MIT License
36.94k stars 7.08k forks source link

require('phaser') with Browserify throws error: Error: Cannot find module './Scalar' #1186

Closed totty90 closed 9 years ago

totty90 commented 10 years ago

I've also got these errors:

photonstorm commented 10 years ago

Can you test something for me please - see if the build of Phaser that doesn't include P2 errors as well? You'll find it in the build/custom folder.

david0178418 commented 10 years ago

I gave this a run with both phaser-no-physics.js and phaser-no-libs.js. While I no longer got the "Scalar" error, I now

Cannot find module 'nw.gui'...
david0178418 commented 10 years ago

Looks like a limitation of browserify. It seems to be addressed here:

https://github.com/substack/node-browserify/issues/653

woutercommandeur commented 10 years ago

What I currently do is atomatically copy phaser.min.js to my game folder using a grunt task. And then use a browserify shim to point 'Phaser' to that file. It will work then and browserify won't complain. But it's a workaround.

A possible solution for the nw.gui test would be to try: require.resolve('nw.gui'); and catch the error as it is done now. That could fix the problem. Resolve only checks the path for the module and returns it if the module is available but doesn't load the module, and thus browserify won't have to load it.

photonstorm commented 10 years ago

I don't use browserify, so if anyone wants to try this fix out and see if it works, then I'll happily merge it if it does.

woutercommandeur commented 10 years ago

the require.resolve('nw.gui') works. And it builds fine with browserify. But without referencing the minified file it will complain PIXI is not found when it overrides the interactionmanager.

jrunestone commented 9 years ago

I'm trying to include phaser in my project with browserify as well, but I'm confused to say the least. Did this ever work? Why doesn't it work anymore? (I can see some module.exports stuff in the phaser src). Is the only way to include phaser right now by manually including it into the global scope?

david0178418 commented 9 years ago

I'm sure there are several workarounds that could be done with effort that could be more wisely spent working on the actual fix.

If you're purpose is just to get going, then global is your best bet. To make it work seamlessly when I or anyone else get the time to fix this, I'm also including another proxy file named "phaser.js" containing this:

// TODO find fix for this hack
module.exports = window.Phaser;

That way, I can still do var Phaser = require('phaser'); in my code. Whenever the fix comes around, I'll just remove the script tag and the matching hack file.

jrunestone commented 9 years ago

Ok thanks that sounds like a good solution for now.

woutercommandeur commented 9 years ago

I use a copy, command in my Gruntfile.js that copies the phaser lib to my game lib:

    copy: {
      phaser: {
       files: [
         { expand: false, flatten: true, src: ['node_modules/phaser/dist/phaser-arcade-physics.min.js'], dest: 'src/client/game/phaser-arcade-physics.min.js' }
      ]
      },
}

And then in my package.json:

  "browser": {
    "Phaser": "./src/client/game/phaser-arcade-physics.min.js"
  },
  "browserify-shim": {
    "Phaser": {
      "exports": "Phaser"
    }
  }

After that

var Phaser = require('Phaser');

then works fine, but it's a hack :)

Rainbowlemon commented 9 years ago

Just started trying to use Phaser and have run into this bug. Is there perhaps an early version of Phaser I could use that doesn't have this issue?

herreraemanuel commented 9 years ago

The solution from @woutercommandeur is working for me. The only modification is using bower and avoid moving the file. I just point to the bower_components directory

"browser": {
    "phaser": "./bower_components/phaser/build/custom/phaser-arcade-physics.js"
},

PD: Sorry for my English

Rainbowlemon commented 9 years ago

Cheers, but this still doesn't work - I'm getting an error "Cannot find module 'nw.gui'". I'd try that require.resolve thing mentioned above, but I've no idea where to put that :-/

woutercommandeur commented 9 years ago

@Rainbowlemon You need to reference the .min.js file and make sure it is copied to your project folder (and referenced from there). Otherwise you will get the nw.gui error or other errors.

nesheroj commented 9 years ago

webpack seems to have issues bundling Phaser too, given the errors it's probably related.

phaser phaser2

robinduckett commented 9 years ago

Can confirm, want to use browserify and Phaser but seems like it's tough luck?

Edit:

Workaround I've found

browserify: {
    libs: {
        options: {
            exclude: ['nw.gui']
        },
        files: {
            'static/js/main.js': ['./src/client/**/*.js']
        }
    }
}
nesheroj commented 9 years ago

Followup on my last comment which I know may be offtopic and warrant another issue to be created. Seems that the way the phaser libs are built collide with webpack. I managed to workaround this using the script loader. Not ideal, but works for now.

    resolve: {
        alias: {
            "phaser": path.join(__dirname, "node_modules/phaser/dist/phaser-arcade-physics.js"),
            "phaser-debug": path.join(__dirname, "node_modules/phaser-debug/dist/phaser-debug.js")
        },
    },
    module: {
        loaders: [
            { test: /(phaser-arcade-physics|phaser-debug)\.js$/i, loader: 'script' },
        ]
    },

Full sample config Hope this helps anyone facing this problem

photonstorm commented 9 years ago

What's webpack?

clark-stevenson commented 9 years ago

Man the list of package managers or build tools is crazy.

nesheroj commented 9 years ago

@photonstorm I linked it above. It kinda replaces grunt/gulp, browserify and some other tools (and that's an understatement). webpack sorry for derailing this conversation, the error seemed related.

photonstorm commented 9 years ago

Oh hell, another one?! It's times like this I wish all package managers would just die out leaving one dominant one left.

HongPong commented 9 years ago

Experimenting with browserify, I discovered that the arcade version 2.0.6 works well, in this boilerplate project via @lukewilde it browserifies correctly and I got that to work in a related project. https://github.com/lukewilde/phaser-js-boilerplate/blob/master/src/js/lib/phaser.arcade.js When I used the default build from here: v2.1.3 "Ravinda" - Built: Thu Oct 23 2014 16:02:23 https://raw.githubusercontent.com/photonstorm/phaser/master/build/phaser.js Then I encountered horrible puzzling errors in FFox/Chrome: Error: Cannot find module '__browserify_process'

Traces in Chrome: Uncaught Error: Cannot find module '__browserify_process' _prelude.js:1s _prelude.js:1(anonymous function) _prelude.js:1../package.json phaser.js:75021s phaser.js:64969e phaser.js:64969(anonymous function) phaser.js:64969a phaser.js:64969browserifyShim phaser.js:64969(anonymous function) phaser.js:83583JkpR2F phaser.js:83585s _prelude.js:1(anonymous function) _prelude.js:1./properties app.js:1s _prelude.js:1e _prelude.js:1(anonymous function)

If I were to guess, the P2 stuff found below lines 62000 has a different looking module export statement at the front of it than the ones for Pixi and Phaser. Since the Pixi & Phaser in 2.0.6 arcade build are working ok, perhaps matching P2's export statement to them would work.

I think my error may have come via 66866, or a similar statement. Maybe the require statements on __browserify_process are somehow malformed to what browserify is expecting:

},{}],3:[function(require,module,exports){ var process=require("__browserify_process"),global=typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {},Buffer=require("__browserify_Buffer"),__filename="/..\\node_modules\\poly-decomp\\src\\Line.js",__dirname="/..\\node_modules\\poly-decomp\\src";var Scalar = require('./Scalar');

Daniel1984 commented 9 years ago

Well, lets hope for the best in new release I guess

sompylasar commented 9 years ago

@photonstorm Sorry for off-topic, but webpack is browserify-compatible and it allows much more than browserify: different module styles, async loading and livereload even in production out of the box, semi-automatic code splitting into chunks that load separately, many loaders for different web resources (you can require an image or a stylesheet) and more. Please take a look at it, it is very promising and works well.

clark-stevenson commented 9 years ago

@sompylasar sorry for off topic again! Browserify + webpack is new to me.

What I am thinking here, is that these tools are superfluous? Just on the grounds that Phaser works as expected. This ticket is saying that the resource managers being used are not compatible with Phaser or vice versa. (But close your eyes and throw a dart at any JS lib, it cannot just be phaser with these issues?).

It seems any problem which these tools claim to solve are just creating more problems, and soon there will be "AnotherXName" project which claims to be better solving these problems... Just like the Browserify > WebPack stuff above has done. Then after that.... another one will come along claiming to solve it.

What is wrong with just standard JS when it comes to something as important as structure?

woutercommandeur commented 9 years ago

It's all down to preference, browserify allows me to use node modules easily and still generate one minified, uglified game.js file. I needed something to triangulate polygons and found a decent module on npmjs.org. npm install the lib. require in my code, and go.

Anyway, the solution from my comment above works fine, and it's what I'll be using.

sompylasar commented 9 years ago

What is wrong with just standard JS when it comes to something as important as structure?

The only standard JS that tries to solve the dependency management problem is ES6 Modules which is not widely supported yet. Why not use a tool that helps to manage the structure and re-use thousands of existing modules now in a compatible and widely supported way?

Before webpack, browserify was the only tool that allowed to re-use node modules in the browser. It has several flaws which webpack gently resolves.

The cause of this issue with Phaser is that its distribution file is a concatenation of several parts, each bundled for the browser separately with its own way of internal dependency management. When this file runs directly in the browser, it works because all the parts export their entry points as different global variables. When this file is used as a CommonJS module (which is a primary method for browserify and webpack), it fails because the UMD snippets included into each part fall into providing entry points via module.exports which is the same for the whole file, so only the last assigned entry point wins. Moreover, several parts of Phaser use global variables without requiring them - this fails because in CommonJS mode of UMD the assignment to the global variables is skipped.

I have just worked out a solution for webpack. Although it slightly patches the current Phaser distribution to fix inconsistent internal dependency management, it does this transparently during the build process without modifying the original sources.

For those who knows how to provide loaders for webpack:

    module: {
        loaders: [
            { test: /\/phaser\.js$/i, loader: "phaser-webpack-loader" },
            { test: /\/phaser-debug\.js$/i, loader: "phaser-debug-webpack-loader" },
            // ...
        ]
    },
    resolveLoader: {
        alias: {
            "phaser-webpack-loader": path.join(__dirname, "tools/phaser-webpack-loader"),
            "phaser-debug-webpack-loader": path.join(__dirname, "tools/phaser-debug-webpack-loader")
        }
    },
    resolve: {
        alias: {
            "phaser": path.join(__dirname, "node_modules/phaser/dist/phaser.js"),
            "phaser-debug": path.join(__dirname, "node_modules/phaser-debug/dist/phaser-debug.js"),
            // ...
        },
        // ...
    },
/** phaser-webpack-loader */
module.exports = function(source) {
    this.cacheable && this.cacheable();

    // Fix for `p2`, it replaces `Phaser` with itself in `module.exports` when in the same file.
    source = source.replace(/"object"==typeof exports/, 'false');

    // Fix for `Phaser` to depend on `PIXI` exported before in the same file.
    source = source.replace(/(var\s+\w+\s*=\s*)Phaser(\s*\|\|\s*\{)/, 'var PIXI = exports.PIXI; $1Phaser$2');

    // Do not replace `module.exports` object, only put a property on `exports`.
    source = source.replace(/typeof module !== 'undefined' && module\.exports/g, "false /* typeof module !== 'undefined' && module.exports */");

    // Fix for Phaser node-webkit detection.
    source = source.replace(/require\('nw\.gui'\)/g, "undefined /* require('nw.gui') */");

    // Fix for missing `require` for `p2`.
    source = source.replace(/(p2\.Body\.prototype)/, 'var Phaser = require("Phaser").Phaser; var p2 = require("p2"); $1');

    // Fix for direct reference to global `document`. Works without this patch, too.
    source = 'var document = global.document;\n\n' + source;

    return source;
};
/** phaser-debug-webpack-loader */
module.exports = function(source) {
    this.cacheable && this.cacheable();

    // Inject Phaser object via webpack's `require` from the outside of the `phaser-debug` module function which has got its own `require`.
    source = source.replace(/(var\s+ui\s*=\s*require\('\.\/util\/ui'\))/, 'var Phaser = _Phaser; $1');
    source = '(function () { var _Phaser = require("phaser").Phaser;\n\n' + source + '\n\n}());';

    return source;
};

The whole project I'm working on is a boilerplate that includes automatic index.html generation and a configured webpack-dev-server via a gulp task. I'm planning to add basic game structure and workarounds for CocoonJS. It won't fit into a single comment, so if someone needs it at its current stage, please tell me, I'll try to publish the repo asap.

clark-stevenson commented 9 years ago

Thanks for the clear explanation @sompylasar

AbrahamAlcaina commented 9 years ago

+1 for the webpack

ThaisRobba commented 9 years ago

The way I'm managing this issue is not as clean as I would like but it works for all versions of Phaser.

I created a template (https://github.com/OttoRobba/browserify-phaser) which uses Phaser from npm. The index.html is like this:

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8" content="content">
        <title>Phaser Game</title>
    </head>
    <body>
        <script src="./node_modules/phaser/build/phaser.js" charset="utf-8"></script>
        <script src="bundle.js"></script>
    </body>
    </html>

Bundle.js is made from calling Beefy, using game.js as the entry file, which is like this:

    //We use window.game because we want it to be accessible from everywhere
    window.game = new Phaser.Game(800, 600, Phaser.AUTO);

    game.globals = { //Add variables here that you want to access globally
    };

    game.state.add('play', require('./states/play.js'));
    game.state.add('load', require('./states/load.js'));
    game.state.add('menu', require('./states/menu.js'));
    game.state.add('boot', require('./states/boot.js'));
    game.state.start('boot');

This works fine and is probably the easiest workaround for now. I'd love to be able to properly require('Phaser'); in the future though.

konsumer commented 9 years ago

It looks like this come from browserify creating CommonJS shims in libs & phaser build stuff concatenating it's products.

I notice p2js stuff in bundle/phaser.js

This isn't the only dep that uses browserify, but it might make sense to make the package.js main property something without the physics & add usage instructions to include these separately if using CommonJS (webpack or browserify.)

If I set the package.json main to ./build/custom/phaser-no-libs.js I get past the initial error, but then get another error like this:

Error: Cannot find module 'nw.gui' from 'node_modules/phaser/build/custom'

Which is probably related (because require is defined before shimming, and it's not requirejs, browserify thinks it might be node-webkit, which has other funny issues that have to be worked around.)

I think maybe the best solution is to switch over to CommonJS, or another module system (ES6 is an emerging standard & there are transpilers for it to convert to ES5) and build stuff that way, or don't concat and shim everything & use with browserify overrides (in the user's project.) Both would require changes to how the build-system works.

sompylasar commented 9 years ago

@konsumer You are right, the proposed solution may help, but you'll have to shim at least PIXI which Phaser depends on implicitly (see line 122 of https://raw.githubusercontent.com/photonstorm/phaser/master/build/custom/phaser-no-libs.js ).

nw.gui is another error that is caused by how Phaser detects Node-WebKit environment. https://github.com/photonstorm/phaser/blob/d8fee414b8c0efe405860eaa5ebfab19d4026d5c/src/system/Device.js#L841 This one should be easily fixed by providing a browserify shim for this nw.gui module that resolves to undefined.

Anyways, Phaser should rework its dependency management and build process to support CommonJS the right way.

konsumer commented 9 years ago

yep, you can add pixi to dependencies, and do var PIXI = require('pixi');

I am working on a light fork over here: https://github.com/notnullgames/phaser

We have it pretty close, but I am noticing some fancy stuff in system/Device.js that will need some attention.

photonstorm commented 9 years ago

Anyways, Phaser should rework its dependency management and build process to support CommonJS the right way.

This isn't going to happen, sorry. If someone wants to submit a PR that is proven to fix it, and doesn't mess anything else up, then I'll happily merge it, but that's all.

konsumer commented 9 years ago

Yep, no prob. I am working on it in a fork, and am happy to submit a PR when it's all worked out, and also happy to just use my fork for my own specialized purposes.

sompylasar commented 9 years ago

@konsumer Please mention me in the pull request, I'd like to review it when it's ready.

konsumer commented 9 years ago

I have a working branch with all the stuff I am not using moved out of the way. I am not sure I want to spend the time to convert all of phaser's build system on a "maybe that would be cool" but you can test mine with npm install notnullgames/phaser. I have a little demo project that uses it & browserify, here complete with beefy dev server & browserify.

konsumer commented 9 years ago

With the included build commands, you can see an example of cross-platform building of a UMD library (it can be used in browser global, AMD, or CommonJS) https://github.com/notnullgames/phaser

Just run npm run full or npm run full-min. Once I figured out that the build/manifest files describe the load-order, it became very easy to make it work. The main trick is using modules.exports=Phaser in Phaser.js, var Phaser=require('../Phaser.js'); in all the other files, and adding the var PIXI=require('pixi.js') for everything that needs that. CommonJS uses the same object for every require after the first. Since these libraries are super-good about keeping everything in their namespace, it becomes very easy to deal with.

photonstorm commented 9 years ago

I'm tempted to create a version of Phaser.Device that contains only the parts Phaser needs in order to run and strips out everything else. I imagine it'd be a tiny file actually.

konsumer commented 9 years ago

I really love that idea.

photonstorm commented 9 years ago

Yeah, am working on it. Will do the same for some other classes too.

konsumer commented 9 years ago

Sweet. Lemme know if I can help.

photonstorm commented 9 years ago

This feature request has been moved to the Phaser 3 feature list (so is being closed here)

sompylasar commented 9 years ago

@photonstorm Why a forum thread? It's not trackable... The feature requests would better be GitHub issues marked with a label and a milestone.

photonstorm commented 9 years ago

I don't want v3 clogging up the v2 repo (it has its own repo for that). I use the issues list as a bug tracker and it should be as close to zero as I can ever get it. I know some projects like to use it as a "todo" list as well, but I don't, sorry.

luckylooke commented 9 years ago

@nesukun hi! I was trying to use your workaround https://github.com/photonstorm/phaser/issues/1186#issuecomment-62481186 but when I am trying to reference phaser like this: require('phaser'); It returns empty object :/ Could you share working example please? Thanks

the-simian commented 9 years ago

I have a working webpack example here: https://github.com/the-simian/phaser-webpack-output-example

sompylasar commented 9 years ago

@the-simian Funny I did similar loader but haven't published to GitHub yet.

the-simian commented 9 years ago

@sompylasar I initially had not published it, but I decided to so I could go ahead and start keeping it handled with semver. I feel like its a bit kludgy- but it does allow a full use of webpack, in the way webpack was intended. Most of the browserify/webpack implementations I saw don't actually use npm for phaser, but keep a local module. I was trying to get away from that.

When I have time I am going to update the loaders to work with 2.3.x, as It does break right now (only works on 2.2.x).

This was the output of the slush-phaser-webpack scaffold I am using for my own purposes, but have opened for anyone to use. Its still under development, right now. I can see from this thread, the solutions are very similar (the find and replace stuff). I can see you wrote this much earlier than I did - Do you want to be listed as an author?

I feel like it slow, brittle work. I am reading that Version 3 will be common module compliant, and I hope that is true... In the meantime, it may have been more trouble than it was worth. Not sure.

sompylasar commented 9 years ago

@the-simian It's not rocket science actually, so I don't think listing me as author is necessary. But I really appreciate the suggestion!

Currently I've got no access to my repo, but I'll be glad to share what I've done (I don't remember if I made it compatible with 2.3.x, but I was targeting the latest release as of the time I did this).