Modifying the Bootstrap Page at the Runtime
Application Shell
The App Shell Model tries to make your website faster by loading the 'important' parts of the web page at first causing a good first impression. The key for this, is to deliver the minimal HTML, CSS and JavaScript required to display the user interface during the first visit, and eventually cache it to be used in future revisits.
The Application Shell in Vaadin is also known as Bootstrap Page or simply index.html.
Modifying the Application Shell
In Vaadin 15+ the user has full control on the index.html
contents, which can by modified in different ways:
In client-side by editing the
frontend/index.html
when the content is static, for instance the<viewport>
tag.In server-side for changes that require some dynamic server content or just when Java syntax is preferred, for example making the application installable by enabling the
@PWA
built-in feature.Implement the
AppShellConfigurator
for cases covered by theAppShellSettings
API, or by annotations.Configure an
IndexHtmlRequestListener
for advanced cases modifying the document structure.
Customizing the Application Shell Template
By default, during the first request, Vaadin parses the frontend/index.html
template file and delivers it with a few modifications as described in the Default Bootstrap Template
This is the best place for customizing the app-shell, for example to put an analytics tag in the page.
...
<head>
<title>My App</title>
</head>
<body>
...
<!-- Google Analytics -->
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-XXXXX-Y', 'auto');
ga('send', 'my-app-bootstrap');
</script>
</body>
Customizing the Application Shell during Runtime
The AppShellConfigurator Interface
In Java code, use the AppShellConfigurator
marker interface rather than editing the index.html
when adding dynamic content during the bootstrap process.
Note |
There must be a single application shell for the entire Vaadin application, and therefore there can be at max one class implementing AppShellConfigurator .
|
Note | AppShellConfigurator is a replacement of the obsolete PageConfigurator interface.
|
The AppShellConfigurator#configurePage Method
Override configurePage
for adding content to the index.html
template by calling the following AppShellSettings
methods:
AppShellSettings#setViewport
to set the viewport value, it replaces the viewport present in theindex.html
template.AppShellSettings#setPageTitle
to set the initial page title, replaces the template title tag.AppShellSettings#setBodySize
to configure the body width and height values.AppShellSettings#addMetaTag
to append meta tags to the head.AppShellSettings#addInlineFromFile
to include content from resource files.AppShellSettings#addInlineWithContents
to add arbitrary content.AppShellSettings#addLink
to add links to the head.AppShellSettings#addFavIcon
to configure the favicon.AppShellSettings#getLoadingIndicatorConfiguration
for configuring loading indicator when legacy bootstrapping is used (deprecated, see details after code example).AppShellSettings#getReconnectDialogConfiguration
for configuring the reconnect dialog when legacy bootstrapping is used (deprecated, see details after code example).AppShellSettings#getPushConfiguration
to customize the push mechanism when legacy bootstrapping is used (deprecated, see details after code example).
public class AppShell implements AppShellConfigurator {
@Override
public void configurePage(AppShellSettings settings) {
settings.setViewport("width=device-width, initial-scale=1");
settings.setPageTitle("A cool vaadin app");
settings.setBodySize("100vw", "100vh");
settings.addMetaTag("author", "bunny");
settings.addFavIcon("icon", "icons/icon-192.png", "192x192");
settings.addLink("shortcut icon", "icons/favicon.ico");
settings.addInlineFromFile(
TargetElement.BODY,
Position.APPEND,
"custom.html",
Wrapping.AUTOMATIC);
settings.addInlineWithContents(Position.PREPEND,
"console.log(\"foo\");", Wrapping.JAVASCRIPT);
}
}
public class ServiceListener implements VaadinServiceInitListener{
@Override
public void serviceInit(ServiceInitEvent event) {
event.getSource().addUIInitListener(uiInitEvent -> {
LoadingIndicatorConfiguration indicator = uiInitEvent.getUI().getLoadingIndicatorConfiguration();
indicator.setApplyDefaultTheme(false);
indicator.setSecondDelay(700000);
PushConfiguration push = uiInitEvent.getUI().getPushConfiguration();
push.setPushMode(PushMode.AUTOMATIC);
ReconnectDialogConfiguration dialog = uiInitEvent.getUI().getReconnectDialogConfiguration();
dialog.setDialogText("reconnecting...");
});
}
}
Java Annotations
Vaadin provide a set annotations for modifying the application shell, though, unlike in previous versions, in Vaadin 15 these annotations must be placed in the application shell class.
@Viewport
to set the viewport value.@PageTitle
to set the initial page title.@BodySize
to configure the body size.@Meta
to append meta tags to the head.@Inline
to include content from resource files in theindex.html
.@PWA
to define application PWA properties.@Push
to configures server push.
@Viewport("width=device-width, initial-scale=1")
@PageTitle("A cool vaadin app")
@BodySize(height = "100vh", width = "100vw")
@Meta(name = "author", content = "bunny")
@Inline(wrapping = Wrapping.AUTOMATIC,
position = Position.APPEND,
target = TargetElement.BODY,
value = "custom.html")
@PWA(name = "Cool Vaadin App", shortName = "my-app")
@Push(value = PushMode.MANUAL, transport = Transport.WEBSOCKET)
public class AppShell implements AppShellConfigurator {
}
Note |
Modifications in the AppShellConfigurator#configurePage do have priority over the equivalent annotations.
|
Note |
Annotations do not cover all the cases that can be done when overriding the AppShellConfigurator#configurePage method
|
The IndexHtmlRequestListener Interface
In addition, for advance cases not covered in the previous section, the content can be modified via an IndexHtmlRequestListener
.
An implementation of the listener should be added via a ServiceInitEvent
when a VaadinService
is initialized. Check the ServiceInitListener tutorial for the details about using Vaadin ServiceInitListeners
.
The example below changes the body class dynamically:
public class MyIndexHtmlRequestListener implements
IndexHtmlRequestListener {
@Override
public void modifyIndexHtmlResponse(
IndexHtmlResponse indexHtmlResponse) {
Document document = indexHtmlResponse.getDocument();
Element body = document.body();
body.classNames(computeBodyClassNames());
}
private Set<String> computeBodyClassNames() {
// Introduce some logic to dynamically change the body class
return Collections.singleton("my-className");
}
}
It can also be provided as a servlet container deployment property with the name useDeprecatedV14Bootstrapping
.