{"id":877,"date":"2017-02-21T08:53:23","date_gmt":"2017-02-21T07:53:23","guid":{"rendered":"http:\/\/tomaszdziurko.com\/?p=877"},"modified":"2017-02-21T08:53:23","modified_gmt":"2017-02-21T07:53:23","slug":"forcing-wicket-place-javascript-files-bottom","status":"publish","type":"post","link":"http:\/\/tomaszdziurko.com\/2017\/02\/forcing-wicket-place-javascript-files-bottom\/","title":{"rendered":"Forcing Wicket to place JavaScript files at the bottom"},"content":{"rendered":"

When you add any Wicket component library e.g. \u00a0Wicket-Bootstrap<\/a> to your project, usually it adds some JavaScript and CSS resources to every\u00a0page or panel. But the problem is that these JS files are added in the <head> section of your page\u00a0while all Internet knowledge says that\u00a0JS should be placed at the bottom of the page for a better performance and faster loading times. In this post I will show how we could configure Wicket to place JS files wherever we want.<\/p>\n

Initial project setup<\/h2>\n

Let’s start with a simple one-page-one-form Wicket application counting days from user’s birthday:<\/p>\n

<\/p>\n

It has a dependency to mentioned earlier Wicket-Bootstrap because we need its DatePicker component:<\/p>\n

<dependency>\r\n  <groupId>de.agilecoders.wicket<\/groupId>\r\n  <artifactId>wicket-bootstrap-core<\/artifactId>\r\n  <version>0.10.11<\/version>\r\n<\/dependency>\r\n<dependency>\r\n  <groupId>de.agilecoders.wicket<\/groupId>\r\n  <artifactId>wicket-bootstrap-extensions<\/artifactId>\r\n  <version>0.10.6<\/version>\r\n<\/dependency><\/pre>\n

Our web page contains a form, one text field and one date picker:<\/p>\n

public class HomePage extends WebPage {\r\n    \r\n\tprivate String name;\r\n\tprivate Date birthDate;\r\n\r\n\tpublic HomePage(final PageParameters parameters) {\r\n\t  super(parameters);\r\n\r\n\t  add(new FeedbackPanel(\"feedbackPanel\"));\r\n          Form<HomePage> form = new Form<HomePage>(\"form\", new CompoundPropertyModel<>(this)) {\r\n            @Override\r\n            protected void onSubmit() {\r\n                info(format(\"Hello %s. It's nice to meet you! You are %d days old!\", name, calculateDaysSinceBirthDay(birthDate)));\r\n            }\r\n          };\r\n        \r\n          form.add(new TextField(\"name\").setRequired(true).setLabel(Model.of(\"Name\")));\r\n          form.add(new DateTextField(\"birthDate\", new DateTextFieldConfig()\r\n                .autoClose(true)\r\n                .withLanguage(\"pl\")\r\n                .withFormat(\"dd\/MM\/yyyy\"))\r\n            .setLabel(Model.of(\"Date of birth\"))\r\n            .setRequired(true)\r\n          );\r\n          add(form);\r\n      }  \r\n\r\n      private int calculateDaysSinceBirthDay(Date birthDate) {\r\n        return Days.daysBetween(LocalDate.fromDateFields(birthDate), LocalDate.now()).getDays();\r\n      }\r\n    \r\n}<\/pre>\n

Problem<\/h2>\n

When we run our application we will see that all Bootstrap related JS files are\u00a0placed in the page header:<\/p>\n

<head>\r\n  <!-- ... -->\r\n  <script type=\"text\/javascript\" src=\".\/wicket\/resource\/de.agilecoders.wicket.extensions.markup.html.bootstrap.references.BootstrapDatepickerJsReference\/js\/datepicker-ver-1484131947646.js\"><\/script>\r\n  <script type=\"text\/javascript\" src=\".\/wicket\/resource\/de.agilecoders.wicket.extensions.markup.html.bootstrap.references.BootstrapDatepickerLangJsReference\/js\/lang\/bootstrap-datepicker.pl-ver-1484131947646.js\"><\/script>\r\n  <script type=\"text\/javascript\" id=\"bootstrap-js\" src=\".\/wicket\/resource\/de.agilecoders.wicket.webjars.request.resource.WebjarsJavaScriptResourceReference\/webjars\/bootstrap\/3.3.7-1\/js\/bootstrap-ver-1484131946909.js\"><\/script>\r\n  <!-- ... -->\r\n<\/head><\/pre>\n

It is not what we wanted, so we need to configure\u00a0our application to add JS files somewhere at the bottom.<\/p>\n

Solution<\/h2>\n

First, let’s start with some background. Each time when a component wants to add something to page header (for example using IHeaderContributor<\/a>) it creates a new instance of HeaderItem <\/a>object. By default all HeaderItems are rendered in <head><\/em>, but we could modify this behaviour using\u00a0IHeaderResponseDecorator<\/a>\u00a0and\u00a0FilteringHeaderResponse<\/a>\u00a0to separate HeaderItems into two places to render: header and defined place in our page body.<\/p>\n

First, we should define a place where all JS files should be rendered by adding a <wicket:container><\/em> element with id:<\/p>\n

<!DOCTYPE html>\r\n<html xmlns:wicket=\"http:\/\/wicket.apache.org\">\r\n\t<body>\r\n\t\t<!-- ... -->\r\n\t\t<wicket:container wicket:id=\"footer-container\"\/>\r\n\t\t\r\n\t<\/body>\r\n<\/html><\/pre>\n

and add it to the Page class:<\/p>\n

add(new HeaderResponseContainer(\"footer-container\", \"footer-container\"));<\/pre>\n

Next step is to configure a response decorator and response filter that will direct some items to our footer-container<\/em> bucket. This should be done in init()<\/em> method of our WicketApplication class:<\/p>\n

@Override\r\npublic void init()\r\n{\r\n    super.init();\r\n    \r\n    IBootstrapSettings settings = new BootstrapSettings();\r\n    Bootstrap.install(this, settings);\r\n\r\n    setHeaderResponseDecorator(new JavaScriptToBucketResponseDecorator(\"footer-container\"));\r\n}<\/pre>\n

Our decorator should use a filter that is already in Wicket core module, a\u00a0JavaScriptFilteredIntoFooterHeaderResponse<\/a>\u00a0that does exactly what we need:<\/p>\n

A header response that creates two buckets. The header bucket will contain all references to CSS and markup from the <head> section from the page. The other bucket will contain all other header items, and you will need to add a HeaderResponseContainer to the footer of your page (typically just before the end body tag) to render those items.<\/p><\/blockquote>\n

So it will split all our HeaderItems into two buckets, one (default) that will be rendered in page header and second rendered where we placed footer-container<\/em> element. Working version of our decorator looks as presented below:<\/p>\n

public class JavaScriptToBucketResponseDecorator implements IHeaderResponseDecorator {\r\n    private String bucketName;\r\n\r\n    public JavaScriptToBucketResponseDecorator(String bucketName) {\r\n        this.bucketName = bucketName;\r\n    }\r\n\r\n    @Override\r\n    public IHeaderResponse decorate(IHeaderResponse response) {\r\n        return new JavaScriptFilteredIntoFooterHeaderResponse(response, bucketName);\r\n    }\r\n}<\/pre>\n

After that we can rebuild our application and see that all our Bootstrap related JS files are rendered at the\u00a0bottom of our page, improving performance and overall user experience of our users.<\/p>\n","protected":false},"excerpt":{"rendered":"

When you add any Wicket component library e.g. \u00a0Wicket-Bootstrap to your project, usually it adds some JavaScript and CSS resources to every\u00a0page or panel. But the problem is that these JS files are added in the <head> section of your page\u00a0while all Internet knowledge says that\u00a0JS should be placed at the bottom of the page for a better performance and faster loading times. In this post I will show how we could configure Wicket to place JS files wherever we want. Initial project setup Let’s start with a simple one-page-one-form Wicket application counting days from user’s birthday: It has a […]<\/p>\n","protected":false},"author":2,"featured_media":882,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[36],"tags":[118,102,21,78,112],"_links":{"self":[{"href":"http:\/\/tomaszdziurko.com\/wp-json\/wp\/v2\/posts\/877"}],"collection":[{"href":"http:\/\/tomaszdziurko.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/tomaszdziurko.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/tomaszdziurko.com\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"http:\/\/tomaszdziurko.com\/wp-json\/wp\/v2\/comments?post=877"}],"version-history":[{"count":7,"href":"http:\/\/tomaszdziurko.com\/wp-json\/wp\/v2\/posts\/877\/revisions"}],"predecessor-version":[{"id":887,"href":"http:\/\/tomaszdziurko.com\/wp-json\/wp\/v2\/posts\/877\/revisions\/887"}],"wp:featuredmedia":[{"embeddable":true,"href":"http:\/\/tomaszdziurko.com\/wp-json\/wp\/v2\/media\/882"}],"wp:attachment":[{"href":"http:\/\/tomaszdziurko.com\/wp-json\/wp\/v2\/media?parent=877"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/tomaszdziurko.com\/wp-json\/wp\/v2\/categories?post=877"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/tomaszdziurko.com\/wp-json\/wp\/v2\/tags?post=877"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}