Adding Bootstrap 4 and Purge CSS to Phoenix 1.5
I hear Tailwind is popular now, but I personally do not see any benefit. It just adds extra complexity. First I tried to get used to it but I feel a lot more productive using Bootstrap and I like simple Bootstrap styles better. So I decided to stick with Bootstrap. For setting up Tailwind, this Pragmatic Studio post was helpful, by the way.
Here is how I set it up.
1. Install Bootstrap
cd assets
npm install bootstrap purgecss-webpack-plugin glob-all --save-dev
2. Import Bootstrap CSS
Next we need to import Bootstrap's CSS into our assets/css/app.scss
file.
/* This file is for your main application css. */
@import "../node_modules/nprogress/nprogress.css";
+ @import "../node_modules/bootstrap/scss/bootstrap.scss";
3. Configure Purge CSS
This is an optional step but we might as well get rid of unused CSS from Bootstrap since it is easy to set up. Open the assets/webpack.config.js
file and modify a few locations:
- Use
glob-all
instead of defaultglob
because we need to specify multiple filenames to Purge CSS. - Require purgecss-webpack-plugin
- Specify array of file paths that may reference any Bootstrap CSS class by name, which in Phoenix are all the view modules, template files, and JavaScript files.
const path = require('path');
- const glob = require('glob');
+ const glob = require('glob-all');
const HardSourceWebpackPlugin = require('hard-source-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const TerserPlugin = require('terser-webpack-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
+ const PurgecssPlugin = require('purgecss-webpack-plugin');
module.exports = (env, options) => {
const devMode = options.mode !== 'production';
return {
# ...
plugins: [
new MiniCssExtractPlugin({ filename: '../css/app.css' }),
new CopyWebpackPlugin([{ from: 'static/', to: '../' }]),
+ new PurgecssPlugin({
+ paths: glob.sync([
+ '../lib/**/*.ex',
+ '../lib/**/*.leex',
+ '../lib/**/*.eex',
+ './js/**/*.js'
+ ]),
+ }),
]
.concat(devMode ? [new HardSourceWebpackPlugin()] : [])
}
};
Or if we want to use Purge CSS only in production mode
module.exports = (env, options) => {
const devMode = options.mode !== 'production';
return {
# ...
plugins: [
new MiniCssExtractPlugin({ filename: '../css/app.css' }),
new CopyWebpackPlugin([{ from: 'static/', to: '../' }]),
].concat(
devMode
? [
// development only
new HardSourceWebpackPlugin(),
]
: [
// production only
new PurgecssPlugin({
paths: glob.sync([
'../lib/**/*.ex',
'../lib/**/*.leex',
'../lib/**/*.eex',
'./js/**/*.js',
]),
}),
]
),
}
};
Now that we use Bootstrap CSS, we can remove Phoenix default CSS for the flash message, other than .alert:empty
, which hides the flash message when there is nothing to show.
- .alert {
- padding: 15px;
- margin-bottom: 20px;
- border: 1px solid transparent;
- border-radius: 4px;
- }
- .alert-info {
- color: #31708f;
- background-color: #d9edf7;
- border-color: #bce8f1;
- }
- .alert-warning {
- color: #8a6d3b;
- background-color: #fcf8e3;
- border-color: #faebcc;
- }
- .alert-danger {
- color: #a94442;
- background-color: #f2dede;
- border-color: #ebccd1;
- }
- .alert p {
- margin-bottom: 0;
- }
.alert:empty {
display: none;
}
That's it!