An open API service indexing awesome lists of open source software.

https://github.com/milewski/bin-exec-loader

Execute any binary as a webpack loader.
https://github.com/milewski/bin-exec-loader

binary executable loader pipe universal-loader webpack webpack-loader

Last synced: 9 months ago
JSON representation

Execute any binary as a webpack loader.

Awesome Lists containing this project

README

          

# bin-exec-loader

[![npm version](https://badge.fury.io/js/bin-exec-loader.svg)](https://badge.fury.io/js/bin-exec-loader)
[![npm downloads](https://img.shields.io/npm/dm/bin-exec-loader.svg)](https://www.npmjs.com/package/bin-exec-loader)

Pipe **any file** through **any binary** with webpack.

##### Usage Examples

- You could transform any `/\.wav$/` to `.mp3` using [ffmpeg](https://ffmpeg.org/)
- You could transform any `/\.pdf$/` to single **JPGs** [ImageMagick](https://www.imagemagick.org/script/convert.php)
- This list could go on indefinitely...

## Install

```bash
$ npm install bin-exec-loader --save
```

## Usage

In your `webpack.config.js` add the bin-exec-loader

#### Examples

Let's say you would like to use imagemagick [`convert`](https://www.imagemagick.org/script/convert.php) to scale all your images down by 50%

In plain bash you would do like this:

```bash
$ convert input/image.png -resize 50% output/image.png
```

Then if you wish to execute the same command but as a webpack-loader you would do:

```js
module: {
rules: [
{
test: /\.(png|jpg|gif)$/,
use: [
{ loader: 'file-loader', options: { name: '[name].[ext]' } },
{
loader: 'bin-exec-loader',
options: {
binary: 'convert', // imagemagick converter binary
prefix: '-', // because imagemagick uses an uncommon syntax -like-this --instead-of-this
export: false, // because i want to let file-loader handle the output
emitFile: false, // otherwise we will end up with the original input file also saved on disk
args: {
$1: '[input]', // [input] will be replaced by the current file that is being proceed
resize: '50%',
$2: '[output]' // [output] will be where your output get's temporarily written
}
}
}
]
}
]
}
```

You can also set dynamic args like this:

```js
const smallImage = require('./test/sample-files/sample.png?resize=50%25') // 50%25 is the encoded version of 50%
```
```js
{
test: /\.(png|jpg|gif)$/,
loader: 'bin-exec-loader',
options: {
binary: 'convert',
prefix: '-',
args: {
$1: '[input]',
resize: '[resize]', // now all the parameters you send from the queryString will be available here as [param]
//resize: '[resize=50%]', // optionally you can set a default value
$2: '[output]'
}
}
}
```

if your binary produces multiple outputs you can grab those like this:
> convert each page of a pdf to jpg and retrieve an array of paths as result

```js
{
test: /\.pdf$/,
loader: 'bin-exec-loader',
options: {
binary: 'convert',
prefix: '-',
multiple: true, // let the loader knows there will be more than one output
emitFile: /\d\.jpg$/ // emit only the files ending with this pattern. e.g file-01.jpg
name: '[name].jpg'
args: {
$1: '[input]',
$2: '[output]'
}
}
}
```
```js
console.log(require('./some/file.pdf'))
// [ 'file-01.jpg', file-02.jpg', 'file-03.jpg', 'file-04.jpg' ]
```

How about a loader over http? optimizing your image using [tinypng](https://tinypng.com/developers/reference) api?

```bash
$ curl --user api:YOUR_API_KEY --data-binary @unoptimized.png https://api.tinify.com/shrink
```

```js
{
test: /\.(png|jpg|gif)$/,
use: 'bin-exec-loader',
options: {
binary: 'curl',
export: true,
args: {
user: 'api:YOUR_API_KEY',
dataBinary: '@[input]',
$0: 'https://api.tinify.com/shrink'
}
}
}
```

Then in some file in your bundle..

```js
const file = require('some-file.png')

console.log(file);

/**
{
"input": {
"size": 826071,
"type": "image/png"
},
"output": {
"size": 183477,
"type": "image/png",
"width": 1000,
"height": 665,
"ratio": 0.2221,
"url": "https://api.tinify.com/output/sau7d5debbhlrtae.png"
}
}
**/
```

You can also chain it with pretty much with any loader, you just need to understand the use of the option export, e.g: in the example above you could also archive the same result chaining it with `json-loader` :

```js
{
test: /\.(png|jpg|gif)$/,
use: [
{ loader: 'json-loader' },
{
loader: 'bin-exec-loader',
options: {
binary: 'curl',
//export: true, disable export so the raw output is passed to the next loader
args: {
user: 'api:YOUR_API_KEY',
dataBinary: '@[input]',
$0: 'https://api.tinify.com/shrink'
}
}
}
]
}
```

## Options


Options
Type
Default
Description


binary
string
-
The binary you want to execute, could be a string to some executable available in your PATH or a npm module.


export
boolean
false
Determines if the output should be read from the [output] placeholder or it should be exported as a module.exports = data


quote
boolean
false
Whether the params should be wrapped with quotes --param "one"


equals
boolean
false
Whether the params should be assigned with a equal sign --param=one


emitFile
boolean|regExp
true
Whether if the output should be emitted


name
string
[name].[ext]
The output file name, you can use [name],[hash],[ext] and for images only: [width], [height]


prefix
string|function
standard
The prefix used to on the args key. standard will act like most CLI does, single letter gets - more than one gets --


enable
boolean
true
Enable/Disable this loader, good to use when you don't want to run it on process.env.NODE_ENV === 'development' for example.


cache
boolean
true
Tell webpack if the output of this loader should be cached.


multiple
boolean
false

Determine if the binary will produce multiple outputs. If true the result will always be an array of path of the resulting files. you can control what gets emitted with using emitFile: regExp



args
object
{}

The args you want to invoke your command with.



  • $ will be replaced -


  • $0...N will be removed. e.g { $2: "hello" } will become my-cli hello


You can also use [input] and [output] on the values as placeholders for the the real resource path.
e.g { $0:"[input]" } will become open an/absolute/path/file.extension

## Testing

To run the tests locally it's necessary to have installed [ImageMagick](http://www.imagemagick.org/script/download.php) and [GhostScript](https://ghostscript.com/download/gsdnld.html)

## License

[MIT](LICENSE) © [Rafael Milewski](https://rafael-milewski.com?github=readme)