web-dev-qa-db-ja.com

PrimeFaces JavaScriptファイルのロードと解析を延期する

JSF 2.1 + PrimeFaces 4.0 webappのパフォーマンスを Google PageSpeed で分析している間、JavaScriptファイルの解析を延期することをお勧めします。 _<p:layout>_を含むテストページと、_<p:watermark>_および_<p:fileUpload>_を含むフォームは次のようになります...

_<p:layout>
    <p:layoutUnit position="west" size="100">Test</p:layoutUnit>
    <p:layoutUnit position="center">
        <h:form enctype="multipart/form-data">
            <p:inputText id="input" />
            <p:watermark for="input" value="watermark" />
            <p:focus for="input" />
            <p:fileUpload/>
            <p:commandButton value="submit" />
        </h:form>
    </p:layoutUnit>
</p:layout>
_

...延期される可能性のある次のJavaScriptファイルがリストされます。

  • _primefaces.js_(219.5KiB)
  • _jquery-plugins.js_(191.8KiB)
  • _jquery.js_(95.3KiB)
  • _layout.js_(76.4KiB)
  • _fileupload.js_(23.8KiB)
  • _watermark.js_(4.7KiB)

このGoogle Developersの記事 にリンクしています。ここでは、遅延読み込みとその実現方法が説明されています。基本的に、onloadwindowイベント中に、目的の_<script>_を動的に作成する必要があります。古いブラウザやバグのあるブラウザが完全に無視される最も単純な形式では、次のようになります。

_<script>
    window.addEventListener("load", function() {
        var script = document.createElement("script");
        script.src = "filename.js";
        document.head.appendChild(script);
    }, false);
</script>
_

さて、これらのスクリプトを制御できる場合、これは可能ですが、リストされたスクリプトはすべてJSFによって強制的に自動的に組み込まれます。また、PrimeFacesは、_jquery.js_から$(xxx)を直接呼び出し、_primefaces.js_からPrimeFaces.xxx()を直接呼び出している一連のインラインスクリプトをHTML出力にレンダリングします。つまり、_$ is undefined_や_PrimeFaces is undefined_などのエラーが発生するだけなので、それらを実際にonloadイベントに延期することは簡単にはできません。

しかし、それは技術的に可能であるべきです。サイトのカスタムスクリプトの多くもそれに依存しているため、jQueryだけを据え置く必要がないことを考えると、PrimeFacesスクリプトを強制的に自動インクルードすることからJSFをブロックして、それらを据え置くことができ、それらをどのように処理できるかインラインPrimeFaces.xxx()呼び出し?

41
BalusC

Defer primefaces.jsへの回答として最初に投稿されましたloading


同じ問題に遭遇した人のために、この質問に別の解決策を追加します。

Pagespeedが推奨する順序を実現するには、primefaces HeadRendererをカスタマイズする必要があります。これはPrimeFacesによって実装される可能性のあるものですが、v5.2.RC2では見られません。これらは、変更が必要なencodeBeginの行です。

96         //Registered Resources
97         UIViewRoot viewRoot = context.getViewRoot();
98         for (UIComponent resource : viewRoot.getComponentResources(context, "head")) {
99             resource.encodeAll(context);
100        }

headタグのカスタムコンポーネントを作成し、それを上記の動作をオーバーライドするレンダラーにバインドするだけです。

この変更のためだけにメソッド全体を複製する必要はありません。「last」というファセットを追加し、スクリプトリソースをレンダラーの先頭に新しいdeferredScriptコンポーネントとして移動する方がきれいな場合があります。興味があれば教えてください。フォークを作成してその方法を説明します。

このアプローチは、新しいリソースの依存関係がコンポーネントに追加されたり、新しいコンポーネントがビューに追加されたりしても壊れないという意味で、「将来の保証」です。

3
Timir