primefaces / primefaces

Ultimate Component Suite for JavaServer Faces
http://www.primefaces.org
MIT License
1.76k stars 748 forks source link

Core: AJAX update of resource doesn't check for duplicate CSS/JS #11714

Open melloware opened 3 months ago

melloware commented 3 months ago

Describe the bug

@tandraschko this was originally reported on a forum post in 2022: https://forum.primefaces.org/viewtopic.php?t=71210

We never got to the bottom of what was happening then...but my current client has this same issue. They do a LOT of dynamic removing and adding components to a single page app using PrimeFaces.current().ajax().update() as well as dynamically constructing components in Java. its a HUGE project.

Here you can see duplicates in the head like InputNumber and FileUpload. If I close one of their panels and open it again it will add 2 more copies.

I shortened it for brevity but in javax.faces.Resource update the scripts are there again.

<?xml version='1.0' encoding='UTF-8'?>
<partial-response>
    <changes>
        <update id="javax.faces.Resource"><![CDATA[
<link type="text/css" rel="stylesheet" href="/emro/javax.faces.resource/fileupload/fileupload.css.trax?ln=primefaces&amp;v=10.0.20&amp;e=10.0.7" />
<script type="text/javascript" src="/emro/javax.faces.resource/fileupload/fileupload.js.trax?ln=primefaces&amp;v=10.0.20&amp;e=10.0.7"></script>
<script type="text/javascript" src="/emro/javax.faces.resource/inputnumber/inputnumber.js.trax?ln=primefaces&amp;v=10.0.20&amp;e=10.0.7"></script>
<link type="text/css" rel="stylesheet" href="/emro/javax.faces.resource/inputnumber/inputnumber.css.trax?ln=primefaces&amp;v=10.0.20&amp;e=10.0.7" />
<script type="text/javascript" src="/emro/javax.faces.resource/inputmask/inputmask.js.trax?ln=primefaces&amp;v=10.0.20&amp;e=10.0.7"></script>]]></update>
        <update id="mainForm:mainPnl"><![CDATA[<div id="mainForm:mainPnl" </div>]]></update>
        <update id="j_id1:javax.faces.ViewState:0"><![CDATA[-1272965173743229381:1530783905304280517]]></update>
    </changes>
</partial-response>

Our core.ajax for those just automatically appends to the head without checking for existing CSS or JS already loaded.

else if (id === PrimeFaces.ajax.RESOURCE) {
    $('head').append(content);
}

And thus over time our head is filling with more and more scripts and is part of their overall browser slowdown after using the app for an hour...

<head id="j_idt2">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
<link href="/emro/resources/css/fonts.css" rel="stylesheet" type="text/css">
<link href="/emro/resources/css/icons.css" rel="stylesheet" type="text/css">
<link rel="apple-touch-icon" href="/emro/resources/bmp/eMRO_WebIcon.png">
<link rel="shortcut icon" type="image/x-icon" href="/emro/resources/bmp/eMRO_Web.ico">
<link type="text/css" rel="stylesheet" href="/emro/javax.faces.resource/blockui/blockui.css.trax?ln=primefaces-extensions&amp;v=10.0.20&amp;e=10.0.7">
<link type="text/css" rel="stylesheet" href="/emro/javax.faces.resource/bootstrap.css.trax?ln=css">
<link type="text/css" rel="stylesheet" href="/emro/javax.faces.resource/components.css.trax?ln=primefaces&amp;v=10.0.20&amp;e=10.0.7">
<link type="text/css" rel="stylesheet" href="/emro/javax.faces.resource/css/layout-blue.css.trax?ln=california-layout">
<link type="text/css" rel="stylesheet" href="/emro/javax.faces.resource/css/nanoscroller.css.trax?ln=california-layout">
<link type="text/css" rel="stylesheet" href="/emro/javax.faces.resource/fa/font-awesome.css.trax?ln=primefaces&amp;v=10.0.20&amp;e=10.0.7">
<link type="text/css" rel="stylesheet" href="/emro/javax.faces.resource/fileupload/fileupload.css.trax?ln=primefaces&amp;v=10.0.20&amp;e=10.0.7">
<link type="text/css" rel="stylesheet" href="/emro/javax.faces.resource/fileupload/fileupload.css.trax?ln=primefaces&amp;v=10.0.20&amp;e=10.0.7">
<link type="text/css" rel="stylesheet" href="/emro/javax.faces.resource/inputnumber/inputnumber.css.trax?ln=primefaces&amp;v=10.0.20&amp;e=10.0.7">
<link type="text/css" rel="stylesheet" href="/emro/javax.faces.resource/inputnumber/inputnumber.css.trax?ln=primefaces&amp;v=10.0.20&amp;e=10.0.7">
<link type="text/css" rel="stylesheet" href="/emro/javax.faces.resource/inputnumber/inputnumber.css.trax?ln=primefaces&amp;v=10.0.20&amp;e=10.0.7">
<link type="text/css" rel="stylesheet" href="/emro/javax.faces.resource/local.css.trax?ln=css">
<link type="text/css" rel="stylesheet" href="/emro/javax.faces.resource/primeicons/primeicons.css.trax?ln=primefaces&amp;v=10.0.20&amp;e=10.0.7">
<link type="text/css" rel="stylesheet" href="/emro/javax.faces.resource/theme.css.trax?ln=primefaces-california-blue&amp;v=10.0.20&amp;e=10.0.7">

<script type="text/javascript" src="/emro/javax.faces.resource/blockui/blockui.js.trax?ln=primefaces-extensions&amp;v=10.0.20&amp;e=10.0.7"></script>
<script type="text/javascript" src="/emro/javax.faces.resource/chartjs/chartjs.js.trax?ln=primefaces&amp;v=10.0.20&amp;e=10.0.7"></script>
<script type="text/javascript" src="/emro/javax.faces.resource/components.js.trax?ln=primefaces&amp;v=10.0.20&amp;e=10.0.7"></script>
<script type="text/javascript" src="/emro/javax.faces.resource/core.js.trax?ln=primefaces&amp;v=10.0.20&amp;e=10.0.7"></script>
<script type="text/javascript" src="/emro/javax.faces.resource/filedownload/filedownload.js.trax?ln=primefaces&amp;v=10.0.20&amp;e=10.0.7"></script>
<script type="text/javascript" src="/emro/javax.faces.resource/fileupload/fileupload.js.trax?ln=primefaces&amp;v=10.0.20&amp;e=10.0.7"></script>
<script type="text/javascript" src="/emro/javax.faces.resource/fileupload/fileupload.js.trax?ln=primefaces&amp;v=10.0.20&amp;e=10.0.7"></script>
<script type="text/javascript" src="/emro/javax.faces.resource/inputmask/inputmask.js.trax?ln=primefaces&amp;v=10.0.20&amp;e=10.0.7"></script>
<script type="text/javascript" src="/emro/javax.faces.resource/inputmask/inputmask.js.trax?ln=primefaces&amp;v=10.0.20&amp;e=10.0.7"></script>
<script type="text/javascript" src="/emro/javax.faces.resource/inputmask/inputmask.js.trax?ln=primefaces&amp;v=10.0.20&amp;e=10.0.7"></script>
<script type="text/javascript" src="/emro/javax.faces.resource/inputnumber/inputnumber.js.trax?ln=primefaces&amp;v=10.0.20&amp;e=10.0.7"></script>
<script type="text/javascript" src="/emro/javax.faces.resource/inputnumber/inputnumber.js.trax?ln=primefaces&amp;v=10.0.20&amp;e=10.0.7"></script>
<script type="text/javascript" src="/emro/javax.faces.resource/inputnumber/inputnumber.js.trax?ln=primefaces&amp;v=10.0.20&amp;e=10.0.7"></script>
<script type="text/javascript" src="/emro/javax.faces.resource/jquery/jquery-plugins.js.trax?ln=primefaces&amp;v=10.0.20&amp;e=10.0.7"></script>
<script type="text/javascript" src="/emro/javax.faces.resource/jquery/jquery.js.trax?ln=primefaces&amp;v=10.0.20&amp;e=10.0.7"></script>
<script type="text/javascript" src="/emro/javax.faces.resource/js/layout.js.trax?ln=california-layout"></script>
<script type="text/javascript" src="/emro/javax.faces.resource/js/nanoscroller.js.trax?ln=california-layout"></script>
<script type="text/javascript" src="/emro/javax.faces.resource/moment/moment.js.trax?ln=primefaces&amp;v=10.0.20&amp;e=10.0.7"></script>
<script type="text/javascript" src="/emro/javax.faces.resource/primefaces-extensions.js.trax?ln=primefaces-extensions&amp;v=10.0.20&amp;e=10.0.7"></script>
<script type="text/javascript">if(window.PrimeFaces){PrimeFaces.settings.locale='en_US';PrimeFaces.settings.viewId='/Home.xhtml';PrimeFaces.settings.contextPath='/emro';PrimeFaces.settings.cookiesSecure=true;}</script>
</head>

Reproducer

I have no idea quite how to reproduce it but I am seeing it in their code base same as that user from 2022. They are not using a Custom HeadRenderer or anything.

Expected behavior

No duplicate CSS or JS even if the head is sent duplicate scripts.

PrimeFaces edition

Community

PrimeFaces version

13.0.0

Theme

California

JSF implementation

Mojarra

JSF version

2.3

Java version

11

Browser(s)

No response

melloware commented 1 month ago

I am still investigating this but I think it might be this Mojarra bug long since fixed that caused it to keep adding resources to the page that have already been added

https://github.com/javaee/mojarra/issues/4249