Wicket scriptタグ を body 閉じタグの直前に出力する


Javascript を head タグ内に記述すると、
HTML のレンダリングをブロックする場合があります。
以前、<wicket:header-items/>タグと、IHeaderResponse#renderを使って、headタグ内にjavascriptのリンクを出力 していましたが、
script タグ のリンクのみを body 閉じタグの直前で出力できるようにしたくなったので、
実装してみた結果を記述します。


前提

  • Wicket version 7.6.0です。
        <dependency>
            <groupId>org.apache.wicket</groupId>
            <artifactId>wicket-core</artifactId>
            <version>7.6.0</version>
        </dependency>
    

参考


何故 body の 閉じタグ直前に出力したいのか

[JS] JavaScript の読み込み位置をページ最後にしたほうがよい理由 | memocarilog
など、ページのレンダリングが止まってしまうので、
基本的に、下部に出力しておきたいと考えます。


実装

以下、実装することで、HTML の head と、 body 閉じタグの直前に、
script タグを出力できるようになりました。

  • Application クラスに HeaderResponseDecorator の設定処理を追加

        // set ResponseDecorator
        setHeaderResponseDecorator(response -> {
            // use this header resource decorator to load all JavaScript resources in the page
            // footer (after </body>)
            return new JavaScriptFilteredIntoFooterHeaderResponse(response, "footerJS");
        });
    

  • HTML body タグの直前に、wicket:container タグを追加

        <wicket:container wicket:id="footerJS"></wicket:container>
        </body>
    

  • Page クラスで HeaderResponseContainer を追加

        add(new HeaderResponseContainer("footerJS", "footerJS"));
    

これで、Page クラスの renderHead メソッド内で、
JavaScriptHeaderItem を追加すると、
body タグの直前に出力されるようになります。
header タグ内には、FilteredHeaderItem を使うと、追加可能です。
Filter 名は、定数 FilteringHeaderResponse.DEFAULT_HEADER_FILTER_NAME を使用します。

  • renderHead メソッド
        @Override
        public void renderHead(IHeaderResponse response) {
    
            super.renderHead(response);
    
            // bodyタグ直前に追加する
            String onReadyScript = null;
            try (PackageTextTemplate template = new PackageTextTemplate(this.getClass(),
                    "pageOnReady.js",
                    "text/javascript")) {
                onReadyScript = template.asString();
            } catch (IOException e) {
                throw new IllegalStateException(e);
            }
            response.render(JavaScriptHeaderItem.forScript(onReadyScript, "onReadyScript"));
    
            // header部に追加する
            response.render(new FilteredHeaderItem(JavaScriptHeaderItem.forUrl("/static/js/custom.js"), FilteringHeaderResponse.DEFAULT_HEADER_FILTER_NAME));
        }
    

以上です。

コメント