Asset Library
Contents
Introduction
A simple solution to serving static assets for your Enonic application. Generates unique fingerprint URLs and sets immutable cache headers for CDN/edge and client caching. Create URLs to your assets with bundled assetUrl function.
| To host a static webapp, or for more fine-grained control over static assets, check out lib-static instead. |
Usage
-
Place your asset files in your project’s
src/main/resources/assets/folder -
Add a dependency to your
build.gradlefile:dependencies { include "com.enonic.lib:lib-asset:${libVersion}" } -
If you are going to call
assetUrlfrom TypeScript code, you’ll need to install type definitions from NPM:npm install --save-dev @enonic-types/lib-assetThen mark the library as external in your
tsup.config.tsfile (if you are using Tsup):tsup.config.tsexternal: [ ... '/lib/enonic/asset', ] -
Import and use the library in your controller:
JavaScript
var assetLib = require('/lib/enonic/asset'); var url = assetLib.assetUrl({path: 'path/to/asset.ext'});TypeScript
import {assetUrl} from '/lib/enonic/asset'; const url = assetUrl({path: 'path/to/asset.ext'});
Configuration
The library may optionally be tuned by addding a config file. Below is a sample config with default values:
{
"root": "/assets", (1)
"cacheControl": "public, max-age=31536000, immutable", (2)
"staticCompress": true <3>,
"cacheBust": true (4)
}
| 1 | The folder in your app where the static files will be placed - relative to /src/main/resources
|
||||
| 2 | Cache-Control header value to be sent with 304 and 200 responses.
|
||||
| 3 | For requests with accept-encoding br or gzip, library will look for, and serve a compressed version of the requested asset if it exists.
|
||||
| 4 | Optionally disable application fingerprinting. This is handy if all assets contain fingerprints in their filenames.
|
Asset service
Url
The Asset library bundles a service that will handle the actual serving of assets. A service URL may look something like this: /_/service/{app-name}/asset/{app-fingerprint}/path/to/asset.ext
If Cache Busting is disabled (cacheBust: false), the URL will look like this /_/service/{app-name}/asset/path/to/asset.ext
In case of a mismatched fingerprint, the service will still responds with the asset contents and 200 code. But with a Cache-Control: private, no-store header. This prevents cache-pollution and makes website rendering more resilient to app redeployments especially in development when app fingerprint changes rapidly. |
Etag
Service calculates and caches ETag for each requested asset. Cache is cleared on application restart. ETag is used to respond with 304 Not Modified for conditional requests.
| In XP dev mode ETags are not generated or cached. |
| ETag is useful even if Cache-Control contains immutable directive. CDNs and Chrome browser ignore immutable. |
API
The library exposes the following API:
assetUrl function generates a URL pointing to a static file.
Parameters
| Name | Type | Description | ||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
params |
object |
Input parameters
|
Returns
string : The generated URL.
Example
JavaScript
const url = assetLib.assetUrl({
path: 'styles/main.css'
});
TypeScript
const url = assetUrl({
path: 'styles/main.css'
});
Migrating from lib-portal
Lib-asset replaces the asset hosting feature that has been part of XP core. As of XP 7.15, this feature will be deprecated, and developers should migrate to lib-asset (or lib-static) instead
Follow the steps below to migrate from the native asset handling to lib-asset.
-
Add lib-asset dependency to your build.gradle file.
-
Change the imports of assetUrl from
/lib/xp/portalto/lib/enonic/asset. -
If you have used
portal.assetUrldirectly within Thymeleaf templates. Migrate by passing the assetUrlBase from your controller instead. See example below:
Thymeleaf migration
If you are using Thymeleaf templating, follow this practical example of how to migrate.
- Controller
-
From
import {render} from '/lib/thymeleaf'; const VIEW = resolve('./thymeleaf-template.html'); export function get() { const model = {}; return { body: render(VIEW, model) }; }Toimport {render} from '/lib/thymeleaf'; import {assetUrl} from '/lib/enonic/asset'; const VIEW = resolve('./thymeleaf-template.html'); export function get() { const model = { assetUrlBase: assetUrl({path: ''}) }; return { body: render(VIEW, model) }; } - Thymeleaf template
-
From
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <link th:href="${portal.assetUrl({'_path=styles.css'})}" rel="stylesheet" type="text/css"/> </head> <body> </body> </html>To<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <link th:href="${assetUrlBase} + '/styles.css'" rel="stylesheet" type="text/css"/> </head> <body> </body> </html>
The legacy portalLib.assetUrl also supported an optional, but extremely rarely used application parameter. This parameter is not supported by lib-asset, as the URLs will always be relative to the current application. |