Ask A Question

Notifications

You’re not receiving notifications from this thread.

How to use Bootstrap with Webpack & Rails Discussion

Thanks for posting this and the previous video on using tailwindcss. It's helpful to see the main themes reinforced in each of the videos. One thing that I'm struggling with is what seems like a violation of POLS and the Rails-way in general where we are now putting SCSS files inside a javascripts folder. I understand that webpacker can just figure this out for us, but if I'm debugging a styling issue in an app I'm unfamiliar with I'm not sure I'd start by looking in a javascripts folder. Is there not a way to keep the separation of concerns explicit and store the stylesheets outside of the javascripts folder?

Reply

The recommended place for stylesheets in Rails 6 is still the asset pipeline. Tailwind is a css framework generated by JS so it needs to be more tied to things than Bootstrap.

This is all just side effects of whats going on in modern frontend. Rails is just trying to make that easier, unfortunately it is pretty messy I think, but its also doing more complex things now.

Reply

@Chris Bloom

You can set up webpacker to look in app/assets too. I tend to keep using app/assets/javascripts and app/assets/stylesheets, but app/javascripts for vue/stimulus/… components.

See for example:
https://gist.github.com/risen/076916a3cea81c83cb0752760772d8bf

Reply

Hi Chris,

Another concern is the location of custom javascript. I am new to Rails so please excuse my ignorance.
In Rails 5 we would add custom js to their own .coffee files. For Blog model I would write custom js in blog.coffee file and so on.
In Rails 6 all javascript gets added to a single file i.e application.js
How can I keep them seggregated?

Reply

I've created a demo app with Rails 6 + Webpacker + Bootstrap (with CoreUI), no Sprockets https://github.com/jasl/cybros_core

Reply

What are the advantages of running Rails without Sprockets, or rather, what is YOUR rationale for not including Sprockets.. Very interested to hear why.

Reply

Hey Chris ,

I'm getting this error:

Webpacker can't find application in /Users/robthomas/Dropbox/rails/sample/public/packs/manifest.json. Possible causes:

  1. You want to set webpacker.yml value of compile to true for your environment unless you are using the webpack -w or the webpack-dev-server.
  2. webpack has not yet re-run to reflect updates.
  3. You have misconfigured Webpacker's config/webpacker.yml file.
  4. Your webpack configuration is not creating a manifest. Your manifest contains: { }

Extracted source (around line #10):


    <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
    <%= stylesheet_pack_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
    <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>

Reply

The error is on the

<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
Reply

You can run bin/webpack to run webpack and see what the compilation error was.

Reply

Did you later find a way to solve this? I have the same issue today.

Reply

I'm getting

error Command "webpack" not found.
Reply

Did you yarn install?

Reply

I did and I got this:

yarn install v1.16.0
[1/4] 🔍  Resolving packages...
success Already up-to-date.
✨  Done in 0.45s.

Reply

Hi there,
What is stylesheet_pack_tag really for in Rails 6? I mean if you import your styles in packs/application.js as done in this episode, webpack doesn't generate any css file. Moreover if you inspect your HTML there is no reference to css file neither.

I have done teh same in a sample app, without including stylesheet_pack_tag and the styles are anyway applied to the view.

This is making me very confused,

Reply

The stylesheet pack tag is used for serving stylesheets in production, or in development if you have it configured that way.

Reply

@chris any comment on using stylesheet_pack_tag with Hot Module Reloading (hmr)? The README states:

If you have hmr turned to true, then the stylesheetpacktag generates no output, as you will want to configure your styles to be inlined in your JavaScript for hot reloading. During production and testing, the stylesheetpacktag will create the appropriate HTML tags.

From Sigfrid's comment above, I'm guessing we should avoid stylesheet_pack_tag and instead import the css in packs/applications.js.

This article suggests a similar approach:

In order to do so [use hmr], we need to activate it in webpacker.yml
and not import the stylesheets via stylesheetpacktag since they will be included from packs/application.js

However, it seems to me that the suggested solution still uses stylesheet_pack_tag:

# packs/application.js
import './stylesheets'

and

# app/views/layouts/application.html.erb
<%= stylesheet_pack_tag 'stylesheets', 'data-turbolinks-track': 'reload' unless Webpacker.dev_server.hot_module_replacing? %>
Reply

Hi there,

thanks for all of the webpack/rails 6 tutorials. They've been really helpful in upgrading a very old rails app to the latest and greatest.

I'm having one small error however. I have a couple of Bootstrap modal dialogs that get populated via an AJAX request. These POST data to the server, which responds with a JS file with

$('#myModal').modal('hide');

WIth the old asset_pipeline method this worked, but I'm now getting this error:

Uncaught TypeError: $(...).modal is not a function

if I include a jQuery command in the file it's available, but any bootstrap function isn't. Any idea on how to expose all of the Bootstrap functions to the entire application?

Reply

Looks like i am not alone.

Reply

The $(…).modal is not a function is usually caused because scripts are loaded in the wrong order . The browser will execute the scripts in the order it finds them. If in a script you attempt to access an element that hasn't been reached yet then you will get an error. Make sure that you don't have a script above one that it requires.

Plugin dependencies

Some plugins and CSS components depend on other plugins. If you include plugins individually, make sure to check for these dependencies in the docs. Also note that all plugins depend on jQuery (this means jQuery must be included before the plugin files).

Multiple jQuery instances

Sometimes this warning may also be shown if jQuery is declared more than once in your code. The second jQuery declaration prevents bootstrap.js from working correctly. The problem is due to having jQuery instances more than one time. Take care if you are using many files with multiples instance of jQuery. Just leave one instance of jQuery and your code will work.

Reply

Thanks for the reply @leneborma

I should have been a little clearer in my explanation. The modal dialog, and all other bootstrap JS (eg tooltips, popovers etc), works well when browsing around the site normally, it's just when I return Javascript from the server after processing the form that appeared in the modal dialog that I get that error.

Step by step:

1) Browse to "New Order Page"
2) Fill in form
3) Click on "Add New Item" button, which opens a modal dialog (via data-behaviour tags) that retrieves a form from the server.
4) Submit the "Add New Item" form. This returns some javascript from the server (via AJAX) which puts a new row on the bottom of the order, and attempts to close the modal dialog. It's at this point that the $('#myModal').modal('hide'); causes an error.

So, I'm not sure why it works at the start, and then stops working when processing the Javascript from the server. The jQuery that adds the new row works, but the modal command fails. There's nothing in the Javascript from the server that reloads the jQuery, so I'm not sure if it's Turbolinks being weird, or if it's something altogether.

Thanks.

Reply

Hey, same issue here, did you find anything out?

Thanks.

Reply

Find the solution in the @Jun Jiang repo cybros_core.
We need to expose jQuery to the window object :

# packs/application.js

import JQuery from 'jquery';
window.$ = window.JQuery = JQuery;
Reply

You are a lifesaver, man.

Reply

Thanks a lot !

Reply

Why HTML rendering faster instead css/js on this tutorial? Can they explain to me, thank you

Reply

Chris thanks for the tutorial.

I've noticed though in a comment you mentioned its still best to use css inside assets/stylesheets.

However with this in place you can't use mixins.
If my style sheet is in javascript/stylesheets the mixin has no problems

When i add @import "../node_modules/bootstrap/scss/bootstrap"; to my stylesheet inside assets stylesheets, the mixins work but thats making webpack redundant so im at a loss.

Doesnt this completely make the asset pipeline redundent or am i missing something ??

Reply

You should be able to use mixins in the asset pipeline, as long as your filename ends in .scss so it gets processed with scss.

It won't hurt to use Webpacker for everything. In fact, you need to in some cases like when you're using TailwindCSS.

Images don't really need to go through it since they don't need to be preprocessed and if you have simpler CSS, then the asset pipeline is still around for that.

Reply

Thanks for the reply.

I can use mixins if i import bootstrap into a .scss stylesheet inside of assets/stylesheets.

If i use the setup in the video then i can use bootstrap javascript but mixins are not available inside .scss assets/stylesheets. They are only available in javascript/stylesheets.

I thought it may be some error on my side but after trying three different fresh rails projects all had the same outcome


h1 {
color: white;
}
@include media-breakpoint-only(xs) {
h1 {
margin-top: 500px;
}
}

Thats the simple scss im using.
I'll stick to using webpack then for stylesheets. If its all loaded using yarn doesnt make sense to add it another way just for styling.

adding the below into asset pipeline stylesheet fixes the mixin problem though.

@import "../node_modules/bootstrap/scss/bootstrap";

I might just remove the asset pipeline all together seeing as though im not going to use it at all and webpack can handle images too.

Reply

Chris,

I followed your instructions, and everything works well except when a view is rendered from an action of a controller that does not inherit from ApplicationController. If the controller inherits directly from ActionController::Base, the view is not styled by bootstrap.

What's the deal with that? Any insight you can offer would be greatly appreciated!

Reply

Does it render a different layout? And if so, have you included the stylesheet tag in that layout?

Reply

Chris, thanks for the qick reply!

Your comment about "layout" inspired me to read the docs and now I understand how controllers decide what layout to use. Inserting layout "application" in the controller inheriting from ActionController::Base fixed the issue. I now understand too that I could have made a sperate layout with the same name as the controller, or its parent, and put the stylesheet tag in it, and all would work as expected.

Appreciate your help! Keep up the great work!

Reply

Hey Chris,

I'm getting the following output when trying to deploy to Heroku:

2019-12-06T07:10:10.191890+00:00 app[web.1]: * Environment: production
2019-12-06T07:10:13.694812+00:00 heroku[web.1]: State changed from starting to crashed
2019-12-06T07:10:13.476484+00:00 app[web.1]: ! Unable to load application: NoMethodError: undefined method `stylesheets' for Rails:Module
2019-12-06T07:10:13.476614+00:00 app[web.1]: bundler: failed to load command: puma (/app/vendor/bundle/ruby/2.6.0/bin/puma)
2019-12-06T07:10:13.476667+00:00 app[web.1]: NoMethodError: undefined method `stylesheets' for Rails:Module

Since I'm a Rails newbie I'm not sure exactly what this means or what to do. The URL for my app on Heroku is here: https://limitless-basin-97153.herokuapp.com/

And my app on Github is here: https://github.com/raybullard/ruby-rails-tutorial

Have you seen these errors before? Any and all help is appreciated!

Thanks,

Ray

Reply

doesnt work on rails 6.0.2.rc1 any advice?

Reply

Sounds like you probably missed a step somewhere. I just installed Rails 6.0.2.rc1 and went through the screencast. Everything works correctly.

Reply

Hi Chris,
I did yarn add bootstrap jquery popper.js and import bootstrap into the app.
Also, bootstrap's popover and tooltip style works well.
But when I add a toast in page and run $('div.toast').toast('show') in chrome's console, it says $(...).toast is not a function
Do you know what's wrong?

Reply

Sounds like you missed a step. I just updated the repository to include toasts in the example and they work just fine.

https://github.com/gorails-screencasts/bootstap-with-webpack-4/commit/49846a028f0d6674b0024fbd4c1f6051c8757884

Compare your code with the repository and see what you missed.

Reply

Hi Chris,
thanks for your reply.
I just recreate a rails project, add bootstrap and config everything follow your video. And when I put a toast html block in page, it did show.
but when I run $('#toast').toast('hide') in browser's console, it still warning

Uncaught TypeError: $(...).toast is not a function
at <anonymous>:1:13

is there any thing wrong about how I use toast() function.

Reply

Uncaught TypeError: $(...).toast is not a function
at :1:13

The $(…).toast is not a function is usually caused because scripts are loaded in the wrong order . The browser will execute the scripts in the order it finds them.

For example, bootstrap depends on jQuery , so jQuery must be referenced first. So, you must called the jquery.min.js and then bootstrap.min.js like the following:

Multiple jQuery instances

Sometimes this warning may also be shown if jQuery is declared more than once in your code. The second jQuery declaration prevents bootstrap.js from working correctly. The problem is due to having jQuery instances more than one time. Take care if you are using many files with multiples instance of jQuery. Just leave one instance of jQuery and your code will work.

http://net-informations.com/jq/iq/modal.htm

Reply

Hi Chris,

thanks so much for this tutorial! :-)
I've been able to follow the process and setup a rails app, that's working like a charm in "development".
When I'm trying to change to "production" with:
export RAILS_ENV=production
rake assets:precompile
rails s
I'm always ending up with my content getting served with no CSS/Bootstrap.
I assume, I'm missing a (few) step(s) when moving to production.
Any hint appreciated! Thanks in advance!

Reply

I can`t even imagine that to find info you need for disertation could be so difficult. But I found that information, so that is why I will share with you http://bestresearchpaper.com (the service which can edit your dissertations and make it perfect). Hope there are students and that help you.

Reply

Hi i followed the tutorial and my Dropdown menus are not working within bootstrap. Any ideas ?

Reply

I'm having exactly the same issue. I've tried every tutorial I can find online but can't solve the problem.

Reply

I'll bet you got tricked into using Bootstrap 5 instead of Bootstrap 4 like I did. That means your selectors need to change from:

    $('[data-toggle="tooltip"]').tooltip()
    $('[data-toggle="popover"]').popover()

to

    $('[data-bs-toggle="tooltip"]').tooltip()
    $('[data-bs-toggle="popover"]').popover()
Reply

Actually, I was even dumber than that. I installed Bootstrap 4.6.0 in my project, but I copied text from the docs for Bootstrap 5.

So I didn't really need to change those selectors, I just needed to copy the right text from the Bootstrap docs.

Reply

You are absolutely right. Thank you so much for the help!

Reply

Hi Chris,

This video is great, thank you very much.
I am having an issue, I wonder if you can help.
Sorry if it's an obvious thing, but I am relatively new and can't find the answer to fix it.

```Processing by PagesController#home as HTML
Rendering pages/home.html.erb within layouts/application
Rendered pages/home.html.erb within layouts/application (Duration: 0.0ms | Allocations: 5)
[Webpacker] Compiling...
[Webpacker] Compilation failed:
[webpack-cli] Failed to load '/Users/Lorenzo/code/LorenzoXavier/planned_maintenance/config/webpack/development.js'
[webpack-cli] TypeError: Cannot read property 'plugins' of undefined
at Object. (/Users/Lorenzo/code/LorenzoXavier/planned_maintenance/config/webpack/environment.js:3:13)
at Module._compile (/Users/Lorenzo/code/LorenzoXavier/planned_maintenance/node_modules/v8-compile-cache/v8-compile-cache.js:192:30)
at Object.Module._extensions..js (node:internal/modules/cjs/loader:1137:10)
at Module.load (node:internal/modules/cjs/loader:973:32)
at Function.Module._load (node:internal/modules/cjs/loader:813:14)
at Module.require (node:internal/modules/cjs/loader:997:19)
at require (/Users/Lorenzo/code/LorenzoXavier/planned_maintenance/node_modules/v8-compile-cache/v8-compile-cache.js:159:20)
at Object. (/Users/Lorenzo/code/LorenzoXavier/planned_maintenance/config/webpack/development.js:3:21)
at Module._compile (/Users/Lorenzo/code/LorenzoXavier/planned_maintenance/node_modules/v8-compile-cache/v8-compile-cache.js:192:30)
at Object.Module._extensions..js (node:internal/modules/cjs/loader:1137:10)

Completed 500 Internal Server Error in 2130ms (ActiveRecord: 0.0ms | Allocations: 5754)```

Reply

Rails 6 & Bootstrap 5 update

Installing packages

  • Bootstrap and jQuery can stay the same, although Bootstrap 5 doesn't use jQuery anymore so it's actually not needed for this.

  • javascript yarn add @popperjs/core
    

    instead of

    yarn add popper.js
    

Importing bootstrap into application.js

import * as bootstrap from 'bootstrap'

Selecting all tooltips

document.addEventListener('turbolinks:load', () => {
  var tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'))
  var tooltipList = tooltipTriggerList.map(function (tooltipTriggerEl) {
    return new bootstrap.Tooltip(tooltipTriggerEl)
  })
})

Note: as mentioned above the data attribute has changed data-bs-toggle="tooltip. You can do the same thing for popovers.

Reply

Thanks for this, saved me some trouble!

Reply

Oh Lord!! I wish this comment was pinned to the top. We're all probabaly following along with this tutorial now and using bs5. I did come across this solution after about an hour of Googling.

Then read the comments hoping I could help someone else possibly stuck with tooltip and popover not triggering. Came across this!!!

Should have read the comments first lol.

Nice work @Nick.

Reply

Also going to add that I had issues with the tooltips triggering after I left the page and came back so to help with any conflicts with Turbolinks I changed addEventLstener to:

document.addEventListener('turbolinks:load', function(event) {

Works much better now. Just in case anyone else is having that issue.

Reply
Join the discussion
Create an account Log in

Want to stay up-to-date with Ruby on Rails?

Join 85,376+ developers who get early access to new tutorials, screencasts, articles, and more.

    We care about the protection of your data. Read our Privacy Policy.