Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Output an executable file with webpack

I'm currently writing a node CLI tool and using webpack to bundle all of my assets. The entry point for this application is the js file where I actually parse process.argv and run a command (For reference, I'm using tj/commander). This way, once the bundling is complete, I can enter ./<outputFile> and it will run my application. The entry file looks like this:

import cli from './cli';

cli.parse(process.argv);

// If nothing was supplied
if (!process.argv.slice(2).length) {
  cli.outputHelp();
}

The bundling works fine but I can't get webpack to output the file as an executable. Once I run chmod +x <outputFile>, everything works perfectly. Is there a way that I can tell webpack what permissions to grant an output file?

like image 422
taylorc93 Avatar asked Jan 23 '17 19:01

taylorc93


People also ask

How do I bundle a JavaScript file using webpack?

You can bundle your JavaScript using the CLI command by providing an entry file and output path. Webpack will automatically resolve all dependencies from import and require and bundle them into a single output together with your app's script.

What is entry and output in webpack?

The output in Webpack is an object holding the path where our bundles and assets will go, as well as the name the entries will adopt. var path = require('path'); var baseConfig = { entry: { main: './src/index.js' }, output: { filename: 'main.js', path: path. resolve('./build') } }; // export configuration module.


2 Answers

I'm surprised no one said a thing about webpack's BannerPlugin. I do something similar than @oklas, but using BannerPlugin to add the specific node shebang:

{
  plugins: [
    new webpack.BannerPlugin({
      banner: '#!/usr/bin/env node',
      raw: true,
    }),
  ],
}

Then I simply add the execution permissions just adding chmod to my package.json file:

"scripts": {
  "build": "webpack && chmod +x dist/mycommand"
}

Anyway, if you'd like to just use webpack you can use the WebpackShellPlugin, as said by oklas (note that using this forces you to add a new dependency, that's why I avoid using this approach):

const WebpackShellPlugin = require('webpack-shell-plugin')
{
  // [...]
  plugins: [
    new WebpackShellPlugin({
      onBuildEnd:['chmod +x dist/mycommand'],
    }),
  ],
}

If you want to avoid including WebpackShellPlugin as a dependency, you can try to define a custom plugin based on fs, as said by @taylorc93

like image 194
elboletaire Avatar answered Sep 28 '22 08:09

elboletaire


One simple way is to use npm. Do you have an package.json in your project? Add "build": "webpack && chmod +x outputFile" to the scripts section of your package.json and build your project by running npm run build.

Another way is to add one of these solutions to your webpack.config.js:

  • simple plugin from this answer which has pre and post build handlers

  • use on-build-webpack plugin, which executes js code at the end of the webpack build process

Whatever you choose, you'll need to add this piece of code:

var chmod = require('chmod');
chmod("outputFile", 500);
like image 32
oklas Avatar answered Sep 28 '22 06:09

oklas