Hi developer friends!
I am the main developer of this app, and I’m really excited to have it on Enonic Market now.
This app has been almost a year in the making, and it has gone trough a lot of iteration to make it as simple as possible for developers to use.
Why use this?
The value proposition of this app is to reduce the feedback loop – while developing server rendered XP-applications – to a few milliseconds. This is compared to several seconds wait time every time you deploy an xp-app locally.
How does it work?
The app exposes an XP-service (storybook-preview
) that Storybook (with Storybook Server rendering) can use to render a preview of Freemarker (*.ftl) or Thymeleaf (*.html) templates.
You write a story where the id
is the path of the template you want to test (relative to the “resources” directory), and the args
is an object that contains all the variables used in the template (sometimes called the model
).
Example:
This is an example of a story that loads a template-file, and the related css.
/site/parts/article-header/article-header.stories.ts
// Importing the {*.ftl, *.html,*.css}-files creates a dependency graph and
// makes storybook/webpack redraw the preview when the file(s) changes.
import id from "./article-header.ftl";
import "./article-header.css";
import type { Meta, StoryObj } from "@itemconsulting/xp-storybook-utils";
import type { FreemarkerParams } from "./article-header.freemarker";
const meta: Meta<FreemarkerParams> = {
title: "Part/Article Header",
parameters: {
server: { id }, // id = site/parts/article-header/article-header.ftl
},
};
export default meta;
export const articleHeader: StoryObj<FreemarkerParams> = {
name: "Article Header",
args: {
displayName: "Dette er en typisk tittel på en bloggartikkel",
intro: "Ingressfelt kan være relevant noen ganger. Det hender at noen nettredaktører skriver en hel artikkel her.",
tag: "Bloggartikkel",
publishedDate: "2023-05-23T10:41:37.212Z",
},
};
/site/parts/article-header/article-header.ftl
[#-- @ftlvariable name="tag" type="String" --]
[#-- @ftlvariable name="displayName" type="String" --]
[#-- @ftlvariable name="intro" type="String" --]
[#-- @ftlvariable name="locale" type="String" --]
[#-- @ftlvariable name="publishedDate" type="java.time.ZonedDateTime" --]
[#import "/site/views/partials/date/date.ftl" as Date]
<div class="article-header">
[#if tag?has_content]
<div class="text-primary">${tag}</div>
[/#if]
<h1>${displayName}</h1>
[#if intro?has_content]
<div class="intro">
[@processHtml value=intro /]
</div>
[/#if]
[#if publishedDate?has_content]
<div class="published">
[@localize key="articleHeader.published" locale=locale /]
[@Date.shortDate date=publishedDate locale=locale /]
</div>
[/#if]
</div>
Resulting storybook running on localhost:6006
What happens technically?
- The Storybook-app exposes a service called
storybook-preview
.
- Storybook will take the
id
from the story and append it to the baseUrl and the args
become the query params. For the example above Storybook server creates the following HTTP GET (simplified):
http://localhost:8080/_/service/no.item.storybook/storybook-preview/site/parts/article-header/article-header.ftl?locale=no&matchers={"zonedDateTime":"/Date$/","region":"/Region$/i"}&displayName=Dette er en typisk tittel på en bloggartikkel&intro=Ingressfelt kan være relevant noen ganger. Det hender at noen nettredaktører skriver en hel artikkel her.&tag=Bloggartikkel&publishedDate=2023-05-23T10:41:37.212Z
- The XP Storybook-app is configured with the
xpResourcesDirPath
which points to the resources directory on your local development machine. It can now use java.io.File
to read the template file (xpResourcesDirPath
+ id
) from disk. So now re-renders of the file only take a few milliseconds.
- If your Storybook project has the preset-enonic-xp configured, it will enable doing
import id from "./myfile.{ftl,html}"
, because it will configure Storybook with new custom webpack loaders for Freemarker and Thymeleaf. The loaders will create a dependency graph for imports in those template files, and provide HMR when changing any file in the dependency tree.
Documentation
Check out the documentation in the xp-storybook-utils repo to learn more about how to work with Storybook and XP.
Have a great day all!
– Tom Arild