- Rails and Webpack and Webpacker
- Organization of the code
- Adding Webpack-bundle-analyzer
- Async loading of plugins
- jQuery and how to expose/import and use
- Adding into the global scope
- Exposing jquery into global scope
- Ingest dependencies into legacy modules
- Adding fonts
- Font awesome
- Boostrap icons
- Using them as svg
- Using it as font
- feather-icons
- octicons ?
Rails and Webpack and Webpacker
The gem is called webpacker and the js thing is webpack.
All javascript is now located in app/javacscript packed in “packs” at
app/javascript/packs
Organization of the code
Good organization according this video is to have:
- runtime pack – the webpack code
- vendor with all the 3rd party libs
- application.js pack with our code
Add this in your layout, the link_tag is for rails, and the pack_tag’s are for the webpack packs
= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload'
= stylesheet_pack_tag 'application', media: 'all', 'data-turbolinks-track': 'reload'
= javascript_packs_with_chunks_tag 'vendor', 'data-turbolinks-track': 'reload'
= javascript_packs_with_chunks_tag 'application', 'data-turbolinks-track': 'reload'
Adding Webpack-bundle-analyzer
This will give you nice visualization of all the js modules loaded and organized by packs
yarn add Webpack-bundle-analyzer
Then add in config/webpack/development.js
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
environment.plugins.append('BundleAnalyzerPlugin', new BundleAnalyzerPlugin())
Async loading of plugins
Benefit of the webpack by loading the imports only where there are used.
Instead of doing that:
import PDFJS from 'pdfjs/webpack'
$('.pdf-canvas').each(() = {
const url = $(this).data('url')
PDFJS.getDocument(url).then(pdf => {
// ... render
})
}
Do this:
import PDFJS from 'pdfjs/webpack'
$('.pdf-canvas').each(() = {
const url = $(this).data('url')
import('pdfjs/webpack').then(PDFJS) => {
PDFJS.getDocument(url).then(pdf => {
// ... render
})
}
}
Magic comments to use the chunks
import(‘pdfjs/webpack’).then(…)
import(/* webpackChunkName: “pdfjs” */ ‘pdfjs/webpack’).then(…)
This will create a new “pack” file which you can see in the output of the webpack-dev-server
jQuery and how to expose/import and use
Adding into the global scope
If you were to add some javascript to your page that calls a jquery function, it would fail as Javascript wouldn’t understand the $. This is because Webpack doesn’t add anything to the global scope by default. We thus need to add $ to the global scope.
To this add in config/webpack/environment.js
environment.plugins.append(
"Provide",
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
Popper: ['popper.js', 'default']
}))
We can add also an (alias)[https://webpack.js.org/configuration/resolve/]
environment.config.set('resolve.alias', {
jquery: 'jquery/src/jquery'
});
and now we can use it like
import jquery;
links:
- add bootstrap
- example with fancy tree
- (jquery sample)[https://code-and-cookies.com/2020/01/new-rails-6-project/]
Exposing jquery into global scope
Use the expose-loader to expose to the global scope.
Then you will be able to do something like that in the views:
<script>
console.log($('.hello'))
</script>`
Install it with
yarn add expose-loader
and configure it with
// this exposes jquery to be available in the views
environment.loaders.append('expose', {
test: require.resolve("jquery"),
loader: "expose-loader",
options: {
exposes: ["$", "jQuery"],
}
});
Ingest dependencies into legacy modules
Better fix or remove the old code instaad of using this trick.
If we have old code we can try using the imports-loader
yarn add imports-loader
Then use it like that
environment.loaders.append('choosen-js', {
test: require.resolve("choosen-js"),
use: [
loader: 'imports-loader',
options: 'jQuery=jquery,$=jquery,this=>window',
]
});
Adding fonts
Font awesome
Install with
yarn add @fortawesome/fontawesome-free
and the js and the scss in application.js or better in vendor.js
import "@fortawesome/fontawesome-free/js/all";
import "@fortawesome/fontawesome-free/css/all.css";
Do not add anything in the application.scss because this is the old way.
Use it with
<i class="fab fa-twitter fa-2x"></i>
If you want to use the scss solution you have to do
Boostrap icons
The offical repo
yarn add bootstrap-icons
Using them as svg
According this answer we have to add in manifest.js
//= link_directory ../../../node_modules/bootstrap-icons .svg
then use it like
svg.bi.bi-telephone-minus fill="currentColor" width="16" height="16" style="color: red;" viewBox="0 0 16 16"
use xlink:href=asset_path("bootstrap-icons/bootstrap-icons.svg#telephone-minus")
Or if you want you can click on the website and copy/paste the code to embed the SVG directly into the webpage.
Using it as font
Add this at application.js or vendor.js
import "bootstrap-icons/font/bootstrap-icons.css";
The use it like that
i class="bi-alarm bi"
feather-icons
feather-icons git and showcase
yarn add feather-icons
Add this at application.js or vendor.js
const feather = require('feather-icons')
document.addEventListener("turbolinks:load", () => {
feather.replace();
})
Then use it with
i data-feather="circle"
However using javascript for icons doesn’t look right, so let’s switch to the css version.
Put this link in manifest.js
//= link feather-icons/dist/feather-sprite.svg
create a app/assets/stylesheets/feather-icons.scss
.feather {
width: 24px;
height: 24px;
stroke: currentColor;
stroke-width: 2;
stroke-linecap: round;
stroke-linejoin: round;
fill: none;
}
octicons ?
And we have add icons forever