How to Change Version of Bootstrap?

Hey all,

I’m very new to phoenix framework and at the stage of just laying out the frontend of my app (a multi-tenant one that I’ve asked about in another question in this forum today), and trying to find where I may be able to change a config setting or how I may use mix to change bootstrap.

I want to use version 4 (alpha) of bootstrap with the hope that it will be release for production by the time my app is ready for launch early next year.

Where/how can the version of bootstrap be changed in the phoenix framework?



I usually get rid of the default application.css file and include the dependencies using npm and let brunch handle the dependencies.


Thanks, how do you do that?

I’ve tried:

deleting phoenix.css


npm install twbs/bootstrap#v4-dev

which installed but didn’t add it to package.json.

So I manually added devDependencies

“bootstrap”: “4.0.0-alpha.5”,

and got no complaint when running mix phoenix.server (I did after first trying “bootstrap: v4-dev”), so assumed it has been added.

I’m ok with Elixir but just getting into Phoenix, so do I need to make a new css file somewhere with Bootstrap 4 referenced in it?


1 Like

Empty the contents of app.css and follow this guide

  1. Remove Bootstrap from web/static/css/phoenix.css.
  2. npm install --save-dev bootstrap@4.0.0-alpha.5
  3. Update brunch-config.js:
npm: {
  // Add this.
  styles: {
    bootstrap: ["dist/css/bootstrap.css"]

If you’d like to use Bootstrap’s JavaScript you also have to:

  1. npm install --save-dev jquery
  2. Update brunch-config.js:
modules: {
  autoRequire: {
    // Add "jquery".
    "js/app.js": ["jquery", "web/static/js/app"]
npm: {
  // Add this.
  globals: {"jQuery": "jquery"}

This is required to make jQuery available to Bootstrap’s JavaScript.

Hope it helps. :slight_smile:


Change that to be:

npm install --save twbs/bootstrap#v4-dev

And it will add it to your package file automatically. :slight_smile:


Thanks, I’ll have a read!

Thanks, I did that and it works.

I must try this next time, thanks!

The --save-dev flag is for adding compile-time dependencies. The --save flag is for adding runtime dependencies. Bootstrap is a runtime dependency, so you should use the --save flag :exclamation:

It will “work” currently regardless because it’s storing the package in node_modules, so because it’s “working” now is misleading. You should use the --save flag as @OvermindDL1 said. Or, just manually move the dependency in package.json to the non-dev dependencies block.

I’m not a javascript expert and this one has bitten me before! :smile: Also, you can check out this article about the differences between the two flags.


Thanks so much for clarifying that!

You’ve saved me a future question as I’ve been wondering what the difference was.

1 Like

Not sure if it’s relevant in your situation but if you deploy to heroku you may run into this too. I switched a phoenix app to use bootstrap 4 alpha and due to build issues I had to down grade sass-brunch in my package.json to:

“sass-brunch”: “^2.0.0”

In this case I think it belongs in devDependencies. It needs to be around during development so that Brunch can bundle it with the rest of your CSS and JavaScript.

1 Like

That’s an interesting idea and I hadn’t thought of that. Does this mean that all of your dependencies go into devDependencies and none into dependencies proper? I would think that with that line of reasoning, any project that uses an asset pipeline like brunch or webpack would always use devDependencies? Is there something particular about phoenix + npm + brunch + bootstrap that would enable this approach?

Like I said, I’m far from a javascript expert. But here is how I separate dependencies from devDependencies in ibgib:

  "dependencies": {
    "bootstrap": "^3.3.7",
    "d3": "^4.2.2",
    "d3-force": "^1.0.2",
    "d3-textwrap": "^2.0.0",
    "font-awesome": "^4.6.3",
    "glslify": "^5.1.0",
    "phoenix": "file:../../deps/phoenix",
    "phoenix-socket": "^1.1.3",
    "phoenix_html": "file:../../deps/phoenix_html",
    "sass-brunch": "^2.6.3"
  "devDependencies": {
    "babel-brunch": "~6.0.0",
    "brunch": "2.7.4",
    "clean-css-brunch": "~2.0.0",
    "css-brunch": "~2.0.0",
    "javascript-brunch": "~2.0.0",
    "uglify-js-brunch": "~2.0.1"

So everything in devDependencies are things that are used at compilation time, and everything else is used to actually run the application. This is supported in most places that I see online, like here, here, the original post I linked, here, here, etc.

That’s why I was pretty sure that what I said was correct. However, if you look at the answer below the accepted answer on SO by wayfarer_boy, he mentions this particular approach is used by Yoeman, i.e. it puts everything in devDependencies. He then recants in his comment and and says that he uses --save for everything but “test and documentation dependencies”.

But, at least Yoeman has this approach (according to him, I have no idea), which certainly isn’t nothing! And interestingly enough, the official bootstrap npm package, it doesn’t mention either flag, and neither does the official bootstrap getting started npm section.

So, whereas at first I thought it’s pretty clear-cut, on second glance your approach does seem interesting, if not unusual. :smile:

EDIT: Looking more at the highly upvoted referenced answer on SO, I would say that you’re saying in this case that because it’s a web app and not a package is why you would put it in devDependencies?

For completeness, there is also a --save-optional (or some variation of optional) for optional dependencies (which are deps that if you are making a library that you can take advantage of, but you have fallbacks if it does not exist). :slight_smile:

Dev Dependency’s are used only at compiling time, no javascript in them is sent to clients, ever.

Dependency’s can be used any time, and you can send their javascript to the clients.

I think from my testing (but not certain), that brunch will only include deps that are non-dev only? That is what I’d been doing at least…

1 Like

dependencies is for modules that need to be installed at runtime. In other words, if node_modules/module doesn’t need to exist at runtime then module doesn’t belong in dependencies.

The idea is that if someone runs something like npm install project or…

git clone
cd project
npm install --production

…then only the modules that are required for project to run are installed.

That’s my understanding, anyway. I could be wrong. :slight_smile:

It depends on the type of project I’m working on. My projects have an empty dependencies when node_modules doesn’t need to exist at runtime.

I imagine there are some valid use cases but in general I agree.

I think the important thing is to understand how dependencies and devDependencies work in practice and use what works best for you.


I just had to do a quick test to ensure I’m not losing it. :smiley:

It appears to work for me:

# This command returns the number of occurrences of "jquery" in priv/static/js/app.js.
$ grep -o jquery priv/static/js/app.js | wc -l

$ npm install --save-dev jquery > /dev/null 2>&1
$ echo 'import "jquery";' > web/static/js/test.js
$ npm run deploy > /dev/null 2>&1

$ grep -o jquery priv/static/js/app.js | wc -l
1 Like

After looking into this more, I note a couple things:

  • You offered yet another link (that I hadn’t hit in my googling) to a highly upvoted question that should have been marked as a duplicate to the other highly upvoted questions that I already linked to.
  • I found an issue for webpack that exactly describes this situation. That is also unresolved.

With these in mind, I can only conclude that there is no real answer to this and that it’s a matter of philosophy and personal upbringing, positioning of the moons, etc.

I would then agree with this statement, except I amend it by removing the “understand how dependencies and devDependencies work”, because nobody does as evidenced by all of the controversy (not surprising in the JS ecosystem). :wink:

So I say:

“I think the important thing is to understand that there is some kind of magical distinction with dependencies and devDependencies, so fiddle with things in practice and use what works best for you.”

Thanks for the discussion and I am now bowing out…I got an Elixir JSON API to build and an Alexa App to connect to it! :smile:

Despite the link to jquery in my brunch file and in package.jspon the JS is inactive.

"dependencies": {
  "bootstrap": "^4.0.0-alpha.6",
  "jquery": "^3.1.1",
  "phoenix": "file:deps/phoenix",
  "phoenix_html": "file:deps/phoenix_html"

modules: {
  autoRequire: {
    "js/app.js": ["jquery","web/static/js/app"]

npm: {
  globals: {"jQuery": "jquery"},
  enabled: true,
  styles: {
    bootstrap: ["dist/css/bootstrap.css"]

Any idea ?

** UPDATE **
To solve it it is required to have below code in app.js :

import $ from “jquery”
import “jquery”

global.jQuery = require(“jquery”) // Needed for tether or bootstrap…
global.Tether = require(“tether”)
global.bootstrap = require(“bootstrap”)

1 Like

Yeah bootstrap is a bit broken for its module handling, surprising with how popular it is…

1 Like