Replacing Brunch with Webpack 1 in Phoenix
A tale of build tools
I recently started with Phoenix and tried to get on board with the whole brunch thing, but that faded quickly enough. I'm more back-end focused and don't want to learn some obscure front-end thing I won't use elsewhere. So, I decided to switch out brunch with webpack.
I'm using webpack 1 still, since it's easier for me at the moment, but will switch to webpack 2 sometime in the future. Unless of course The Next Big Thing TM for front-end comes out before then.
Steps
Like most things Phoenix, this was actually pretty easy to switch out. I'm going to show you my personal setup I use on my own projects. I am not claiming for this to be The One True Way or anything remotely close to that.
First, let's add some npm dependencies to package.json
. This is what I use:
{
"babel-core": "^6.24.0",
"babel-loader": "^6.4.1",
"babel-plugin-transform-runtime": "^6.23.0",
"babel-preset-es2015": "^6.24.0",
"copy-webpack-plugin": "^4.0.1",
"cross-env": "^3.2.4",
"css-loader": "^0.27.3",
"eslint": "^3.18.0",
"eslint-loader": "^1.6.3",
"extract-text-webpack-plugin": "^1.0.1",
"json-loader": "^0.5.4",
"node-sass": "^4.5.0",
"sass-loader": "^6.0.3",
"style-loader": "^0.14.1",
"webpack": "1"
}
Add a .babelrc
file:
{
"presets": [
"es2015"
],
"plugins": [
"transform-runtime"
]
}
Add an .eslintrc
file (this is a snippet version of my rules, see full file here):
{
"env": {
"browser": true,
"node": true
},
"parserOptions": {
"sourceType": "module"
},
"ecmaFeatures": {
"arrowFunctions": true,
"destructuring": true,
"classes": true,
"defaultParams": true,
"blockBindings": true,
"modules": true,
"objectLiteralComputedProperties": true,
"objectLiteralShorthandMethods": true,
"objectLiteralShorthandProperties": true,
"restParams": true,
"spread": true,
"templateStrings": true
},
"rules": {
"accessor-pairs": 2,
"array-bracket-spacing": 0,
"block-scoped-var": 0,
"brace-style": [2, "1tbs", { "allowSingleLine": true }],
"camelcase": 0,
"etc ..."
}
}
And then let's add a webpack.config.js
file:
var ExtractTextPlugin = require("extract-text-webpack-plugin");
var CopyWebpackPlugin = require("copy-webpack-plugin");
module.exports = {
entry: ["./web/static/css/app.scss", "./web/static/js/app.js"],
output: {
path: "./priv/static",
filename: "js/app.js"
},
resolve: {
modulesDirectories: [ "node_modules", __dirname + "/web/static/js" ]
},
devtool: "source-map",
module: {
loaders: [{
test: /\.json$/,
loader: 'json'
},{
test: /\.js$/,
exclude: /node_modules/,
loader: "babel!eslint"
}, {
test: /\.scss$/,
loader: ExtractTextPlugin.extract(
"style",
"css!sass?sourceMap"
)
}]
},
plugins: [
new CopyWebpackPlugin([{ from: "./web/static/assets" }]),
new ExtractTextPlugin("css/app.css")
]
};
After that we will tweak package.json
scripts, change this:
"scripts": {
"deploy": "brunch build --production",
"watch": "brunch watch --stdin"
},
to this:
"scripts": {
"deploy": "webpack -p",
"watch": "webpack --watch-stdin --progress --color"
},
And finally, update your Phoenix config, config/dev.exs
. Change:
watchers: [node: ["node_modules/brunch/bin/brunch", "watch", "--stdin",
cd: Path.expand("../", __DIR__)]]
to
watchers: [npm: ["run", "watch"]]
Conclusion
That wasn't so bad! Now when you run npm watch
or mix phoenix.server
, you will be using webpack instead of brunch.
Going further
If you use Vue.js, then I've added a post Add Vue.js to your Phoenix project's webpack 1 config