
Configuring Webpack and React with Phoenix 1.3 (with Heroku deployment)
If you are building an app with a heavy focus on the front-end. You may want to use Webpack. Especially if you also would like to add React to your project.
We can manually replace Brunch with Webpack. This will remove a lot of headaches during deployment of a Phoenix application (an extensive process in itself).
Starting from version 1.4, Phoenix will support it out of the box for asset management.
Credit to Vitaly Tatarintsev for the initial guidance.
Configure Webpack
We need to remove all the Brunch configuration we already have in our project.
As a first step, we should remove the following libraries from the development dependencies of the package.json file:
"devDependencies": {
"babel-brunch": "...",
"brunch": "...",
"clean-css-brunch": "...",
"uglify-js-brunch": "...",
...
}(and any other Brunch dependencies you might have)
Install the newly required dependencies:
cd assets
npm install babel-core babel-loader@7 babel-preset-env --save-dev
npm install webpack webpack-cli --save-dev
npm install copy-webpack-plugin css-loader mini-css-extract-plugin optimize-css-assets-webpack-plugin uglifyjs-webpack-plugin --save-devNote: At the time of this writing, Babel 7 was just released. If you want to use the latest version of Babel, ignore babel-loader@7 and use babel-loader. You will have to debug quite a bit of preset naming.
Open package.json again and change:
"scripts": {
"deploy": "brunch build --production",
"watch": "brunch watch --stdin"
},to
"scripts": {
"deploy": "webpack --mode production",
"watch": "webpack --mode development --watch"
},Now, remove the brunch-config.js file.
rm brunch-config.jsCreate a new file: assets/webpack.config.js with the following content:
const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
module.exports = (env, options) => ({
optimization: {
minimizer: [
new UglifyJsPlugin({ cache: true, parallel: true, sourceMap: false }),
new OptimizeCSSAssetsPlugin({})
]
},
entry: './js/app.js',
output: {
filename: 'app.js',
path: path.resolve(__dirname, '../priv/static/js')
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader'
}
},
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, 'css-loader']
}
]
},
plugins: [
new MiniCssExtractPlugin({ filename: '../css/app.css' }),
new CopyWebpackPlugin([{ from: 'static/', to: '../' }])
]
});Add import css from "../css/app.css" on top of the assets/js/app.js file
In the config/dev.exs change
watchers: [node: ["node_modules/brunch/bin/brunch", "watch", "--stdin",
cd: Path.expand("../assets", __DIR__)]]to:
watchers: [node: ["node_modules/webpack/bin/webpack.js", "--mode", "development", "--watch-stdin",
cd: Path.expand("../assets", __DIR__)]]Create a assets/.babelrc file with the following content:
{
"presets": [
"env"
]
}If further configuration is needed, you can review the babel-preset-env docs.
Pause for a moment and start your server:
cd .. # If you are inside your /assets directory
mix phx.serverIf you have any errors, follow the previous steps to debug.
On Default Phoenix CSS
We did not includeassets/css/phoenix.css into the assets/css/app.css file.
Phoenix 1.3 provides us by default glyphicons fonts. However, they are not imported. It was not a problem with brunch because we can’t see any errors related to missing fonts until we try to use them. This workflow changes with Webpack. When Webpack processes the file, it will try to build a dependency graph. If an error occurs, it will crash.
If you desire to use assets/css/phoenix.css you must either delete the line in the minified file or import glyphicons fonts.
Configure React
If you want to install React (or any other front-end framework), continue onward.
First, let’s install additional dependencies.
cd assets
npm install --save react react-dom
npm install --save-dev babel-preset-react
cd ..Extend presets assets/.babelrc to have react as well.
{
"presets": [
"env",
"react"
]
}Done! Import all JS files as normal within your app.js file.
Deploying on Heroku
If you are updating from Brunch to Webpack on a production application, you will need to do some deployment modifications.
At the time of writing, the Heroku buildpacks default to Brunch.
Customizing the Buildpack
By default, there is acompile shell script which gets run after building dependencies and just before finalizing the build. The compile file looks like this.
To customize your app’s compile hook, just add a compile file to your app's root directory. compile is just a shell script, so you can use any valid bash code. Keep in mind you'll have access to your node_modules and mix. This means that if you're using a Node build tool other than brunch, you can just do something like:
#./compile
cd $phoenix_dir
npm --prefix ./assets run build
mix "${phoenix_ex}.digest"Recommended compile file for Webpack is:
./node_modules/.bin/webpack -pcd $phoenix_dirmix phx.digest
Then, redeploy your application.

