Filter duplicate extensions by src URL#1192
Conversation
|
Testing PHP implementation: ampproject/amp-toolbox-php#130 |
| <link rel="preload" href="https://cdn.ampproject.org/v0.css" as="style"> | ||
| <link href="https://fonts.googleapis.com/css?foobar" rel="stylesheet" type="text/css"> | ||
| <link as="script" crossorigin="anonymous" href="https://cdn.ampproject.org/v0.mjs" rel="modulepreload"> |
There was a problem hiding this comment.
Shouldn't the link[rel=preload] and link[rel=modulepreload] be moved to the beginning of the head?
|
Here's the current order in the PHP implementation: <link as="script" crossorigin="anonymous" href="https://cdn.ampproject.org/v0.mjs" rel="modulepreload">
<link rel="preload" href="https://cdn.ampproject.org/v0.css" as="style">
<link rel="stylesheet" href="https://cdn.ampproject.org/v0.css">
<script async nomodule src="https://cdn.ampproject.org/v0.js"></script>
<script async src="https://cdn.ampproject.org/v0.mjs" type="module" crossorigin="anonymous"></script>
<script async nomodule src="https://cdn.ampproject.org/v0/amp-experiment-0.1.js" custom-element="amp-experiment"></script>
<script async custom-element="amp-experiment" src="https://cdn.ampproject.org/v0/amp-experiment-0.1.mjs" type="module" crossorigin="anonymous"></script>
<script async="" nomodule="" src="https://cdn.ampproject.org/v0/amp-mustache-0.2.js" custom-template="amp-mustache"></script>
<script async="" custom-template="amp-mustache" src="https://cdn.ampproject.org/v0/amp-mustache-0.2.mjs" type="module" crossorigin="anonymous"></script>
<link href="https://example.com/favicon.ico" rel="icon">
<link href="https://fonts.googleapis.com/css?foobar" rel="stylesheet" type="text/css">When outputting AMP scripts, it seems that the |
Not sure if that really makes a difference. I'd assume that the browser will simply ignore the |
| <script async custom-template="amp-mustache" src="https://cdn.ampproject.org/v0/amp-mustache-0.2.mjs" type="module" crossorigin="anonymous"></script> | ||
| <link href="https://example.com/favicon.ico" rel="icon"> | ||
| <link href="https://fonts.googleapis.com/css?foobar" rel="stylesheet" type="text/css"> | ||
| <link as="script" crossorigin="anonymous" href="https://cdn.ampproject.org/v0.mjs" rel="modulepreload"> |
There was a problem hiding this comment.
This modulepreload link needs to be moved up along with the preload as well. Ref ampproject/amp-toolbox-php@a3a99fd
There was a problem hiding this comment.
Thanks for the patience taking it up with my empty brain today...
| <!doctype html> | ||
| <html ⚡> | ||
| <head> | ||
| <script async nomodule src="https://cdn.ampproject.org/v0.js"></script> |
There was a problem hiding this comment.
Big problem: The nomodule v0.js script is getting dropped in the output. Here's one thing I had to do in the PHP version to account for this: ampproject/amp-toolbox-php@4bad718
| <link as="script" crossorigin="anonymous" href="https://cdn.ampproject.org/v0.mjs" rel="modulepreload"> | ||
| <link rel="preload" href="https://cdn.ampproject.org/v0.css" as="style"> | ||
| <link rel="stylesheet" href="https://cdn.ampproject.org/v0.css"> | ||
| <script async src="https://cdn.ampproject.org/v0.mjs" type="module" crossorigin="anonymous"></script> |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
Can we go ahead and do that so that there is consistency in the ordering? I've implemented this in the PHP version now. The PHP version now generates the <link as="script" crossorigin="anonymous" href="https://cdn.ampproject.org/v0.mjs" rel="modulepreload">
<link rel="preload" href="https://cdn.ampproject.org/v0.css" as="style">
<link rel="stylesheet" href="https://cdn.ampproject.org/v0.css">
<script async src="https://cdn.ampproject.org/v0.mjs" type="module" crossorigin="anonymous"></script>
<script async nomodule src="https://cdn.ampproject.org/v0.js"></script>
<script async custom-element="amp-experiment" src="https://cdn.ampproject.org/v0/amp-experiment-0.1.mjs" type="module" crossorigin="anonymous"></script>
<script async nomodule src="https://cdn.ampproject.org/v0/amp-experiment-0.1.js" custom-element="amp-experiment"></script>
<script async custom-template="amp-mustache" src="https://cdn.ampproject.org/v0/amp-mustache-0.2.mjs" type="module" crossorigin="anonymous"></script>
<script async nomodule src="https://cdn.ampproject.org/v0/amp-mustache-0.2.js" custom-template="amp-mustache"></script>
<link href="https://example.com/favicon.ico" rel="icon">
<link href="https://fonts.googleapis.com/css?foobar" rel="stylesheet" type="text/css">This ordering aligns with the AMP boilerplate usage as well, where we have |
|
The PHP version is also sorting the script components by name, so |
| _removeDuplicateCustomExtensions(extensions) { | ||
| const nodesByName = new Map(); | ||
| const nodesBySrc = new Map(); | ||
| for (const node of extensions) { | ||
| const name = this._getName(node); | ||
| nodesByName.set(name, node); | ||
| const src = node.attribs['src']; | ||
| nodesBySrc.set(src, node); | ||
| } | ||
| return Array.from(nodesByName.values()); | ||
| return Array.from(nodesBySrc.values()); | ||
| } |
There was a problem hiding this comment.
I took an alternative approach to this in PHP, to do the deduplication in the registerScript function itself: https://github.com/ampproject/amp-toolbox-php/pull/130/files#diff-b0da2cc892f74bf1ebc7a84e63d7065894b24541a48f3a26089f23860ee1209fR156-R190
This also accounts for module and nomodule variations.
| for (const node of extensions) { | ||
| const name = this._getName(node); | ||
| nodesByName.set(name, node); | ||
| const src = node.attribs['src']; |
There was a problem hiding this comment.
Shouldn't this remove the host to make sure a same extension is not downloaded twice from two different hosts?
| <script async nomodule src="https://cdn.ampproject.org/v0/amp-mustache-0.2.js" custom-template="amp-mustache"></script> | ||
| <script async custom-template="amp-mustache" src="https://cdn.ampproject.org/v0/amp-mustache-0.2.mjs" type="module" crossorigin="anonymous"></script> |
There was a problem hiding this comment.
Can the order be reversed, with the nomodule one coming after?
| } | ||
|
|
||
| _registerScript(node) { | ||
| const moduleIndex = hasAttribute(node, 'nomodule') ? 0 : 1; |
There was a problem hiding this comment.
This should ensure nomodule comes after type=module.
| const moduleIndex = hasAttribute(node, 'nomodule') ? 0 : 1; | |
| const moduleIndex = hasAttribute(node, 'nomodule') ? 1 : 0; |
sebastianbenz
left a comment
There was a problem hiding this comment.
Addressed the feedback. Scripts should now have the right order.
Not super happy about the changes as the implementation is now more complex (and expensive) than before (without a real need, as the module scripts are injected in a later stage of the transformation).
| <script async nomodule src="https://cdn.ampproject.org/v0/amp-mustache-0.2.js" custom-template="amp-mustache"></script> | ||
| <script async custom-template="amp-mustache" src="https://cdn.ampproject.org/v0/amp-mustache-0.2.mjs" type="module" crossorigin="anonymous"></script> |
| <!doctype html> | ||
| <html ⚡> | ||
| <head> | ||
| <script async nomodule src="https://cdn.ampproject.org/v0.js"></script> |
| appendAll(head, this._metaOther); | ||
| appendAll(head, this._resourceHintLinks); |
There was a problem hiding this comment.
The metaOther can potentially includes lots of non-critical stuff like OpenGraph tags. I think in terms of performance, the resource hints should come right after the charset and before these other meta tags.
There was a problem hiding this comment.
good point! done
schlessera
left a comment
There was a problem hiding this comment.
I'm still wondering about the following priorities:
- ) Is the viewport needed for making decisions about the resource hints? I don't think so, but I'm not entirely sure.
- ) The boilerplate style is now much further down, after the scripts. Are we sure this does not lead to FOUC?
| // needs to run after ReorderHeadTransformer | ||
| 'RewriteAmpUrls', |
There was a problem hiding this comment.
| // needs to run after ReorderHeadTransformer | |
| 'RewriteAmpUrls', | |
| 'RewriteAmpUrls', |
| // needs to run after ReorderHeadTransformer | ||
| 'RewriteAmpUrls', |
There was a problem hiding this comment.
| // needs to run after ReorderHeadTransformer | |
| 'RewriteAmpUrls', | |
| 'RewriteAmpUrls', |
| // needs to run after ReorderHeadTransformer | ||
| 'RewriteAmpUrls', |
There was a problem hiding this comment.
| // needs to run after ReorderHeadTransformer | |
| 'RewriteAmpUrls', | |
| 'RewriteAmpUrls', |
|
re 1) Yes, viewport needs to come first (I think that was the reason why I added |
|
Hm. Following that logic, we should also move |
westonruter
left a comment
There was a problem hiding this comment.
LGTM, but I defer to @schlessera.
|
|
|
Thanks a lot for the patience and detailed review! |
Fixes #1191