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.htmlwhen 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
@PWAbuilt-in feature.Implement the
AppShellConfiguratorfor cases covered by theAppShellSettingsAPI, or by annotations.Configure an
IndexHtmlRequestListenerfor 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#setViewportto set the viewport value, it replaces the viewport present in theindex.htmltemplate.AppShellSettings#setPageTitleto set the initial page title, replaces the template title tag.AppShellSettings#setBodySizeto configure the body width and height values.AppShellSettings#addMetaTagto append meta tags to the head.AppShellSettings#addInlineFromFileto include content from resource files.AppShellSettings#addInlineWithContentsto add arbitrary content.AppShellSettings#addLinkto add links to the head.AppShellSettings#addFavIconto configure the favicon.AppShellSettings#getLoadingIndicatorConfigurationfor configuring loading indicator when legacy bootstrapping is used (deprecated, see details after code example).AppShellSettings#getReconnectDialogConfigurationfor configuring the reconnect dialog when legacy bootstrapping is used (deprecated, see details after code example).AppShellSettings#getPushConfigurationto 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.
@Viewportto set the viewport value.@PageTitleto set the initial page title.@BodySizeto configure the body size.@Metato append meta tags to the head.@Inlineto include content from resource files in theindex.html.@PWAto define application PWA properties.@Pushto 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.