Why i have switched from webpack to brunch?

I always used webpack for my react.js projects. But one month ago i started to play with brunch build tool. And as much more i was learned about brunch, then less i wanted to return to webpack.

It is not going to be a tutorial, i just want to show you the benefits of brunch and hope after reading this article you will want to try this build tool too.

Brunch is not so popular as webpack or gulp or grunt, maybe you are hearing about it first time, but it is not mean that it worse, conversely, in most cases much more better. And below i am going to tell you why.


Here i will compare a simple build configs, which do almost the same work. One for webpack and one for brunch.

Here is the main files in the root of project.

And the content of “src” folder.

I have omitted all other stuff, because that’s all what we need to start discuss our build configs. All source code you can find in this repo.

https://github.com/beznosd/meet-up-event-planner


Let’s start from webpack. If you are not sure about what’s going on in this config, below i will shortly describe it.

// webpack.config.js
const path = require('path');
const webpack = require('webpack');
module.exports = {
devtool: 'source-map',
 entry: path.join(__dirname, '/src/index.jsx'),
output: {
path: path.join(__dirname, '/public'),
filename: 'bundle.js'
},
 module: {
loaders: [
{
include: path.join(__dirname, '/src'),
loader: 'babel'
},
{
test: /\.css$/,
loaders: ['style', 'css']
},
{
test: /\.png$/,
loader: 'url?limit=100000'
},
{
test: /\.jpg$/,
loader: 'file'
},
{
test: /\.(woff|woff2)(\?v=\d+\.\d+\.\d+)?$/,
loader: 'url?limit=10000&mimetype=application/font-woff'
},
{
test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/,
loader: 'url?limit=10000&mimetype=application/octet-stream'
},
{
test: /\.eot(\?v=\d+\.\d+\.\d+)?$/,
loader: 'file'
},
{
test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
loader: 'url?limit=10000&mimetype=image/svg+xml'
}
]
},
 resolve: {
modulesDirectories: ['node_modules'],
extensions: ['', '.js', '.jsx'],
alias: { picker: 'pickadate/lib/picker' }
},
resolveLoader: {
modulesDirectories: ['node_modules'],
moduleTemplate: ['*-loader', '*'],
extensions: ['', '.js']
},
 plugins: [
new webpack.ProvidePlugin({
$: 'jquery',
})
],
 watchOptions: {
aggregateTimeout: 100
},
 devServer: {
contentBase: './public',
colors: true,
historyApiFallback: true,
inline: true
}
};

So, what i don’t like in this stuff, and probably you too:

First. This config is for development environment, here we are not using any webpack optimization plugins.

If we will do in the same config production and development builds depends on process.env.NODE_ENV, this config will be much more bigger then now, or we should have different configs for each environment. Not cool.

Second. We have devtool, entry, output settings, and this is okay. Also we have loaders where we define how to process code which was written with using ES6 and jsx syntax. But below, we have to write a bunch of loaders for fonts and pictures. And part with fonts and pictures we will copy paste from project to project. Not cool.

Third. In resolve setting we provide modules directories, extension to be processed and alias for third-party library, resolveLoader is for improving the speed of build, because by default webpack looks for a lot of unnecessary in my case folders and extensions. You can see defaults by link. https://webpack.github.io/docs/configuration.html#resolveloader

aggregateTimeout property of watchOption setting we also redefine to improve speed of rebuilds. By default it is 300 ms.

Fourth. We need to install separate package webpack-dev-server and configure it to serve our bundle and recompile the bundle whenever the source files are changed. Or we can write simple server to serve our static files. Will be great to have all this stuff out of the box in the build tool.

And brunch help us to avoid or at least simplify all this cases. The config is simple, more understandable and TWICE smaller. Just look.

// brunch-config.js
module.exports = {
paths: {
watched: ['src']
},
 files: {
javascripts: {
joinTo: {
'bundle.js': /^src/
}
},
stylesheets: {
joinTo: 'app.css'
}
},
 plugins: {
babel: {
presets: ['es2015', 'react', 'stage-0']
}
},
 npm: {
globals: {
'$': 'jquery'
},
javascripts: {
'materialize-css': ['dist/js/materialize.min']
},
styles: {
'pickadate': ['lib/themes/default.date.css', 'lib/themes/default.css'],
'materialize-css': ['dist/css/materialize.css']
}
}
};

So, here, on top we define where to take files from, by default brunch watch for [‘app’, ‘test’, ‘vendor’] directories, if i will rename src folder to app, i will be able to omit this setting and make my config smaller.

In files setting we describe what brunch will generate and how brunch will do that. In output we will have one JS file with all resolved dependencies and one with our styles.

Then we define plugins, in our case we need just one (babel-brunch) to handle ES6 and jsx. Brunch have a lot more for all build needs.

In last section we tell brunch to handle some styles and js code from node_modules which can not be imported as modules in the code.

We have missed fonts and pictures, if you will put them to the src/assests folder brunch will just copy them to the public. If you want to optimize your images, brunch have plugins for this.

Yes, that’s all. All other stuff brunch will do for us.

Everything will Just Work™

Things that i like in brunch:

  • Super clean and small config file.
  • Fast builds and rebuilds.
  • Build in dev server
  • Simple configuration of production build.
  • Documentation
  • Skeletons (ideal option for quick start)
A Brunch skeleton is basically an application boilerplate that provides a good starting point for new applications. Skeleton can start you on your way with a specific pattern.

Conclusion

To learn more about brunch check it’s official site.

http://brunch.io/

Hope you have motivated to try brunch and got something new for yourself.

If you liked this article, tap the ❤ below to let more people know about brunch.