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
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
Alex Coles
December 06, 2016
Technology
90
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
120
How a language reflects its people
myabc
0
110
Rails: beyond the asset pipeline (RubyC)
myabc
0
150
Frontend Choices (Tropical Ruby)
myabc
1
810
Frontend Choices (RubyConf Portugal)
myabc
1
480
Frontend Choices
myabc
0
72
Frontend Choices
myabc
0
310
Putting the Hype back in Hypermedia
myabc
1
250
DataMapper
myabc
2
240
Other Decks in Technology
See All in Technology
Webの技術とガジェットで子どもも大人も楽しめるワクワク体験を提供する / Qiita Tech Festa Day 2026
you
PRO
1
160
生成 AI 時代にいま一度「問い合わせ」について考えてみる
kazzpapa3
1
130
AIが当たり前の組織で エンジニアはどう育つか
nishihira
1
970
設計レビューとAIハーネスで向き合う AIが生み出した新しいボトルネックの対処法 / Design Reviews and AI Harnesses Against New Bottlenecks Created by AI
nstock
4
430
AI Coding Agent時代のcdk-nagガードレール 〜組織ルールを強制CIで守り抜く設計の挑戦〜
mhrtech
3
510
探索・可視化・自動化を一本化 Amazon Quickでデータ活用スピードを上げる方法
koheiyoshikawa
0
170
ここは地獄!つらい朝会を体験することで、チームとしてのより良い振る舞いに気づくワークショップ / The stand-up meeting from hell in the game industry
scrummasudar
0
230
Alphaモジュール使っていいのかい!?いけないのかい!?どっちなんだいっ!?
watany
1
320
“それは自分の仕事じゃない"を越えて行け
yuukiyo
1
520
SoccerMaster: A Vision Foundation Model for Soccer Understanding
kzykmyzw
0
170
副作用のある Lambda でも Lambda Power Tuning は使えるのか / lambda-power-tuning-side-effects
koukihosaka
1
140
41歳でAWSが好きすぎてITエンジニアになったおっさんの話
yama3133
1
740
Featured
See All Featured
The Mindset for Success: Future Career Progression
greggifford
PRO
0
430
Leo the Paperboy
mayatellez
8
1.9k
More Than Pixels: Becoming A User Experience Designer
marktimemedia
3
470
Code Review Best Practice
trishagee
74
20k
CoffeeScript is Beautiful & I Never Want to Write Plain JavaScript Again
sstephenson
162
16k
Connecting the Dots Between Site Speed, User Experience & Your Business [WebExpo 2025]
tammyeverts
11
970
Dominate Local Search Results - an insider guide to GBP, reviews, and Local SEO
greggifford
PRO
0
210
10 Git Anti Patterns You Should be Aware of
lemiorhan
PRO
659
62k
The Spectacular Lies of Maps
axbom
PRO
1
870
Site-Speed That Sticks
csswizardry
13
1.3k
The Cult of Friendly URLs
andyhume
79
7k
Max Prin - Stacking Signals: How International SEO Comes Together (And Falls Apart)
techseoconnect
PRO
0
320
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?