Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

webpack + shelljs will throw "Error: Cannot find module '/exec-child.js'"

I want to use shelljs to write some scripts in javascript, since I want to use some new JavaScript features, I use Babel + webpack to bundle my code to a single bundle js.

The code is quite simple:

entry.js

import shell from 'shelljs'

shell.exec('ls')

webpack.conf.js

module.exports = {
    mode: "development",
    target: 'node',
    entry: './entry.js',
    output: {
        path: __dirname,
        filename: './dist/bundle.js'
    },
    module: {
        rules: [{
            test: /\.js$/,
            use: [{
                loader: 'babel-loader', options: {
                    presets: ['@babel/preset-env']
                }
            }]
        }]
    }
}

package.json

{
  "scripts": {
    "demo": "webpack && node ./dist/bundle.js"
  },
  "devDependencies": {
    "@babel/core": "7.2.2",
    "@babel/preset-env": "7.4.2",
    "babel-loader": "8.0.6",
    "webpack": "4.28.1",
    "webpack-cli": "3.2.1"
  },
  "dependencies": {
    "shelljs": "0.8.3"
  }
}

When I run "npm install && npm run demo", it throws:

Error: Cannot find module '/exec-child.js'
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:636:15)
    at Function.Module._load (internal/modules/cjs/loader.js:562:25)
    at Function.Module.runMain (internal/modules/cjs/loader.js:829:12)
    at startup (internal/bootstrap/node.js:283:19)
    at bootstrapNodeJSCore (internal/bootstrap/node.js:622:3)
webpack:///./node_modules/shelljs/src/common.js?:412
        throw e;
        ^

ShellJSInternalError: ENOENT: no such file or directory, open '/var/folders/gm/t8kf08qn0598qcl_vkxxyhxc0000gr/T/shelljs_d7da547d2136239bb317'
    at Object.openSync (fs.js:443:3)
    at Object.readFileSync (fs.js:343:35)
    at execSync (webpack:///./node_modules/shelljs/src/exec.js?:85:17)
    at Object._exec (webpack:///./node_modules/shelljs/src/exec.js?:213:12)
    at Object.eval [as exec] (webpack:///./node_modules/shelljs/src/common.js?:348:23)
    at eval (webpack:///./entry.js?:5:48)

I can't figure out why.

Here is also an complete small demo for this problem, you can just clone and run it:

https://github.com/freewind-demos/javascript-shelljs-webpack-demo

like image 633
Freewind Avatar asked Aug 04 '19 07:08

Freewind


1 Answers

I was able to work around this issue by modifying my Webpack config.

ShellJS uses node to execute a JS file called exec-child.js - code at the time of writing.

The problem is that the bundled code doesn't know where that file is, for two reasons.

  1. You need to specify node: false in addition to target: node to avoid global mocks. There is a good write up here.

  2. You need to explicitly copy the file to your output directory, since __dirname will point there, and then path.join(__dirname, 'exec-child.js') will be valid. You can do this using copy-webpack-plugin. Here is an example of the config that I have working.

like image 189
Matt Avatar answered Nov 15 '22 19:11

Matt