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
Alex Coles
December 06, 2016
Technology
91
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
320
Putting the Hype back in Hypermedia
myabc
1
250
DataMapper
myabc
2
240
Other Decks in Technology
See All in Technology
猫付きpingコマンドを自作
uyuki234
0
240
Sansan Engineering Unit 紹介資料
sansan33
PRO
1
4.9k
Forza Horizon 6 のテレメトリ機能で 自動運転に使えそうな学習データを集める話
henjin0
0
180
まちスペース®とデジタルツインと「まちづくり」
hiro_ogi
0
120
Bits AI を制するものは Datadog を制す / The player that controls Bits AI, controls Datadog
kaminashi
0
100
Webアクセシビリティ入門 2026
recruitengineers
PRO
3
570
モノリス Rails でも日中に rails db:migrate を走らせたい! / Daytime rails db:migrate on Monolithic Rails!
euglena1215
4
580
【Google Cloud Next Tokyo'26】Gemini Enterprise と Oracle AI Database で実現する、業務データ活用を実現する AI エージェント実装
shisyu_gaku
0
250
Breaking the Seal: Static Deobfuscation of Compiled V8 JavaScript Bytecode Malware
hshrzd
0
770
Bits Agent Builder の⼊⾨と活⽤事例
nulabinc
PRO
0
140
Bill One 開発エンジニア 紹介資料
sansan33
PRO
7
19k
制約理論(ToC)入門 2026版
recruitengineers
PRO
8
2.3k
Featured
See All Featured
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
49
10k
Agile Leadership in an Agile Organization
kimpetersen
PRO
0
200
Leadership Guide Workshop - DevTernity 2021
reverentgeek
1
340
ReactJS: Keep Simple. Everything can be a component!
pedronauck
666
130k
Context Engineering - Making Every Token Count
addyosmani
9
1.1k
Design of three-dimensional binary manipulators for pick-and-place task avoiding obstacles (IECON2024)
konakalab
0
540
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
333
23k
JAMstack: Web Apps at Ludicrous Speed - All Things Open 2022
reverentgeek
1
570
The State of eCommerce SEO: How to Win in Today's Products SERPs - #SEOweek
aleyda
2
11k
Designing Experiences People Love
moore
143
24k
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
360
30k
Heart Work Chapter 1 - Part 1
lfama
PRO
8
36k
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?