Primefaces javascript defer parsing

1k Views Asked by At

Primefaces 4.0 is generating lots of overhead during page loading as seen from PageSpeed Insights:

**605.3KiB of JavaScript is parsed during initial page load. Defer parsing JavaScript to reduce blocking of page rendering.**
http://localhost:8888/.../primefaces.js.xhtml?... (219.5KiB)
http://localhost:8888/.../jquery-plugins.js.xhtml?... (191.8KiB)
http://localhost:8888/.../jquery.js.xhtml?... (95.3KiB)
http://localhost:8888/.../tooltip.js.xhtml?... (34.5KiB)
http://localhost:8888/.../jsf.js.xhtml?... (25.4KiB)
http://localhost:8888/.../primefaces-extensions.js.xhtml?... (19.7KiB)
http://localhost:8888/.../watermark.js.xhtml?... (4.7KiB)
http://localhost:8888/.../hotkey.js.xhtml?... (1.2KiB)

Any idea how these 3rd party javascript files could be set to be in the bottom of the body section instead head or use defer/async parameters? Javascript loaders do not help in this case as these are coming from the JSF renderer. Also I tried to create a Listener for PreRenderView (Best way for JSF to defer parsing of JavaScript?) but that did not work out. Any other options that could solve this problem? Thanks for your help!

1

There are 1 best solutions below

0
On

I got the moving of the scripts to work with the followind snippet:

public class ScriptValidateListener implements SystemEventListener {

    @Override
    public void processEvent(SystemEvent event) throws AbortProcessingException {
        UIViewRoot root = (UIViewRoot) event.getSource();
        FacesContext ctx = FacesContext.getCurrentInstance();
        List<UIComponent> resources = root.getComponentResources(ctx, "HEAD");
        for (UIComponent r : resources) {
            String name = (String) r.getAttributes().get("name");
            if (name == null) {
                continue;
            }

            if (name.contains(".js")) {
                root.removeComponentResource(ctx, r, "HEAD");
                root.addComponentResource(ctx, r, "BODY");
            }
        }
    }

    @Override
    public boolean isListenerForSource(Object source) {
        return (source instanceof UIViewRoot);
    }
}

This moves all javascripts from HEAD to end of the BODY. But. There is this problem with Primefaces that the components rendered will try to access either JQuery ($.) or PrimeFaces javascript functions and that will break all ajax functionality on the page. Propably I will need to decide what of the scripts to move and what not to move. Also a part from the Listener I needed to define the following to faces-config.xml to make it work:

<application>
    <system-event-listener>
        <system-event-listener-class>com.example.listener.ScriptValidateListener</system-event-listener-class>
        <system-event-class>javax.faces.event.PreRenderViewEvent</system-event-class>
    </system-event-listener>
</application>