Created
November 2, 2012 20:15
-
-
Save eboto/4004051 to your computer and use it in GitHub Desktop.
Play 2 Assets pipeline
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package assetproviders { | |
import play.api.mvc.Action | |
import play.api.mvc.Controller | |
import play.api.mvc.AnyContent | |
import play.api.mvc.Call | |
/** | |
* This simple interface is meant to mimic the existing interface in Play 2.0 | |
* for the Assets controller it provides. By implementing this it is possible | |
* to mix and combine various AssetProviders to create a custom Asset controller | |
* with additional functionality. | |
*/ | |
trait AssetProvider { this: Controller => | |
/** | |
* This is to be implemented by the concrete class and is supposed to be a | |
* call to the reverse router for the at(path, file) call. | |
*/ | |
protected def assetReverseRoute(file: String): Call | |
/** | |
* This is the method that will be called by the router to serve the | |
* asset to the client. | |
*/ | |
def at(path: String, file: String): Action[AnyContent] | |
/** | |
* This is the method that will be called by the templates mostly to get | |
* a Call that enables them to get the external URL of the asset. | |
*/ | |
def at(file: String): Call | |
} | |
/** | |
* An AssetProvider view of Play's built in Asset controller that can be mixed | |
* into other AssetProviders. | |
*/ | |
trait PlayAssets extends AssetProvider { this: Controller => | |
override def at(path: String, file: String): Action[AnyContent] = controllers.Assets.at(path, file) | |
override def at(file: String): Call = assetReverseRoute(file) | |
} | |
/** | |
* Pipelines fingerprinting for your static assets, which allows you to improve site | |
* performance by setting very long cache expiries. Assets are fingerprinted like this: | |
* original = foo.jpg | |
* fingerprinted = foo-fp-1231343451234.jpg | |
* | |
* Where '-fp-1231343451234' is the 'fingerprint' and '1231343451234' is a checksum of | |
* the file contents. | |
* | |
* We got some inspiration from ruby on rails, but the solution was a bit obvious. | |
* http://guides.rubyonrails.org/asset_pipeline.html#what-is-fingerprinting-and-why-should-i-care | |
*/ | |
trait FingerprintedAssets extends AssetProvider { this: Controller => | |
def defaultPath: String | |
val cacheControlMaxAgeInSeconds: Int | |
/** | |
* This will find files that were fingerprinted. If the file is found with the fingerprint | |
* striped out of its name and the checksum matches the checksum in the fingerprint. Otherwise | |
* it will just return whatever the super.at(path, file) returns. | |
*/ | |
abstract override def at(path: String, file: String): Action[AnyContent] = { /* impl */ } | |
abstract override def at(file: String): Call = { /* impl */ } | |
} | |
/** | |
* Pipelines CDN access for static files. Mix this trait in and provide remoteContentUrl to | |
* have all calls from your views to your assets automatically resolve to a url with the | |
* correct domain. | |
* | |
* Inspired by http://www.jamesward.com/2012/08/08/edge-caching-with-play2-heroku-cloudfront | |
*/ | |
trait RemoteAssets extends AssetProvider { this: Controller => | |
/** | |
* This application's content URL with protocol. For example "https://souefusfisu.cloudfront.net" | |
*/ | |
protected def remoteContentUrl: Option[String] | |
abstract override def at(path: String, file: String): Action[AnyContent] = { /* impl */ } | |
abstract override def at(file: String): Call = { /* impl */ } | |
} | |
} | |
package controllers { | |
import play.api.Play.current | |
import play.api.mvc.Controller | |
import assetproviders.RemoteAssets | |
import assetproviders.FingerprintedAssets | |
import assetproviders.PlayAssets | |
/** Collects all asset transformations into a single trait for use in our website app */ | |
trait FullAssetPipeline | |
extends PlayAssets with RemoteAssets with FingerprintedAssets { this: Controller => } | |
/** | |
* The concrete asset implementation for our website app. This maps to /assets | |
* in the routes file | |
*/ | |
object EgraphsAssets extends Controller with FullAssetPipeline { | |
// This object has a route in our routes file | |
override def assetReverseRoute(file: String) = controllers.routes.EgraphsAssets.at(file) | |
// MIA: boring implementations of abstract methods from the pipeline | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment