Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Taking Rails beyond the asset pipeline (Worksho...
Search
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
Alex Coles
December 06, 2016
Technology
94
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Taking Rails beyond the asset pipeline (Workshop at RubyDay Italia)
Alex Coles
December 06, 2016
More Decks by Alex Coles
See All by Alex Coles
How a language reflects its people (Brighton Ruby)
myabc
0
130
How a language reflects its people
myabc
0
110
Rails: beyond the asset pipeline (RubyC)
myabc
0
150
Frontend Choices (Tropical Ruby)
myabc
1
820
Frontend Choices (RubyConf Portugal)
myabc
1
480
Frontend Choices
myabc
0
73
Frontend Choices
myabc
0
320
Putting the Hype back in Hypermedia
myabc
1
250
DataMapper
myabc
2
240
Other Decks in Technology
See All in Technology
Level Up Your CDK DX: 5 Tools I’ve Been Building
gotok365
2
190
Sony-DroidKaigi2026
sony
1
310
Jetpack Compose で挑む新聞紙面UI ─ 複合ジェスチャー・ポリゴン記事領域・適応的ページ構成という3つの壁/droidkaigi2026
nikkei_engineer_recruiting
0
190
Bet AI Day 2026丨Production-Ready AI Agents — エンタープライズの実務を任せるための設計と運用
layerx
PRO
3
2k
Hub & Spoke 環境のネットワークルーティングを分解してみる
tsuyataku
1
520
データエンジニアの困りごとをDevinと一緒に解消する
10xinc
2
790
作り直せるコードは迅速に 作り直せないDBは慎重に - AI時代のプロダクトエンジニアが「判断の不可逆性」で開発速度を変える話
kinosuke01
0
190
AI時代に、プロダクトの数だけ積み上がる所有コストをどうエンジニアリングするか / Engineering the Cost of Ownership
kzkmaeda
0
940
AI-DLCって実際どう? 〜聞きたいこと全部聞いてみる〜
news_it_enj
0
220
多摩川(.dev)ランニング入門 / Tamagawa.dev#3
fujiwara3
3
330
本番に近いテストをもっと手軽に - Postmanで広がるAPIテストの世界 / Expanding the World of API Testing with Postman
yokawasa
1
240
Does an AI Watermark Survive Translation?
machinetranslation
0
520
Featured
See All Featured
Raft: Consensus for Rubyists
vanstee
141
7.7k
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
35
2.6k
Into the Great Unknown - MozCon
thekraken
41
2.7k
How to build an LLM SEO readiness audit: a practical framework
nmsamuel
1
890
Bash Introduction
62gerente
615
220k
Principles of Awesome APIs and How to Build Them.
keavy
128
18k
Code Reviewing Like a Champion
maltzj
528
40k
How To Speak Unicorn (iThemes Webinar)
marktimemedia
1
570
Connecting the Dots Between Site Speed, User Experience & Your Business [WebExpo 2025]
tammyeverts
11
1k
StorybookのUI Testing Handbookを読んだ
zakiyama
31
6.9k
A Guide to Academic Writing Using Generative AI - A Workshop
ks91
PRO
1
410
SEO in 2025: How to Prepare for the Future of Search
ipullrank
3
3.8k
Transcript
Taking Rails beyond the asset pipeline a workshop RubyDay Italia,
Firenze | Novembre 2016
Benvenuto
prima di iniziare
Pre-requisites recent Ruby (2.2+) recent Node (6.9.1+) an existing Rails
app (4.2/5.0) – or example app
Node on macOS brew update brew install yarn
Node on Windows & Linux https://yarnpkg.com/en/docs/install
Frontend has changed
asana
typecast
blocs
So how can Rails keep up?
psst… ditch the asset pipeline
buon pomeriggio RubyDay Italia!
About me @myabc github.com/myabc alexbcoles.com
where I work
what I work on
31 August 2011 Ciao Rails 3.1!
gem wrappers
$ gem list --remote jquery | wc -l 349
Bower
1. gem Using an integration like or gem bower-rails bower
gem install bower-rails source 'https://rubygems.org' gem 'bower-rails'
2. Load path config.assets.paths << File.join(Rails.root, 'bower_components')
3. rails-assets.org source 'https://rubygems.org' gem 'rails' source 'https://rails-assets.org' do gem
'rails-assets-bootstrap' gem 'rails-assets-angular' gem 'rails-assets-leaflet' end
Bower only solves dependency management
Things you might need Dependency management Pre and post-processing Code
loading Code bundling Tree shaking
Sprockets plugins alexspeller/non-stupid-digest-assets
Sprockets plugins Post-processing JS/CSS uses PostCSS project autopre xer uses
(formerly 6to5), requires Sprockets 3 ai/autopre xer-rails TannerRogalsky/sprockets-es6 Babel
Problem with Sprockets No standard plugin con guration style Cannot
control pre/post-processing order Asset dependencies
Things you might need Dependency management Pre and post-processing Code
loading Code bundling
Webpack
Webpack configuration + entry point // webpack.config.js module.exports = {
context: __dirname + '/app', entry: 'rubydayit-app.js', output: { filename: '[name].js', path: path.join(__dirname, '..', 'app', 'assets', 'javascripts', 'bundles'), publicPath: '/assets/bundles' } }
Requiring JS single files and dependencies require('./another-file'); //= require ./another-file
(Sprockets) var angular = require('angular'); var jQuery = require('jquery'); require('jquery-ui');
Requiring JS a tree var requireTemplate = require.context('./app/controllers', true, /\.js$/);
requireTemplate.keys().forEach(requireTemplate); //= require_tree ./app/controllers (Sprockets)
Requiring assets require('jquery-ui/ui/jquery-ui'); // .js (default) require('jquery-ui/themes/base/jquery.ui.core.css'); require('jquery-ui/themes/base/jquery.ui.datepicker.css'); require('select2/select2'); //
.js (default) require('select2/select2.css');
Requiring assets quick start require('jquery-ui/ui/jquery-ui'); // .js (default) require('!style-loader!css-loader!jquery-ui/themes/base/jquery.ui.core.css'); require('!style-loader!css-loader!jquery-ui/themes/base/jquery.ui.datepicker.css');
Requiring assets with a bit of config // webpack.config.js module.exports
= { context: __dirname + '/app', entry: 'rubydayit-app.js', module: { loaders: [ { test: /\.css$/, loader: 'style-loader!css-loader' }, { test: /\.png$/, loader: 'url-loader?limit=100000&mimetype=image/png' }, { test: /\.gif$/, loader: 'file-loader' }, { test: /\.jpg$/, loader: 'file-loader' } ]} } require('jquery-ui/ui/jquery-ui'); // .js (default) require('jquery-ui/themes/base/jquery.ui.core.css'); require('jquery-ui/themes/base/jquery.ui.datepicker.css');
Requiring assets body { background: url(/assets/bundles/background-texture.jpg) } /* border-image: url(border-image.png);
*/ .box { border-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFoAAA…'); }
Loaders and plugins Webpack is built on the concept of
loaders and plugins
Loaders
Loaders Loaders are transformations that are applied on les. They
preprocess les. I. e. they can transform Co eeScript to JavaScript.
Chaining Loaders eslint ← co ee json ← yaml style
← postcss ← css ← sass ngtemplate-loader ← markdown
Requiring Rails- style translation files $ yarn add --dev json-loader
yaml-loader I18n.translations = I18n.translations || {}; I18n.translations.en = require('!json!yaml!config/locales/en_US.yml').en; I18n.translations.de = require('!json!yaml!config/locales/en_DE.yml').de;
Transpiling (ES6 → ES5) $ yarn add --dev babel-loader module:
{ loaders: [ { test: /\.js$/, exclude: /node_modules/, loader: 'babel-loader'} ] }
Transpiling (ES6 → ES5) // app-defaults.js export default { favouriteConf:
'RubyDay Italia' }; // app.js import appDefaults from './app-defaults.js'; class ExampleApp { constructor() { console.log(appDefaults.favouriteConf); } } export default ExampleApp;
Legacy code support $ yarn add --dev exports-loader module: {
loaders: [ { test: /[\/]angular\.js$/, loader: 'exports?angular' } ] }
One more thing…
http://xkcd.com/303/
Hot reloading
Hot reloading colektivo/song-song-song gaearon/react-hot-loader
Instructions Building a vanilla Rails 5 application
Generate a new Rails app rails new TimeTracker git init
and git commit after each step.
Generate Rails scaffolding
Project ./bin/rails generate scaffold Project name:string:required colour:string TimeEntry ./bin/rails generate
scaffold TimeEntry project:references begin_at:datetime end_at:datetime note ./bin/rake db:migrate
Add materialize-sass and spruce up the application
Example application https://github.com/myabc/webpack-rails-rubydayit
Transforming the application with Webpack 2.0
Webpack 2 yarn add --dev
[email protected]
In webpack.config.js const webpack
= require('webpack'); const path = require('path'); module.exports = { entry: './app/assets/javascripts/application.js', output: { filename: 'application.js', path: path.join(__dirname, 'public', 'javascripts') } }
Babel yarn add --dev babel-loader babel-core yarn add --dev babel-preset-es2015
module.exports = { // ... module: { loaders: [ { test: /\.js$/, exclude: /node_modules/, loader: 'babel-loader', query: { presets: ['es2015'] } } ] } }
Sass/CSS Support yarn add --dev sass-loader css-loader node-sass yarn add
--dev
[email protected]
const ExtractTextPlugin = require('extract-text-webpack-plugin'); module.exports = { // ... module: { loaders: [ // ... { test: /\.scss$/, loader: ExtractTextPlugin.extract({loader: "css-loader!sass-loader"}) } ] }, plugins: [ new ExtractTextPlugin("../stylesheets/application.css") ] }
jQuery yarn add --dev jquery yarn add --dev expose-loader module.exports
= { // ... module: { loaders: [ { test: require.resolve("jquery"), loader: "expose-loader?$!expose-loader?jQuery" } ] } }
Materialize Framework yarn add --dev materialize-css
Rails libraries (asset pipeline analogues) yarn add --dev jquery-ujs yarn
add --dev turbolinks
Adapt application.js //= require jquery import jQuery from 'jquery'; //=
require jquery_ujs import 'jquery-ujs'; //= require turbolinks import Turbolinks from 'turbolinks'; Turbolinks.start(); //= require materialize-sprockets import 'materialize-css'; import './../stylesheets/application.scss';
Adapt application.css -@import "materialize/components/color"; +@import "~materialize-css/sass/components/color"; $primary-color: #5d4ca0 !default; $secondary-color:
#38d59c !default; -@import "materialize" +$roboto-font-path: "~materialize-css/fonts/roboto/"; +@import "~materialize-css/sass/materialize"; module.exports = { // ... module: { loaders: [ { test: /\.eot(\?v=\d+\.\d+\.\d+)?$/, loader: "file-loader" }, { test: /\.(woff|woff2)$/, loader: "url-loader?prefix=font/&limit=5000" { test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/, loader: "url-loader?limit=10000&mimetype=application/ { test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, loader: "url-loader?limit=10000&mimetype=image/svg+xm ] } }
Run yarn run webpack
Integrate with Rails rake webpack – or – rake assets:precompile
Foreman gem install foreman foreman start # Procfile rails: bundle
exec rails server -e ${RAILS_ENV:="development"} -p 3000 webpack: yarn webpack -- --watch --progress
Disabling the Rails asset pipeline
in a new app rails new app --skip-sprockets rails new
app --skip-javascript --skip-turbolinks --skip-action-cable
in an existing app # config/application.rb -require 'rails/all' +require 'rails'
+require 'active_model/railtie' +require 'active_job/railtie' +require 'active_record/railtie' +require 'action_controller/railtie' +require 'action_mailer/railtie' +require 'action_view/railtie' +require 'action_cable/engine' +require 'rails/test_unit/railtie' - config.assets.debug = true - config.assets.quiet = true rm config/initializers/assets.rb
Rails integration /// manifest-84b43dda218a2c29ce11f4f7b9ca4e5f.json { "assets": { "1downarrow.png": "1downarrow-d2055955ce2927de07f2e33abdbfdc1b.png", "1uparrow.png":
"1uparrow-a4eef1942dd999e6a16e84c1c8122b8a.png", "2downarrow.png": "2downarrow-e8bc5b59fa922f68637dc22b4a467f5c.png" } }
Rails integration # app/helpers/application_helper.rb def webpack_bundle_tag(bundle) src = if Rails.configuration.webpack[:use_manifest]
manifest = Rails.configuration.webpack[:asset_manifest] filename = manifest[bundle] "#{compute_asset_host}/assets/#{filename}" else "#{compute_asset_host}/assets/#{bundle}-bundle" end javascript_include_tag(src) end http://clarkdave.net/2015/01/how-to-use-webpack-with-rails/
Conclusion
Grazie!
Domande?