[4.0][RFC] Fix CSP and apply deferred attribute to all scripts (with exceptions)#31485
[4.0][RFC] Fix CSP and apply deferred attribute to all scripts (with exceptions)#31485dgrammatiko wants to merge 1 commit intojoomla:4.0-devfrom
Conversation
Seems sensible suggestion assuming that joomla is needed as some sort of unique identifier. |
|
but jquery |
As I said this is 100% backwards compatible (jQuery or even Mootools would be happy. I won't if I see them, but we all know I'm a special case 😃) Edit: By the way, although this is far for an actual PR the code is fully functional, try it if you don't believe me |
|
@Fedik can you provide some feedback here? Can we expand the schema to have a |
hm, what exactly do you mean? About PR. Sorry, it no go. The chance to make all |
I don't like this as well but it is needed not only for
But this RFC goes a bit further it also introduces |
That why I said, if it not work then it should not work. If someone add script with addCustomTag or other non standard way, then CSP should throw an error and skip that script.
You already can use module/nomodule, it just a "type" attribute of the script tag. |
Ok, I think I didn't explain well my intend. Files with
That will require some kind of db migration for anyone updating from J3. But yes I would also prefer to spend the extra time on the form save rather on each page cycle. |
I think we should not do such assumptions, developers should be free to use any filename for any kind of script. It is up to them use or not use es6 es10 etc.
No. It also will be parsing (as you made here), but only for the editor content, similar to loadmodule and emailcloack . |
Sorry I fail to see what's different using the plugin hook. I mean essentially this line
It's not an assumption. The javascript group intentionally named the modern js as |
Yea, that line just renders the module for the given position. if (strpos($article->text, '<script') !== false)
{
// Run CSP fix for $article->text;
}
That is a group assumption ;)
That a good question ;) But that time not lost for nothing, now we know how to write es6 code and stuff :) |
|
A note for whom may concern, about In the view/layout : $wa->useScript('foo');In the result this will render both |
|
@Fedik I think you're right, that would make sense a year ago when we were discussing the @wilsone please make sure that #31485 (comment) is documented in the assets manager documentation and also communicate somehow that styles and scripts that aren't introduced using the Joomla API will break CSP. The B/C break due to moving the scripts at the end of the page is also something that needs documentation... |
Pull Request for Issue # .
Summary of Changes
type="module"nomodulefor scripts (eg load ES2015+ for new browsers or legacy js for old browsers)data-joomla-no-deferexists or the script has an attributeasync, or an attributetype=modulewhich is deferred by default)srcattribute, keep reading...The CSP problem
First and mostly lets thank @zero-24 for implementing the endpoint and the headers part for CSP and @wilsonge adding the
nonceattribute for the inline scripts/styles. That said the CSP, as is right now` is totally broken even when someone will use the Joomla API and here's the proof:nonceattribute but they don't and thus the CSP is BROKEN! To take this one step forward try to insert the following code into any layout (component/module/JLayout)Once again the CSP is broken as there's no
nonceattributenonce.The script defer
Some background (very brief) information on the scripts loading (read more on https://flaviocopes.com/javascript-async-defer/ )
Joomla 3.x has all the scripts (appended using the API) in the head of the document resulting into blocking the parser:

Joomla 4.0 moved the code to the body end (breaking B/C and possibly any inline script that exists into any component/module content). Although it doesn't pause the parser it introduces another problem, scripts starts downloading late and maybe behind fetches for images and other not critical assets

The proposed solution: defer all scripts but keep them in the head (or wherever the dev injected them)

The last one is not the first time tried for Joomla 4.0 (eg: #22460 ) but that PR had side effects, notably the inline scripts inside any content area. So the solution is a two fold here, since fixing the CSP requires adding the nonce attribute we can add also a defer attribute. Unfortunately this will not work for inline scripts since the browsers behaviour (unless type=module) is to parse and execute immediately. We will bend things a bit here by appending the content of the inline script to the src attribute and to do that we will use the very well known/supported way of encoding the data:
$attribs['src'] = 'data:text/javascript;base64,' . base64_encode($content);. That's it. Scripts get to load the new ES2015+ code for newer browsers, have a fallback for IE11 or other legacy, and the inline scripts are properly deferred.Things that need a decision
data-joomla-no-deferTesting Instructions
Follow the description above
Actual result BEFORE applying this Pull Request
Lighthouse really bad results
Expected result AFTER applying this Pull Request
A bit better Lighthouse results, but there's a lot more work to get to the green fields...
@zero-24 since I know that you're in charge of the Lighthouse insights integration could you please ask Paul Irish to comment on this proposal?
Documentation Changes Required
Probably