Skip to content

egoist/conpack

Repository files navigation

conpack

NPM version NPM downloads CircleCI donate chat

Manage rules and plugins in webpack config like a boss.

Use case

Imagine friend A writes a package called create-babel-webpack-config that adds babel-loader to webpack config:

module.exports = () => {
  return {
    module: {
      rules: [{
        test: /\.jsx?$/,
        use: [{
          loader: 'babel-loader',
          options: { presets: ['react-app'] }
        }]
      }]
    }
  }
}

Then friend B wants to reuse this package but with some tweaks to use buble-loader instead:

// webpack.config.js
const createBabelWebpackConfig = require('create-babel-webpack-config')

const webpackConfig = createBabelWebpackConfig()

webpackConfig.module.rules = webpackConfig.module.rules.map(rule => {
  if (rule.test.toString() === '/\\.jsx?$/') {
    rule.use[0].loader = 'buble-loader'
    rule.use[0].options = { target: { node: 6 } }
  }
  return rule
})

module.exports = webpackConfig

THIS IS OBVIOUSLY UGLY!

Finally friend C shows friend A the power of conpack, letting him rewrite create-babel-webpack-config to as follows:

const Conpack = require('conpack')

module.exports = () => {
  const conpack = new Conpack()
  const jsRule = conpack.rules.add('js', {
    test: /\.jsx?$/
  })
  jsRule.loaders.add('babel', {
    loader: 'babel-loader',
    options: {
      presets: ['react-app']
    }
  })
  return conpack
}

For friend B, he can find and modify the rules with confidence:

// webpack.config.js
const createBabelWebpackConfig = require('create-babel-webpack-config')

const conpack = createBabelWebpackConfig()

const jsRule = conpack.rules.get('js')
jsRule.loaders.replace('babel', 'buble', {
  loader: 'buble-loader',
  options: {
    target: { node: 6 }
  }
})

module.exports = conpack.toConfig()

Install

yarn add conpack
Example
// webpack.config.js
const Conpack = require('conpack')

const conpack = new Conpack()

// Add a rule
const jsRule = conpack.rules.add('js', {
  test: /\.jsx?$/
})
jsRule.loaders.add('babel', {
  loader: 'babel-loader',
  options: {}
})

// Change loader later by name
jsRule.loaders.replace('babel', 'buble', {
  loader: 'buble-loader',
  options: {}
})

// Add a plugin
conpack.plugins.add('uglify', webpack.optimize.UglifyJsPlugin, [
  {/* options */}
])
// Remove a plugin
conpack.plugins.remove('uglify')

conpack.config = {
  entry: './src/index.js',
  output: {
    path: __dirname,
    filename: '[name].js'
  },
  mode: process.env.NODE_ENV || 'development'
}

module.exports = conpack.toConfig()
// Alternatively
module.exports = {
  ...conpack.config,
  module: {
    rules: conpack.rules.toArray()
  },
  plugins: conpack.plugins.toArray()
}

Guide

General options

For general options (other than module.rules and plugins).

Note that following methods support dot-nested path as they're using lodash.get lodash.set lodash.unset under the hood.

Getting value

conpack.get('resolve.modules')

Setting value

conpack.set('resolve.alias.foo$', 'foo-module')
// { resolve: { alias: { foo$: 'foo-module' } } }

Delete value

conpack.delete('resolve.alias.foo$')

Update value

conpack.update('output.path', currentPath => currentPath + '/foo')

Append value

conpack.append('entry.client', './foo.js')

Prepend value

conpack.prepend('entry.client', 'webpack/hot/client')

Rules

Add a rule

const rule = conpack.rules.add('rule-name', {
  test: /\.js$/,
  // ...options (excluding `use`)
})
// =>
// {
//   module: {
//     rules: [
//       {
//         test: /\.js$/,
//         // ...options
//       }
//     ]
//   }
// }

Prepend a rule

conpack.rules.prepend('rule-name', options)

Get a rule

conpack.rules.get('rule-name')

Update a rule

// Always got the rule
const rule = conpack.rules.get('rule-name')
rule.update(options => {
  options.test = /\.ext$/
  return options
})

// Or update a rule by name directly
conpack.rules.update('rule-name', options => newOptions)

Delete a rule

conpack.rules.delete('rule-name')

Replace a rule

conpack.rules.replace('rule-name-to-replace', 'new-rule-name', newOptions)

Check if a rule exists

conpack.rules.has('rule-name')

Loaders

Loader belong to a rule.

The API rule.loaders is pretty much the same as conpack.rules.

Plugins

The API conpack.plugins is pretty much the same as conpack.rule, except for:

  • conpack.plugins.add(name, Plugin, options): The second argument is the plugin constructor, the third one is its options as an array.
  • conpack.plugins.update(name, Plugin, options): Update plugin by given name.
  • conpack.plugins.updateOptions(name, options): Update plugin options by given name.

Contributing

  1. Fork it!
  2. Create your feature branch: git checkout -b my-new-feature
  3. Commit your changes: git commit -am 'Add some feature'
  4. Push to the branch: git push origin my-new-feature
  5. Submit a pull request :D

Author

conpack © EGOIST, Released under the MIT License.
Authored and maintained by EGOIST with help from contributors (list).

github.com/egoist · GitHub @EGOIST · Twitter @_egoistlily

About

Manage webpack config like a boss.

Topics

Resources

License

Stars

Watchers

Forks

Sponsor this project

 

Packages

No packages published