Usage and examples
Contents
Introduction
There are multiple ways of deploying and using lib-static in your application. Below we expore the most common approaches. This includes how you may set up lib-static to service different files, using different cache headers.
Common
Follow these initial steps to get started, they are common for all the examples below:
-
Use an existing Enonic app, or create a new one with the following command:
enonic sandbox create static_tutorial -t essentials -f enonic create com.example.static -r starter-ts
-
Add the lib-static dependency with a single line
build.gradledependencies { include "com.enonic.lib:lib-static:${libVersion}" }
Replace ${libVersion}
with the desired version of lib-static.
You can now move on to the various examples below:
Service example
This demonstrates how to serve assets using a http service.
This example showcases:
-
Serving assets from the default static folder
-
Overriding "immutable" default cache headers
-
Disabling serving of index.html files
-
Start by adding a service to your app.
/src/main/resources/services/myStatic/myStatic.tsimport { RESPONSE_CACHE_CONTROL, requestHandler, } from '/lib/enonic/static'; import Router from '/lib/router'; const router = Router(); router.all('{path:.*}', (request) => { return requestHandler( request, { cacheControl: () => RESPONSE_CACHE_CONTROL.SAFE, (1) index: false, (2) } ); }); export const all = (request) => router.dispatch(request);
1 As the files are not hashed, override the default immutable cache header 2 Disable serving of index.html files -
Place a folder and stylesheet in the app:
/src/main/resources/static/css/style.cssbody { color: mediumblue; }
/src/main/resources/static/
is the default location where lib static will look for the files -
Add a page controller that links to the stylesheet.
/src/main/resources/site/pages/dynamic/dynamic.tsimport {serviceUrl} from '/lib/xp/portal'; // Static URL helper function const myStaticUrl = (path: string) => `${serviceUrl({service: 'myStatic'})}/${path}`; export const get = () => { return { body: `<!DOCTYPE html> <html> <head> <title>Dynamic Page with static assets</title> <link rel="stylesheet" href="${myStaticUrl('css/style.css')}"/> </head> <body> <main> <h1>Dynamic Page with static assets</h1> <p>All text on this page shoule be mediumblue.</p> </main> </body> </html>`, status: 200 }; };
-
Create a site with a page using this controller, you should instantly see the result.
Site mapping example
Developers using site engine may want to serve the assets from a pretty URL, rather than a service endpoint.
This example demonstrates
-
use of relativeMappedPath
-
using a custom static folder location
-
Create a controller that will serve the files:
site/controllers/myController/myController.tsimport { mappedRelativePath, requestHandler, } from '/lib/enonic/static'; import Router from '/lib/router'; const router = Router(); router.get('{path:.*}', (request) => { log.info('mapped get request:%s', JSON.stringify(request, null, 4)); return requestHandler( request, { relativePath: mappedRelativePath('mymapping'), (1) root: '/site/controllers/myController/files', (2) } ); }); export const all = (request) => router.dispatch(request);
1 relativeMappedPath must match the mapping in site.xml
below2 Defines a custom location where the controller will look for static files -
Define the mapping in your
site.xml
file.site/site.xml<site> <mappings> <mapping controller="/site/controllers/myController/myController.js" order="1"> <pattern>/mymapping(/.*)?</pattern> </mapping> </mappings> </site>
-
Add a file to the static files folder. In this case we place the files together with the controller:
site/controllers/myController/files/css/styles.cssbody { color: green; }
-
Build, deploy and add the application to a site. The files will be served from site-relative mapping path (in this case
/mymapping/css/styles.css
).
Webapp example
Lib static is also capable of acting like a webserver, serving html-files. In this example we use XP’s /webapp feature to do the job. To make the example as realistic as possible, we use a React SPA created with Vite.
Read more about XP webapps |
This example demonstrates advanced use-cases like:
-
Custom Cache control handling
-
Fallback handling to SPA file for 404
-
Custom static folder location
-
Create a new React app using Vite
npm create vite@latest my-app-name -- --template react-ts cd my-app-name
-
Replace the default App.tsx file with this:
/src/vite/App.tsximport './App.css' import { BrowserRouter, Link, Route, Routes } from "react-router-dom"; function App() { return ( <BrowserRouter basename='/webapp/com.example.static'> {/* <1> */} <Routes> <Route path="/" element={<Link to="/bookmarkable">Bookmarkable</Link>}/> <Route path="/bookmarkable" element={<Link to="/">Home</Link>}/> <Route path="*" element={<div> <h1>404</h1> <Link to="/">Go home</Link> </div>}/> </Routes> </BrowserRouter> ) } export default App
You may serve the webapp from any context path (and domain) using vHosts. Make sure the baseUrl in your React app is compliant with the deployment. -
From the React app folder, build the static webapp:
npm install npm run build
-
Copy the static webapp files from the React app
dist/
folder into your Enonic app. In this casesrc/main/resources/webapp/files/
-
In the Enonic app, create a webapp controller that will serve the SPA
src/main/resources/webapp/webapp.tsimport { RESPONSE_CACHE_CONTROL, defaultCacheControl, requestHandler, spaNotFoundHandler, } from '/lib/enonic/static'; import Router from '/lib/router'; const router = Router(); router.get('{path:.*}', (request) => requestHandler( request, { // Override the defaultCacheControl contentType, path, resource, }) => { // The "webapp/files/vite.svg" file has no contentHash if (path.startsWith('/vite.svg')) { return RESPONSE_CACHE_CONTROL.SAFE; } // fall back to defaultCacheControl for all other assets. return defaultCacheControl({ contentType, path, resource, }); }, // Fallback to SPA index.html when asset not found notFound: spaNotFoundHandler, root: '/webapp/files', } )); export const all = (request) => router.dispatch(request);
-
Build and deploy the Enonic app containing the SPA, you should see the result by visiting http://localhost:8080/webapp/com.example.static