Upload
colin-harrington
View
7.069
Download
2
Embed Size (px)
DESCRIPTION
Presentation about Grails' Resources plugin
Citation preview
Grails' Resource Plugin
Intro
● Resources plugin– http://grails.org/plugin/resources
● Installed by default in Grails 2.0– Available in 1.3.x branches
● Written by Marc Palmer & Luke Daley
Why?
Performance ~ Perception
Performance impacts cost
- less traffic- less load
- better scalability
14 rules
http://stevesouders.com/hpws/rules.php
Good performance tips from Yahoo!
Firefox ySlow pluginGoogle Page Speed - Chrome - Firefox - mod_pagespeed for apache
Rule 1 - Make Fewer HTTP RequestsRule 2 - Use a Content Delivery NetworkRule 3 - Add an Expires HeaderRule 4 - Gzip ComponentsRule 5 - Put Stylesheets at the TopRule 6 - Put Scripts at the BottomRule 7 - Avoid CSS ExpressionsRule 8 - Make JavaScript and CSS ExternalRule 9 - Reduce DNS LookupsRule 10 - Minify JavaScriptRule 11 - Avoid RedirectsRule 12 - Remove Duplicate ScriptsRule 13 - Configure ETagsRule 14 - Make AJAX Cacheable
Example
Example optimized with resources
Modular development
History
● D.I.Y.● 2008 - UI Performance● 2009 - Static Resources Plugin● December 2011 – Resources Plugin included by
default in Grails 2.0 release
DIY
● pre-optimized bundles
● custom filters
● build time jobs
UI Performance plugin
● http://grails.org/plugin/ui-performance/
● minification of CSS and JS● compression● css sprites● bundling of CSS and JS● build time
Resources Plugin
● Pluggable framework for handling static resources
● runtime ":resources:1.2-RC1"
● “This plugin represents a new way of declaring and linking to static resources in your application and plugins. Resource dependencies can be declared (e.g. jQuery UI requires jQuery) and pages simply indicate which resource modules they require. The plugin does the rest, and provides a processing pipeline for advanced optimisations.”
Using Resources in your Layout
<html> <head> <g:layoutTitle/> <r:layoutResources/> </head> <body> <g:layoutBody/> <r:layoutResources/> </body></html>
GSP view
<html> <head> <meta name="layout" content="main"/> <r:require modules="jquery-ui, blueprint"/> <r:script> $(function() { $('#form').dialog('open'); }); </r:script> </head> <body> <div id="form"> Hello World </div> </body></html>
Runtime
● Redirects on legacy URLs to a /static/<resource URI>
● Uses the ProcessingFilter to Process the Resource
Resources
● MyApplicationResources.groovy contains modules, bundles, etc.
● ResourcesArtefactType
– *Resources.groovy
● Definable in Config.groovygrails.resources.modules = { … }
Resource DSLmodules = {
core {
dependsOn 'jquery, utils'
defaultBundle 'ui'
resource url:'/js/core.js', disposition: 'head'
resource url:'/js/ui.js'
resource url:'/css/main.css',
resource url:'/css/branding.css'
resource url:'/css/print.css', attrs:[media:'print']
}
…
}
dependsOn
modules = {
core {
dependsOn 'jquery, utils'
dependsOn 'other'
dependsOn(['heavy', 'metal'])
}
}
resource method
modules = {
ui {
resource '/css/forms.css'
resource '/js/forms.js'
}
}
resource attributes
● url * required● exclude (exclude:'minify')● bundle● disposition● attrs● id● linkOverride● wrapper
– (wrapper: { s -> "<!--if lt IE 8>$s<!endif-->" } )
defaultBundle method
modules = {
core {
defaultBundle 'core-ui'
...
}
ui {
defaultBundle 'core-ui' …
}
}
TagLib
● <r:resource>● <r:img>● <r:renderModule>● <r:script> ● <r:layoutResources>● <r:require>● <r:external>
CSS
● Bundling
● Rewriting
● Minification
yui-minification for css and js
● runtime ":yui-minify-resources:0.1.5"
● http://grails.org/plugin/yui-minify-resources● Confgurable:
– grails.resources.mappers.yuicssminify.includes = ['**/*.css']
– grails.resources.mappers.yuijsminify.includes = ['**/*.js']
– grails.resources.mappers.yuicssminify.excludes = ['**/*.min.css']
– grails.resources.mappers.yuijsminify.excludes = ['**/*.min.js']
– More...
less.css
● Variables● Mixins● Nested Rules● Functions & Operations
● Client side● Server side● Command Line
● compile ":lesscss-resources:1.3.0.3"● http://lesscss.org/
Smart Sprites Resources
● compile ":smart-sprites-resources:0.2"
● http://grails.org/plugin/smart-sprites-resources● Uses Smart Sprites● http://csssprites.org/● Used in UI Performance
Javascript
● jQuery● Bootstrap (out of date?)● Handlebars● dustjs● gsp
disposition
● link disposition (head vs defer)
● Successive calls to <r:layoutResources>– Once in the <head/>– Once before the closing </body> tag
● Blocking the UI!! Don't do it!
● <r:layoutResources disposition='defer'/>
Asset pipeline
● Pluggable pipeline of ResourceMappers
● Include/exclude logic
● Phases
● Configurable map() method
class TestResourceMapper {
def phase = MapperPhase.MUTATION
static defaultExcludes = [ '**/*.png', '**/*.gif', '**/*.jpg', '**/*.jpeg', '**/*.gz', '**/*.zip' ] static defaultIncludes = [ '/images/**' ]
def map(resource, config) { … }}
enum MapperPhase { GENERATION, MUTATION, COMPRESSION, LINKNORMALISATION, AGGREGATION, RENAMING, LINKREALISATION, ALTERNATEREPRESENTATION, DISTRIBUTION, ABSOLUTISATION, NOTIFICATION }
Mapper Phase
● GENERATION
– create new assets = compile less files
● MUTATION
– alter/improve assets (may mean creating new/deleting aggregated resources) = spriting
● COMPRESSION
– reducing the file size but maintaining semantics = minify
● LINKNORMALISATION
– convert all inter asset references into a normal form = css links
● AGGREGATION
– combining multiple assets into one = bundling
Mapper Phase
● RENAMING
– moving of physical assets = hashing
● LINKREALISATION
– convert normalised inter asset references into real form = css links
● ALTERNATEREPRESENTATION
– attach different representations of the asset = gzipping
● DISTRIBUTION
– moving assets to their hosting environment = s3, cdn
● ABSOLUTISATION
– update inter asset references to their distributed equivalent
● NOTIFICATION
– let the world know about the new resources = cache invalidation
cached-resources
● runtime ":cached-resources:1.0"● http://grails.org/plugin/cached-resources● Files/resources use a SHA-256 hash● Delegates to the cache-headers plugin
– ETag header
– Last-Modified header
zipped-resources
● runtime ":zipped-resources:1.0"● http://grails.org/plugin/zipped-resources● Gzip applied to files● Sends the .gz contents
● Sets the Transfer-Encoding header to 'gzip'
cdn-resources
● compile ":cdn-resources:0.2.1"● http://grails.org/plugin/cdn-resources
● grails.resources.cdn.enabled = true● grails.resources.cdn.url = "http://static.mydomain.com/”
● Configurable URL per modules...
Configuration
● Change the /static/ URI prefix: grails.resources.uri.prefix = 'other'
● grails.resources.work.dir
● grails.resources.debug = true
● grails.resources.processing.enabled = false
● grails.resources.rewrite.css
More Config
● grails.resources.adhoc.patterns = ["/images/*", "*.css", "*.js"]
● grails.resources.mappers.cssrewriter.includes = ['**/*.css', '**/*.less']
● grails.resources.mappers.csspreprocessor.includes = ['**/*.css', '**/*.less']
● grails.resources.mappers.cssrewriter.excludes = ['unsafe/**']
● grails.resources.mappers.csspreprocessor.excludes = ['unsafe/**']
● grails.resources.mappers.bundle.excludes = ['unsafe/**/*.css']
Debugging
● Reloading in development
● Debug with ?_debugResources=y
● anti-cache: ?_refreshResources=y
● log4j:● debug "org.grails.plugin.resource"
● println grailsResourceProcessor.dumpResources()
Write your own plugin?
● Dart?
● Sass?
● Javascript templating du jour?
Issues
● Load balancing bugs
● non-DRY elements in Deep hierarchies
● Others?
Questions?
Thank you