Code Monkey home page Code Monkey logo

webpack-blocks's Introduction

webpack-blocks

Functional building blocks for the webpack config. Compose it using feature middlewares like Babel, PostCSS, HMR (Hot Module Replacement), …

Missing anything? Write your own and share them!

Build Status JavaScript Style Guide

"Finally, webpack config done right. (...) Webpack clearly wants to stay low-level. So it makes total sense to outsource configuring it to well designed blocks instead of copy-paste."

Dan Abramov via twitter (Co-author of Redux, Create React App and React Hot Loader)

Installation

npm install --save-dev @webpack-blocks/webpack2 @webpack-blocks/babel6 ...

Usage

Create a webpack 2 config with Babel support, dev server and PostCSS autoprefixer:

const { createConfig, defineConstants, env, entryPoint, setOutput, sourceMaps } = require('@webpack-blocks/webpack2')
const babel = require('@webpack-blocks/babel6')
const devServer = require('@webpack-blocks/dev-server2')
const postcss = require('@webpack-blocks/postcss')
const autoprefixer = require('autoprefixer')

module.exports = createConfig([
  entryPoint('./src/main.js'),
  setOutput('./build/bundle.js'),
  babel(),
  postcss([
    autoprefixer({ browsers: ['last 2 versions'] })
  ]),
  defineConstants({
    'process.env.NODE_ENV': process.env.NODE_ENV
  }),
  env('development', [
    devServer(),
    devServer.proxy({
      '/api': { target: 'http://localhost:3000' }
    }),
    sourceMaps()
  ])
])

Wanna use CSS modules? No problem!

const cssModules = require('@webpack-blocks/css-modules')

...

module.exports = createConfig([
  ...
  cssModules()
])

Need a custom block? Easy, since a block is just a function returning a function:

module.exports = createConfig([
  ...
  myCssLoader([ './styles' ])
])

function myCssLoader (include) {
  return (context) => ({
    module: {
      loaders: [
        {
          test: context.fileType('text/css'),
          loaders: [ 'style-loader', 'my-css-loader' ],
          include
        }
      ]
    }
  })
}

Check out the sample app to see a webpack config in action or read how to create your own blocks.

Available webpack blocks

Missing something? Write and publish your own webpack blocks!

Upgrading from webpack 1.x to webpack 2.x

One of the nice gimmicks of using webpack-blocks is that you can switch between webpack versions in an instant!

Just use the webpack 2.x versions of the following blocks:

@webpack-blocks/webpack -> @webpack-blocks/webpack2
@webpack-blocks/dev-server -> @webpack-blocks/dev-server2
@webpack-blocks/extract-text -> @webpack-blocks/extract-text2

Design principles

  • Extensibility first
  • Uniformity for easy composition
  • Keep everything configurable
  • But provide sane defaults

You might want to know

Can I get rid of the default loaders?

The createConfig() function sets some generic default loaders. This should not be a problem. If does happen to be a problem you can also create a "vanilla" configuration (without the defaults) by using createConfig.vanilla() instead.

How does env() work?

You might wonder how env('development', [ ... ]) works? It just checks the NODE_ENV environment variable and only applies its contained webpack blocks if it matches.

So make sure you set the NODE_ENV accordingly:

// your package.json
"scripts": {
  "build": "NODE_ENV=production webpack --config webpack.config.js",
  "start": "NODE_ENV=development webpack-dev-server --config webpack.config.js"
}

If there is no NODE_ENV set then it will just treat NODE_ENV as if it was development.

What does defineConstants() do?

defineConstants() is just a small convenience wrapper around webpack's DefinePlugin. It is composable and automatically encodes the values. Use it to replace constants in your code by their values at build time.

So having a defineConstants({ 'process.env.FOO': 'foo' }) and a defineConstants({ 'process.env.BAR': 'bar' }) in your config means the resulting webpack config will finally contain a single new webpack.DefinePlugin({ 'process.env.FOO': '"FOO"', 'process.env.BAR': '"BAR"' }), thus replacing any occurence of process.env.FOO and process.env.BAR with the given values.

What does a block look like from the inside?

A webpack block is just a function and requires no dependencies at all (🎉🎉), thus making it easy to write your own blocks and share them with the community.

Take the babel6 webpack block for instance:

/**
 * @param {object} [options]
 * @param {RegExp|Function|string}  [options.exclude]   Directories to exclude.
 * @return {Function}
 */
function babel (options) {
  const { exclude = /\/node_modules\// } = options || {}

  return (context) => ({
    module: {
      loaders: [
        {
          // we use a `MIME type => RegExp` abstraction here in order to have consistent regexs
          test: context.fileType('application/javascript'),
          exclude: Array.isArray(exclude) ? exclude : [ exclude ],
          loaders: [ 'babel-loader?cacheDirectory' ]
        }
      ]
    }
  })
}

Add a README and a package.json and you are ready to ship.

For more details see How to write a block.

I need some custom webpack config snippet!

No problem. If you don't want to write your own webpack block you can just use customConfig():

const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { addPlugins, customConfig } = require('@webpack-blocks/webpack2')

...

module.exports = createConfig([
  ...
  addPlugins([
    // Add a custom webpack plugin
    new HtmlWebpackPlugin({
      inject: true,
      template: './index.html'
    })
  ]),
  customConfig({
    // Add some custom webpack config snippet
    resolve: {
      extensions: [ '.js', '.es6' ]
    }
  })
])

The object you pass to customConfig() will be merged into the webpack config using webpack-merge like any other webpack block's partial config.

How to compose blocks? (a.k.a. building presets)

Got some projects with a similar, yet not identical webpack configuration? Seems like you could use a preset:

const { createConfig, env, group } = require('@webpack-blocks/webpack2')
const babel = require('@webpack-blocks/babel6')
const devServer = require('@webpack-blocks/dev-server2')

function myPreset (proxyConfig) {
  return group([
    babel(),
    env('development', [
      devServer(),
      devServer.proxy(proxyConfig)
    ])
  ])
}

module.exports = createConfig([
  myPreset({
    '/api': { target: 'http://localhost:3000' }
  }),
  ...   // add more blocks here
])

The key feature is the group() method which takes a set of blocks and returns a new block that combines all their functionality.

Like what you see?

Support webpack-blocks by giving feedback, publishing new webpack blocks or just by 🌟 starring the project!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.