DEV Community

Kevin
Kevin

Posted on

Using Bootstrap 4 with Phoenix 1.4

Why bootstrap?

The default Phoenix CSS is very limited.

I wanted to add a minimal CSS to our webpage, but I'm not really expierenced in web development and needed something that's easy to use and offers a great documentation, so I decided (like everyone else) to use Bootstrap.

Adding Bootstrap to Phoenix is not that difficult, because you basically just have to follow the steps on the Bootstrap Getting started page for webpack.

1. Create your phoenix app

If you already have a phoenix app, you can skip this step.

Create your Phoenix project with

mix phx.new $PROJECT_NAME

2. Install bootstrap and its dependencies

Bootstrap needs jQuery and Popper.js to work. So we need to install it alongside Bootstrap. Because our npm root directory is located at $PROJECT_NAME/assets, we have to specify the prefix in npm install (or cd into assets).

To install everything just run

npm install bootstrap jquery popper.js --prefix assets

in our project directory.

You maybe get a deprecation warining for popper.js because a new version of popper exists, which is currently not supported by Bootstrap. So we ignore the warning for now.

(I learned that the --save option can be dropped since npm 5.0.0 because it defaults to adding the package to your dependencies)

3. Import bootstrap into the project

First we import the Bootstrap JavaScript files into our project.
For this to work, we add an import for Bootstrap in our app.js.
The app.js is located under $PROJECT_NAME/assets/js/app.js.

If you have a fresh Phoenix install your app.js should look like this:

// assets/js/app.js

// We need to import the CSS so that webpack will load it.
// The MiniCssExtractPlugin is used to separate it out into
// its own CSS file.
import css from "../css/app.css"

// webpack automatically bundles all modules in your
// entry points. Those entry points can be configured
// in "webpack.config.js".
//
// Import dependencies
//
import "phoenix_html"

// Import local files
//
// Local files can be imported directly using relative paths, for example:
// import socket from "./socket"

import 'bootstrap'; // Bootstrap support

Next we have to add the Bootstrap CSS.

If you want to customize the build-in bootstrap variables (e.g. to customize the theme of your page), you need to use SCSS.

If you don't need customization or want to override the css by your self, you can just import the bootstrap.min.css into your app.css under $PROJECT_NAME/assets/css/app.css like this:

@import '../node_modules/bootstrap/dist/css/bootstrap.min.css';

Otherwise we have to add the needed dependencies, so webpack can handle the SCSS.

For this we need sass-loader (with it's dependencies).

To add this to our project just run:

npm install sass-loader node-sass webpack --save-dev --prefix assets

After that, we need to change the webpack.config.js to compile our SCSS, so your webpack.config.js should look like this:

const path = require('path');
const glob = require('glob');
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');

module.exports = (env, options) => ({
  optimization: {
    minimizer: [
      new TerserPlugin({ cache: true, parallel: true, sourceMap: false }),
      new OptimizeCSSAssetsPlugin({})
    ]
  },
  entry: {
    './js/app.js': glob.sync('./vendor/**/*.js').concat(['./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: /\.s?css$/,
        use: [MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader']
      },
    ]
  },
  plugins: [
    new MiniCssExtractPlugin({ filename: '../css/app.css' }),
    new CopyWebpackPlugin([{ from: 'static/', to: '../' }])
  ]
});

After that we rename our app.css to app.scss and add the import for Boostraps SCSS files. The app.css file should look like this:

/* This file is for your main application css. */

/* Add your Bootstrap variable overrides here */


@import "~bootstrap/scss/bootstrap";

The last step is to replace the css import in the app.js with the scss import so the file looks like this:

// We need to import the CSS so that webpack will load it.
// The MiniCssExtractPlugin is used to separate it out into
// its own CSS file.
import css from "../css/app.scss"

// webpack automatically bundles all modules in your
// entry points. Those entry points can be configured
// in "webpack.config.js".
//
// Import dependencies
//
import "phoenix_html"

// Import local files
//
// Local files can be imported directly using relative paths, for example:
// import socket from "./socket"
import 'bootstrap';

That's it!

Now just run mix phx.server and you can use Bootstrap and it's components in your Phoenix Application.

Top comments (1)

Collapse
 
ramka001 profile image
Ram Kumar • Edited

Hi Kevin,

Thanks for this article.

I have a question when using Bootstrap, is there any way I can include the bootstrap.bundle.min.js i.e.

<script src="bootstrap.bundle.min.js">
</script>

into the app.js file?

I've tried using:

import 'bootstrap.bundle';

but it doesn't seem to work.