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
Assets Build Automation
Search
Marconi Moreto
February 25, 2014
Programming
2
310
Assets Build Automation
Automated building of your webapp assets using Gruntjs.
Marconi Moreto
February 25, 2014
Tweet
Share
More Decks by Marconi Moreto
See All by Marconi Moreto
Development Mini Toolbox
marconi
1
170
Introduction to Docker
marconi
4
1.3k
SaltStack 101
marconi
10
1.1k
Concurrency with Gevent
marconi
3
410
Django Quickstart
marconi
1
120
Other Decks in Programming
See All in Programming
SourceGeneratorのススメ
htkym
0
200
登壇資料を作る時に意識していること #登壇資料_findy
konifar
4
1.1k
CSC307 Lecture 08
javiergs
PRO
0
670
Package Management Learnings from Homebrew
mikemcquaid
0
220
AIによるイベントストーミング図からのコード生成 / AI-powered code generation from Event Storming diagrams
nrslib
2
1.9k
Oxlintはいいぞ
yug1224
5
1.3k
MUSUBIXとは
nahisaho
0
130
高速開発のためのコード整理術
sutetotanuki
1
400
Apache Iceberg V3 and migration to V3
tomtanaka
0
160
Spinner 軸ズレ現象を調べたらレンダリング深淵に飲まれた #レバテックMeetup
bengo4com
1
230
CSC307 Lecture 09
javiergs
PRO
1
840
フロントエンド開発の勘所 -複数事業を経験して見えた判断軸の違い-
heimusu
7
2.8k
Featured
See All Featured
Applied NLP in the Age of Generative AI
inesmontani
PRO
4
2k
Docker and Python
trallard
47
3.7k
The Language of Interfaces
destraynor
162
26k
Optimizing for Happiness
mojombo
379
71k
Breaking role norms: Why Content Design is so much more than writing copy - Taylor Woolridge
uxyall
0
160
How to audit for AI Accessibility on your Front & Back End
davetheseo
0
180
The Psychology of Web Performance [Beyond Tellerrand 2023]
tammyeverts
49
3.3k
Typedesign – Prime Four
hannesfritz
42
2.9k
GraphQLとの向き合い方2022年版
quramy
50
14k
The Mindset for Success: Future Career Progression
greggifford
PRO
0
240
AI in Enterprises - Java and Open Source to the Rescue
ivargrimstad
0
1.1k
GitHub's CSS Performance
jonrohan
1032
470k
Transcript
Assets Build Automation Marconi Moreto @marconimjr
Story time...
Classic way: <!doctype html> <html> <head> <title>My Awesome WebApp</title> <link
href="/static/css/somegrid.css" type="text/css" rel="stylesheet"/> <link href="/static/css/plugins.css" type="text/css" rel="stylesheet"/> <link href="/static/css/styles.css" type="text/css" rel="stylesheet"/> </head> <body> ... <script src="/static/js/jquery.js" type="text/javascript"></script> <script src="/static/js/plugins.js" type="text/javascript"></script> <script src="/static/js/app.js" type="text/javascript"></script> </body> </html> Number of requests: 7
None
Concatenate everything: <!doctype html> <html> <head> <title>My Awesome WebApp</title> <link
href="/static/css/app.css" type="text/css" rel="stylesheet"/> </head> <body> ... <script src="/static/js/app.js" type="text/javascript"></script> </body> </html> Number of requests: 3
Quick peak 1/2 body { padding: 0; margin: 0; }
#notification { width: 100%; font-size: 18px; text-align: center; padding: 15px 0; } #notification.success { background: #1abc9c; } #notification.error { background: #e74c3c; } app.css app.js /** * Basic notification class */ function Notification(msg, type) { this.msg = msg; this.type = typeof type !== 'undefined' ? type : 'success'; } Notification.prototype.show = function() { // build notification var notif = document.createElement('div'); notif.id = 'notification'; notif.className = this.type; notif.innerHTML = this.msg; // prepend notificaiton var doc = document.getElementsByTagName("body")[0]; doc.insertBefore(notif, doc.firstChild); }; $(function() { new Notification("Welcome!").show(); })(); Size: 277 bytes Size: 543 bytes
None
Minify everything: <!doctype html> <html> <head> <title>My Awesome WebApp</title> <link
href="/static/css/app.min.css" type="text/css" rel="stylesheet"/> </head> <body> ... <script src="/static/js/app.min.js" type="text/javascript"></script> </body> </html> ✓ Number of requests: 3 ✓ Faster loading time
Quick peak 2/2 body{padding:0;margin:0} #notification{width: 100%;font-size:18px;text- align:center;padding:15px 0} #notification.success{backg round:#1abc9c}
#notification.error{backgro und:#e74c3c} app.min.css app.min.js function Notification(a,b){this.msg=a,this.type="undefined"! =typeof b?b:"success"}Notification.prototype.show=function() {var a=document.createElement("div");a.id="notification",a.classNam e=this.type,a.innerHTML=this.msg;var b=document.getElementsByTagName("body") [0];b.insertBefore(a,b.firstChild)},$(function(){new Notification("Welcome!").show()})(); Size: 277 bytes Size: 177 bytes Size: 543 bytes Size: 352 bytes
None
Why do all these?
None
None
None
But why do we automate?
None
But really, why do we automate?
Focus on fun stuff!
The JavaScript Task Runner
✓ Node ✓ JS/Coffee + JSON ✓ Focus on web
development ✓ Over 2,294 plugins! Things to love about Grunt:
None
Who’s using it? And some more: Wordpress, Opera, etc.
$ npm install -g grunt-cli - package.json - Gruntfile.(js|coffee) Getting
started: Installation: Requirements:
{ "name": "MyAwesomeApp", "version": "0.0.1", "private": true } package.json $
npm install grunt --save $ npm install grunt-contrib-uglify --save $ npm install grunt-contrib-cssmin --save ... $ cat package.json { "name": "MyAwesomeApp", "version": "0.0.1", "private": true, "dependencies": { "grunt": "~0.4.2", "grunt-contrib-uglify": "~0.3.2", "grunt-contrib-cssmin": "~0.8.0" } } Install dependencies:
CSS Minification
module.exports = function(grunt) { grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), cssmin: { styles:
{ files: { 'static/css/app.min.css': ['src/css/*.css'] } } } }); grunt.loadNpmTasks('grunt-contrib-cssmin'); grunt.registerTask('default', ['cssmin']); }; Gruntfile.js Lets run it! $ grunt
JS Minification
module.exports = function(grunt) { grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), cssmin: { styles:
{ files: { 'static/css/app.min.css': ['src/css/*.css'] } } }, uglify: { scripts: { files: { 'static/js/app.min.js': [ 'src/js/jquery.js', 'src/js/plugins.js', 'src/js/app.js' ] } } } }); grunt.loadNpmTasks('grunt-contrib-cssmin'); grunt.loadNpmTasks('grunt-contrib-uglify'); grunt.registerTask('default', ['cssmin']); grunt.registerTask('deploy', ['cssmin', 'uglify']); }; Gruntfile.js: Lets run it! $ grunt deploy
Concatenate on development + minify on deploy
module.exports = function(grunt) { grunt.initConfig({ ... concat: { dist: {
src: ['src/js/**/*.js'], dest: 'static/js/app.all.js' } }, uglify: { scripts: { files: { 'static/js/app.min.js': ['static/js/app.all.js'] } } } }); ... grunt.loadNpmTasks('grunt-contrib-concat'); grunt.registerTask('default', ['cssmin', 'concat']); grunt.registerTask('deploy', ['cssmin', 'concat', 'uglify']); }; Gruntfile.js: Lets run it! $ grunt deploy Install plugin: $ npm install grunt-contrib-concat --save
What about SASS? Updated project structure: $ tree . .
├── public │ └── index.html ├── src │ ├── Gruntfile.js │ ├── js │ │ ├── jquery.js │ │ ├── app.js │ │ └── plugins.js │ ├── package.json │ └── sass │ ├── _plugins.scss │ └── app.scss └── static ├── css │ └── app.min.css └── js ├── app.all.js └── app.min.js #notification { width: 100%; font-size: 18px; text-align: center; padding: 15px 0; &.success { background: #1abc9c; } &.error { background: #e74c3c; } } _plugins.scss body { padding: 0; margin: 0; } @import "plugins"; app.scss
module.exports = function(grunt) { grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), sass: { dist:
{ options: { outputStyle: 'compressed' }, files: { '../static/css/app.min.css': 'sass/app.scss' } } }, concat: { ... }, uglify: { ... } }); grunt.loadNpmTasks('grunt-sass'); grunt.loadNpmTasks('grunt-contrib-concat'); grunt.loadNpmTasks('grunt-contrib-uglify'); grunt.registerTask('default', ['sass', 'concat']); grunt.registerTask('deploy', ['sass', 'concat', 'uglify']); }; Gruntfile.js: Install plugin: $ npm install grunt-sass --save
Watching files
module.exports = function(grunt) { grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), ... watch: {
sass: { files: ['sass/**/*.scss'], tasks: ['sass'] }, concat: { files: ['js/**/*.js'], tasks: ['concat'] }, uglify: { files: ['../static/js/app.all.js'], tasks: ['uglify'] } } }); ... grunt.loadNpmTasks("grunt-contrib-watch"); ... }; Gruntfile.js: Install plugin: $ npm install grunt-contrib-watch --save Watch changes: $ grunt watch
<!doctype html> <html> <head> <title>My Awesome WebApp</title> <link href="/static/css/app.min.css" type="text/css"
rel="stylesheet"/> </head> <body> ... <script src="/static/js/app.min.js" type="text/javascript"></script> </body> </html> index.html
None
None
body { padding: 0; margin: 0; } #left, #right {
width: 290px; height: 315px; float: left; margin-right: 10px; } #left { background: url('../images/left.jpg') no-repeat top left; } #right { background: url('../images/right.jpg') no-repeat top left; } @import "plugins"; app.scss
<!doctype html> <html> <head> <title>My Awesome WebApp</title> <link href="/static/css/app.min.css" type="text/css"
rel="stylesheet"/> </head> <body> ... <script src="/static/js/app.min.js" type="text/javascript"></script> </body> </html> index.html Number of requests: 5
module.exports = function(grunt) { grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), sass: { ...
}, imageEmbed: { dist: { src: ['../static/css/app.min.css'], dest: '../static/css/app.min.css', options: {deleteAfterEncoding : false} } }, ... watch: { sass: { files: ['sass/**/*.scss'], tasks: ['sass', 'imageEmbed'] }, ... } }); grunt.loadNpmTasks("grunt-contrib-watch"); grunt.loadNpmTasks("grunt-image-embed"); grunt.registerTask('default', ['sass', 'imageEmbed', 'concat']); grunt.registerTask('deploy', ['sass', 'imageEmbed', 'concat', 'uglify']); }; Gruntfile.js: Install plugin: $ npm install grunt-image-embed --save
Number of requests: 3
OMG!
Thank you Marconi Moreto @marconimjr http://marconijr.com https://github.com/marconi