Serving a public resource in Play is the same as serving any other HTTP request. It uses the same routing as regular resources: using the controller/action path to distribute CSS, JavaScript or image files to the client.

During the build process, the contents of the public folder are processed and added to the application classpath. When you package your application, these files are packaged into the application JAR file (under the public/ path).

As for any controller mapped in the routes file, a reverse controller is created in controllers.routes.Assets. You use this to reverse the URL needed to fetch a public resource. For example, from a template:

<script src="@routes.Assets.at("javascripts/jquery.js")"></script>

This will produce the following result:

<script src="/assets/javascripts/jquery.js"></script>

Note that we don’t specify the first folder parameter when we reverse the route. This is because our routes file defines a single mapping for the Assets.at action, where the folder parameter is fixed. So it doesn’t need to be specified explicitly.

However, if you define two mappings for the Assets.at action, like this:

The Assets controller automatically manages ETag HTTP Headers. The ETag value is generated from the resource name and the file’s last modification date. (If the resource file is embedded into a file, the JAR file’s last modification date is used.)

When a web browser makes a request specifying this Etag, the server can respond with 304 NotModified.

Usually, using Etag is enough to have proper caching. However if you want to specify a custom Cache-Control header for a particular resource, you can specify it in your application.conf file. For example:

By default Play compiles all managed assets that are kept in the app/assets folder. The compilation process will clean and recompile all managed assets regardless of the change. This is the safest strategy since tracking dependencies can be very tricky with front end technologies.