Skip to content

Instantly share code, notes, and snippets.

@beschauer
Last active December 26, 2015 04:48
Show Gist options
  • Save beschauer/7095624 to your computer and use it in GitHub Desktop.
Save beschauer/7095624 to your computer and use it in GitHub Desktop.
Resource Versioning, Cache Busting, Fingerprinting with Playframework 2.1 All resources that are normally located under /assets/xxx now live under /assets/[VERSION]/xxx
�# This is the main configuration file for the application.
# ~~~~~
application.version= "1.0.1"
# Secret key
# ~~~~~
# ...
import com.typesafe.config.ConfigFactory
import sbt._
import Keys._
import play.Project._
object ApplicationBuild extends Build {
val conf = ConfigFactory.parseFile(new File("conf/application.conf")).resolve()
val appVersion = conf.getString("application.version")
// ...
val main = play.Project(appName, appVersion, appDependencies).settings(
// Add your own project settings here
testOptions in Test := Nil,
requireJs += "app.js",
templatesImport += "controllers.TemplateHelper._" // this imports all methods of TemplateHelper in every template file
)
}
@(title: String, loginLevel: Int, appjs: String)(content: Html)<!DOCTYPE html>
<!-- =========== Note how you can use TemplateHelpers 'asset' method to include resources. ============ -->
<head>
<title>MyApp</title>
<script type="text/javascript">
window.baseUrl = '@play.api.Play.current.configuration.getString("application.context")';
window.assetBaseUrl = '@assetBaseUrl()';
</script>
<link rel="stylesheet" media="screen" href="@asset("stylesheets/bootstrap-2.3.2.min.css")" />
</head>
<body>
<script src='@asset("jslib/jquery-1.10.1.min.js")'></script>
<script src='@asset("jslib/bootstrap-2.3.2.min.js")'></script>
@helper.requireJs(core = asset("javascripts/require.js").url, module = asset(appjs).url)
</body>
</html>
# Map static resources from the /public folder to the /assets URL path
GET /assets/:version/*file controllers.VersionedAsset.asset(version, file)
package controllers
import play.api.mvc._
import play.api.{Mode, Play}
import org.joda.time.DateTime
import org.joda.time.format.DateTimeFormat
object VersionedAsset extends Controller {
val RFC1123_DATE_TIME_FORMATTER = DateTimeFormat.forPattern("EEE, dd MMM yyyy HH:mm:ss 'GMT'").withZoneUTC();
val expiresDate = RFC1123_DATE_TIME_FORMATTER.print(new DateTime().plusYears(1))
val lastModifiedDate = RFC1123_DATE_TIME_FORMATTER.print(new DateTime().minusMonths(3))
val maxAge = "max-age=31536000" // a year in seconds
def appVersion =
Play.current.configuration.getString("application.version").getOrElse(throw new RuntimeException(s"application.version must be defined in application.conf"))
def asset(version: String, file: String) = Action { request =>
Assets.at(path = "/public", file)(request) match {
case result => result.withHeaders(
(EXPIRES, expiresDate),
(LAST_MODIFIED, lastModifiedDate),
(CACHE_CONTROL, maxAge)
)
}
}
}
object TemplateHelper {
def asset(file: String) = controllers.routes.VersionedAsset.asset(VersionedAsset.appVersion, file)
def assetBaseUrl() =
(
play.api.Play.current.configuration.getString("application.context") map ( _ + "/assets/" + VersionedAsset.appVersion )
) getOrElse (throw new RuntimeException(s"application.context must be defined in application.conf"))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment