Vm2: Make vm2 compatible with Webpack

Created on 26 Apr 2017  ·  5Comments  ·  Source: patriksimek/vm2

  • [x] figure out how to remove coffee-script require without breaking a backwards compatibility
  • [ ] figure how to instruct webpack to bundle scripts loaded via fs - sandbox.js and contextify.js
feature request help wanted

Most helpful comment

Any progress on this issue? Here is the best and probably the simplest way I've found to make vm2 compatible with Webpack. It doesn't require any changes in vm2 itself, just 3 lines of additional configuration and a simple NPM script:

  1. Create a package.json in the output/ directory:
{
    "dependencies": {
        "vm2": "latest"
    }
}
  1. Mark vm2 as an external library in the Webpack config:
externals: {
    "vm2": "require('vm2')"
}
  1. Add an additional script in NPM which installs dependencies in output/ directory once Webpack has finished all the stuff:
"scripts": {
    "prepare-output": "cd output && npm install",
    "prepare": "webpack --progress && npm run prepare-output"
}

All 5 comments

Another issue is require. Although webpack just generate warnings for these require:

WARNING in ./~/vm2/lib/main.js
147:26-33 Critical dependency: require function is used in a way in which dependencies cannot be statically extracted

WARNING in ./~/vm2/lib/main.js
251:3-10 Critical dependency: require function is used in a way in which dependencies cannot be statically extracted

WARNING in ./~/vm2/lib/main.js
295:26-33 Critical dependency: require function is used in a way in which dependencies cannot be statically extracted

webpack actually replaced these require with exceptions:
For example, before webpack:

        Reflect.defineProperty(this, '_internal', {
            value: vm.runInContext(`(function(require, host) { ${cf} \n})`, this._context, {
                filename: `${__dirname}/contextify.js`,
                displayErrors: false
            }).call(this._context, require, host)
        });

After webpack:

        Reflect.defineProperty(this, '_internal', {
            value: vm.runInContext(`(function(require, host) { ${cf} \n})`, this._context, {
                filename: `${__dirname}/contextify.js`,
                displayErrors: false
            }).call(this._context, !(function webpackMissingModule() { var e = new Error("Cannot find module \".\""); e.code = 'MODULE_NOT_FOUND'; throw e; }()), host)
        });

Replace require with eval('require') can solve the problem for me. I wonder if there is a better solution.

Any progress on this issue? Here is the best and probably the simplest way I've found to make vm2 compatible with Webpack. It doesn't require any changes in vm2 itself, just 3 lines of additional configuration and a simple NPM script:

  1. Create a package.json in the output/ directory:
{
    "dependencies": {
        "vm2": "latest"
    }
}
  1. Mark vm2 as an external library in the Webpack config:
externals: {
    "vm2": "require('vm2')"
}
  1. Add an additional script in NPM which installs dependencies in output/ directory once Webpack has finished all the stuff:
"scripts": {
    "prepare-output": "cd output && npm install",
    "prepare": "webpack --progress && npm run prepare-output"
}

Hi !

I got the same problem and here is how I resolved it :

  1. First, I can't directly use the module as a npm module, because I had to modify the sources, so I c/c the lib in a folder of my project (it's only a few files, no problem with that)

  2. About the fs for sandbox.js/contextify.js : I renamed them sandbox.txt & contextify.txt, then used a raw-loader to load them as plain text.

main.js (at the top)

const sb = require('./sandbox.txt');
const cf = require('./contextify.txt');

webpack.config.js

{
    test: /\.txt$/,
    use: 'raw-loader'
}

Don't forget to change all references of sandbox.js/contextify.js to sandbox.txt/contextify.txt in main.js.

  1. Last tricky part, require : for NodeVM, I changed one line

main.js (around line 250)

[...]
const host = {
    version: parseInt(process.versions.node.split('.')[0]),
    require: eval('require'),
    process,
    console,
[...]

I changed the "require" to "require: eval('require')" so webpack doesn't modify it (as suggered by Coxxs) and it did the trick.

Now I can use vm2 properly, without needing it as an external library.
I know it's quite tricky and not very clean, but it's the only solution I got so far.
I hope it can help some of you & also help in a real fix.

If you have better solutions, we'd love to hear them ! :)

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

FWIW - bundling with Webpack 5, with a target of node appears to work.

Was this page helpful?
0 / 5 - 0 ratings