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
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.
You need to specify node: false
in addition to target: node
to avoid global mocks. There is a good write up here.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With