javascriptnode.jsbrowserifycasperjsslimerjs

Bundling code for CasperJS+SlimerJS using Browserify?


TLDR; My question is: is there a way to make browserify NOT override require with its own implementation, and instead have it use a different method name (e.g. browserifyRequire) for all of its own internal requiring. To find out why I need to do this, please read on...

The Scenario

I'm trying to write some automated tests using CasperJS and running them in SlimerJS -- as opposed to the default PhantomJS (although for all I know, I would run into the same following issues with PhantomJS).

I really want to figure out how to write these in CoffeeScript. As it turns out, CasperJS or SlimerJS don't do well with CoffeeScript nowadays. The docs' recommendation is to compile to JS prior running casper. Ok... not super convenient, but I can handle it. In fact, I'm also finding out that the way require resolves paths in these tools is not as straightforward as in Node, so bundling ahead of running should help with that too.

But now I'm running into a new set of issues when trying to run the bundled code. I'm using Browserify for that.

The Problem

In my test code, I need to require('casper'). Standard practice in CasperJS world. So I had to tell browserify NOT to bundle CasperJS, by putting "browser": { "casper": false } in my package.json. No probs so far. But the problem comes next:

Browserify overrides the built-in require function, supplying its own implementation of require that does all the things that make browserify work. CasperJS is fine with it until it encounters the require('casper') directive. That's the one time CasperJS has to do the require'ing, not browserify. And that fails.

The Incomplete Solution

I'm quite sure that CasperJS just can't deal with the fact that Browserify overrides require, because CasperJS implements its own way of requireing. To test that hypothesis, I edited the resulting bundle manually, renaming every occurence of require to browserifyRequire -- including browserify's implementation of require. The only require I left unchanged was that call to require('casper'), because that's the one time I need CasperJS to handle the requireing. And indeed, this made things work as expected.

The Question

Again, is there a way to make browserify use a different name for its own internal require? I suppose I can write a script to make this change after the bundling, but I'd much rather figure out how to do this via config.

An Alternate Question

Maybe instead of Browserify there's another solution for bundling and running CoffeeScript inside CasperJS? I haven't found one yet....


Solution

  • Found a reasonable solution — one that can be run as an npm script, eg npm run build-test-bundle by adding to package.json

    "scripts": {
      "build-test-bundle": "browserify -t coffeeify casper-coffee-test.coffee | derequire | sed 's/_dereq_..casper../require(\"casper\")/g' > casper-coffee-test.compiled.js"
    },
    

    This sequence of commands does the following:

    1. browserify -t coffeeify casper-coffee-test.coffee builds the bundle
    2. | derequire pipes the browserify output to derequire, an npm that renames all occurrences of require function to _dereq_
    3. | sed 's/_dereq_..casper../require(\"casper\")/g' pipes previous output to the sed command, which replaces back to normal require all occurrences of _dereq_("casper")