• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
The new static resources framework
 

The new static resources framework

on

  • 4,092 views

My talk on the new Resources plugin for Grails, at Groovy Grails Exchange 2010

My talk on the new Resources plugin for Grails, at Groovy Grails Exchange 2010

Statistics

Views

Total Views
4,092
Views on SlideShare
4,092
Embed Views
0

Actions

Likes
8
Downloads
43
Comments
0

0 Embeds 0

No embeds

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    The new static resources framework The new static resources framework Presentation Transcript

    • The new staticresources framework
    • About meMarc PalmerPaid to develop WeceemFounder at NoticeLocal and Spotty MushroomOld skool Grails user since 0.4Plugin writing maniac
    • Resource management Web performance
    • Eternal caching Minifying Zipping Bundling Load order
    • Old ProblemsAntJavaBoilerplate codeSpring MVC configCode verbosity
    • New ProblemsDownload performanceComplex UI from plugins
    • Your application Admin UICustom CSS Security UICustom JS Scaffolding CSS JS JS +CSS Blueprint jQuery jQuery UI
    • Optimization hellWho includes resources & when?Is the resource already optimized?Load orderPerformance: I want control
    • Plugin version conventions help:grails-blueprint-0.9grails-jquery-1.4.3grails-jquery-ui-1.8.2
    • Resources pluginResource declaration DSLDependency resolutionResource tagsMapping pipelineModular and extensibleProcessed at runtime
    • Runtime?!
    • Runtime?!
    • Only at startup!Works in any environmentCan be bypassedSupports reloadingTiny trade-off
    • Installing itmarcmacbook:AwesomeApp marc$ grails install-plugin resourcesWelcome to Grails 1.3.1 - http://grails.org/Licensed under Apache Standard License 2.0Grails home is set to: /usr/local/grails-1.3.1Base Directory: /Users/marc/Projects/AwesomeAppResolving dependencies...Dependencies resolved in 1172ms.Running script /usr/local/grails-1.3.1/scripts/InstallPlugin.groovyEnvironment set to developmentInstalling zip ../checkout/Resources/grails-resources-1.0-RC1.zip... ... [mkdir] Created dir: /Users/marc/.grails/1.3.1/projects/AwesomeApp/plugins/resources-1.0-RC1 [unzip] Expanding: /Users/marc/Projects/checkout/Resources/grails-resources-1.0-RC1.zip into /Users/marc/.grails/1.3.1/projects/AwesomeApp/plugins/resources-1.0-RC1Installed plugin resources-1.0-RC1 to location /Users/marc/.grails/1.3.1/projects/AwesomeApp/plugins/resources-1.0-RC1. ...Resolving plugin JAR dependencies ...Executing resources-1.0-RC1 plugin post-install script ...Plugin resources-1.0-RC1 installedmarcmacbook:AwesomeApp marc$
    • So far so...?Before After
    • Resource DSLFile: grails-app/config/AwesomeResources.groovymodules = { grailsDefaults { resource url:[dir:css, file:main.css] resource url:[dir:js, file:application.js], disposition:head resource url:[dir:js/prototype, file:prototype.js] } myStuff { dependsOn grailsDefaults resource url:[dir:css, file:branding.css] resource url:[dir:js, file:ui-logic.js] }}
    • Changes to GSPFile: grails-app/views/index.gsp<html> <head> <title>Welcome to Grails</title> <meta name="layout" content="main" /> <r:use modules="myStuff"/> </head> <body><!-- ... --> </body></html>
    • What does this page do? What does it need to do it?Explicit resource tags are wrong
    • Changes to layoutFile: grails-app/views/layouts/main.gsp<html> <head> <title><g:layoutTitle default="Grails" /></title> <r:layoutResources /> <link rel="shortcut icon" href="${r.resource(dir:images,file:favicon.ico)}" type="image/x-icon" /> <g:layoutHead /> </head> <body> <div id="spinner" class="spinner" style="display:none;"> <img src="${r.resource(dir:images,file:spinner.gif)}" alt="Spinner" /> </div> <div id="grailsLogo" class="logo"><a href="http://grails.org"> <img src="${r.resource(dir:images,file:grails_logo.png)}" alt="Grails" border="0" /></a> </div> <g:layoutBody /> <r:layoutResources /> <script type="text/javascript"> oneLineAmazingUI(); </script> </body></html>
    • Link disposition<head> <r:layoutResources/> <!-- head --></head><body> ... <r:layoutResources/> <!-- defer --></body>
    • The basic tags<script src="..."><script src="..."> <r:use modules="myStuff"/><link rel="stylesheet" ... /><link rel="stylesheet" ... /><g:resource .../> <r:resource .../><img .../> <r:img .../>
    • Disposition in DSLFile: grails-app/config/AwesomeResources.groovymodules = { grailsDefaults { resource url:[dir:css, file:main.css] resource url:[dir:js, file:application.js], disposition:head resource url:[dir:js/prototype, file:prototype.js] } myStuff { dependsOn grailsDefaults resource url:[dir:css, file:branding.css] resource url:[dir:js, file:ui-logic.js] }}
    • Better...Before After
    • Bundlingmodules = { grailsDefaults { resource url:[dir:css, file:main.css] resource url:[dir:js, file:application.js], disposition:head resource url:[dir:js/prototype, file:prototype.js], bundle: core } myStuff { Cross-module bundle! dependsOn grailsDefaults defaultBundle core resource url:[dir:css, file:branding.css] resource url:[dir:js, file:ui-logic.js] }}
    • Dependency overridesmodules = { grailsDefaults { defaultBundle core resource url:[dir:css, file:main.css] } myStuff { dependsOn grailsDefaults, blueprint defaultBundle core Text resource url:[dir:css, file:branding.css] resource url:[dir:js, file:ui-logic.js] } overrides { jquery { defaultBundle core } jquery-ui { resource id:js, bundle: core resource id:theme, bundle: core } blueprint { resource id:main, bundle: core } }}
    • Deferred inline JS<r:script> initUIThatDoesNotSuck();</r:script>
    • We love the debugDevelopment reloadsTurn it all off: add ?_debugResources=yCache defeat: add ?_refreshResources=yX-Grails-Resources-Original-Src:/bundle-grailsDefaults.js, /js/application.js, /js/prototype/prototype.js
    • What just happened?Declarative resourcesSingle tag mechanismOptimal, smart orderingResource de-dedupingBundling
    • Now the fun part
    • Mapping pipeline Copy to work dir Apply mappers Modify resource Add response handler Update URI
    • Mapper Artefactsclass TestResourceMapper { def priority = Integer.MAX_VALUE def map(resource, config) { Text def file = new File(resource.processedFile.parentFile, "_${resource.processedFile.name}") assert resource.processedFile.renameTo(file) resource.processedFile = file resource.updateActualUrlFromProcessedFile() }}
    • Bundling Mapper /js/jquery-ui/jquery-ui.css /css/blueprint/screen.css /css/main.css /bundle_main.css
    • CSS rewriting Before /css/main.css: body {Both CSS and image background-image: url(../images/bg.png);may be renamed }and/or moved After /bundle_main.css: body { background-image: url(../changed.png); }
    • Resources Others
    • Zipped Resourcesgrails install-plugin zipped-resourcesCompresses files to xxx.css.gzKeeps URI the sameSets Content-Encoding: gzip
    • Cached Resourcesgrails install-plugin cached-resourcesRenames to SHA256 digest of contentsShortens name to base62 encodingFlattens directory structureSets Expires to 1 year
    • /js/some-bloated-lib/plugin/foo.js/b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9.js /UpLdvv429fMac6FhEx5FMU2F3Cg1yj4HwUGmihFvjYR.js
    • In production already
    • Config conventionsgrails.resources.<mapper>.excludes = [...]grails.resources.modules = { ... }grails.resources.debug = truegrails.resources.work.dir = ...grails.resources.uri.prefix = staticgrails.resources.adhoc.patterns = ...
    • Integration into core DSL Grails Core Dependency resolution Tags Mapping pipelinegrails-resources 2.0 Bundling CSS Rewriting Mapper pluginsgrails-xxxx-resources e.g. zipped-resources
    • FutureMinifyCSS SpritesSmart image links with auto w & hE.S.P. - externalising inline JSFlavours (content variants)CDN up loaders
    • Special thanks... Peter Ledbrook Luke Daley Stéphane Maldini Robert Fletcher Burt Beckwith
    • Q & A and linksSample app:http://bit.ly/awesomeapp1http://bit.ly/awesomeapp2http://grails.org/plugin/resourceshttp://grails.org/plugin/zipped-resourceshttp://grails.org/plugin/cached-resourceshttp://noticelocal.comhttp://www.experienceoz.com.auhttp://www.icescrum.orgAlso check out some unsung plugins:taxonomy, invitation-only, cache-headers,one-time-data, email-confirmation