How should I reference conditional assets in a rails app? - ruby-on-rails

To install bootstrap and have it work correctly on legacy versions of IE, you need to place this your head:
<!--[if lt IE 9]>
<script src="js/html5shiv.js"></script>
<script src="js/respond.min.js"></script>
<![endif]-->
That's fine on a static site, but how would this work in a Rails app? Do I use sprockets to do this?
I have html5shiv.js located at
root/vendor/assets/javascripts/html5shiv.js
and respond.min.js located at
root/vendor/assets/javascripts/respond.js
How should I go about including these conditional assets?

In application.rb:
config.assets.precompile += %w(html5shiv.js respond.js)
Then add them in your layout:
/[if LT IE 9]
= javascript_include_tag 'html5shiv'
= javascript_include_tag 'respond'
By the way, what about a CDN for those resources?

Related

Why assets served as compiled?

I am using Rails 5.2, and I notice when serving a page, the javascript file being served is compiled, however, I am in development mode.
for example, I get this html:
<script src="/assets/auth0/auth0_dialog.self-73034e01a7da3c346f6c123d6890950c4f1aac7f5f35ca09ced526e9c550328d.js?body=1"></script>
<script src="/assets/auth0/lock_init.self-b564b1f75c18a2fbbe1d41be6af70aa3d1c36c31aeb50cf52017d2ec31ceba10.js?body=1"></script>
for:
= javascript_include_tag "auth0/auth0_dialog"
= javascript_include_tag "auth0/lock_init"
any idea?

How to use third party plugin in rails 6? Using webpacker

How can I use the the third party plugin via webpacker. I dont want to use cloudfare external link in application.html.erb.
Why means, I just want to compile all the plugin while application loading for the initial time.
Thanks in advance :)
<!DOCTYPE html>
<html lang="en">
<head>
<title><%= yield(:title).present? ? yield(:title) : 'Tryblank' %></title>
<meta name="description" content="<%= yield(:description).present? ? yield(:description) : 'Tryblank' %>" />
<%= csrf_meta_tags %>
<%= csp_meta_tag %>
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
<%= stylesheet_pack_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
<script src="https://cdn.jsdelivr.net/npm/sweetalert2#8"></script>
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/lightgallery/1.6.12/css/lightgallery.min.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/lightgallery/1.6.12/js/lightgallery.js" type="text/javascript"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lg-thumbnail/1.1.0/lg-thumbnail.min.js" type="text/javascript"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.19.1/jquery.validate.js" ></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.7.1/css/bootstrap-datepicker3.standalone.min.css" />
<script src="https://code.jquery.com/jquery-2.2.4.min.js" integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.7.1/js/bootstrap-datepicker.min.js"></script>
</head>
<body>
<%# <p class="notice"> notice</p> <p class="alert">alert</p> %>
<%= yield %>
</body>
</html>
application.js
require("#rails/ujs").start()
require("turbolinks").start()
require("#rails/activestorage").start()
require("channels")
require("jquery")
import '../stylesheets/style'
import './default.js'
import './bootstrap_custom.js'
import './side_menu.js.erb'
//import './sweetalert.js'
import './business_hours.js'
import './admin.js'
import './services.js'
import './user_service.js'
I answered a similar question here:
https://stackoverflow.com/a/58794513/12104222
There, I explained how to include jquery, bootstrap and popper.js to a project using yarn, and then two different approaches to actually importing the libraries (or modules) to use them in your app, depending on whether you need to expose the modules as a global plugin (something you probably want only for jQuery and similar global libraries) or not, as a single import (the most common option, which I exemplified with Bootstrap).
Updated with instructions for sweetalert & lightgallery, as requested by OP:
Run $ yarn sweetalert lightgallery lg-thumbnail (or whatever plugins you may need; you can also use yarn sweetalert#2.1.2, etc if you need a specific version of the plugin). That will install the modules in your node_modules directory, and will make them available to Webpacker.
You will also need $ yarn jquery to install jquery as a node module as well.
Edit your config/webpack/environment.js so it looks like this:
# Some other previous code
environment.plugins.append('Provide',
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery'
})
)
module.exports = environment
That will ensure jQuery is exposed to every other plugin that depends on it.
Edit app/javascript/packs/application.js so it looks like this:
require("#rails/ujs").start()
require("turbolinks").start()
require("#rails/activestorage").start()
require("channels")
//require("jquery") //commented as you loaded jQuery before.
import '../stylesheets/style'
import './default.js'
import './bootstrap_custom.js'
import './side_menu.js.erb'
import swal from 'sweetalert' //Note you don't need './' in your path if you import via yarn
import 'lightgallery'
import './business_hours.js'
import './admin.js'
import './services.js'
import './user_service.js'
Import lightGallery.css in your application.scss
Remove these lines from your view, since you will be loading them using webpack:
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/lightgallery/1.6.12/css/lightgallery.min.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/lightgallery/1.6.12/js/lightgallery.js" type="text/javascript"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lg-thumbnail/1.1.0/lg-thumbnail.min.js" type="text/javascript"></script>
<script src="https://code.jquery.com/jquery-2.2.4.min.js" integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44=" crossorigin="anonymous"></script>
By now, you've installed jQuery, lightgallery and sweetalert as webpack modules. I cannot guarantee, however, that this will work in your case since the code you provided looks like it's importing a lot of different plugins from many different sources (webpack, CDN, maybe also sprockets) which can (and probably will) cause conflicts between them.
If possible, I'd recommend you replace every <script> tag with the correct import method for webpack, which is just following the method I described for the plugins you mentioned in this answer, but applying them to your other libraries/plugins.
Edit 2:
Remember that, if you use Turbolinks (and it looks like you do), you need to replace this sort of code:
$(document).ready(function() {
$("#lightgallery").lightGallery();
});
With this:
$(document).on('turbolinks:load', function() {
$("#lightgallery").lightGallery();
});
Good luck!

Custom IE script tag syntax with Slim (Rails)

I want to create a script tag for IE only, like this:
<!--[if lt IE 9]>
<script src="..."></script>
<![endif]-->
The js file is in assets/javascript, so it will be precompiled and i have to point to the digest file via asset_path.
How could I write it in Slim?

Async JavaScript in production environment only?

I'm trying to get my JavaScript (Angular app) to load asynchronously so that the page can render a loading image while the browser downloads the JavaScript later. In production, this works just fine, but not in development, because Sprockets hasn't concatinated all of the files yet.
I'm using the following in my HAML file:
= javascript_include_tag "mio", :async => true
which is working as intended in production:
<script async="async" src="/assets/mio.js"></script>
However, in development the files are all separate, and execute out of order. For example, my Angular Quote Form Controller is executing before Angular has finished loading:
<script async="async" src="/assets/angular.js?body=1"></script>
<script async="async" src="/assets/mio.js?body=1"></script>
<script async="async" src="/assets/mio-ng/controllers/quote_form.js?body=1"></script>
So the question is, can javascript_include_tag ignore the async flag when in development, but not in production?
I found a way to rig this up to work, but I feel it is not the best solution:
= javascript_include_tag "application", :async => Rails.env == "production"

How can i use css with rails and the asset pipeline

I followed the guide but can't apply styles.
How can I make the page background blue?
I have the following file: app/assets/stylesheets/main.css.scss
Contents are: body { background-color: #123456;}
I have the following in my app/assets/application.css.scss file:
/*
*
*= require_self
*= require_tree .
*/
The web page, once loaded includes the following line in the head tag:
<link href="/assets/main.css?body=1" media="all" rel="stylesheet" type="text/css" />
But my webpage is not blue so I am ;)
How do I get the webpage background-color to be blue?
I've stopped and started the server to try and make sure that asset compilation is taking place.
Your css link needs to reference application.css - that is the main file name that the rest of the css is compiled into.
<link href="/application.css?body=1" media="all" rel="stylesheet" type="text/css" />
also, in rails it's preferred to use the asset helpers:
<%= stylesheet_link_tag "application" %>
See http://guides.rubyonrails.org/asset_pipeline.html for more documentation.

Resources