Skip to content

Commit

Permalink
Migrate to AMP Optimizer 2.0 (#10535)
Browse files Browse the repository at this point in the history
* Migrate to AMP Optimizer 2.0

Most notable changes:

* Automatically import all missing AMP component scripts.
* Automatically add any missing mandatary AMP tags.
* 40% faster

I've updated the docs to mention component auto import and added a corresponding
test case.

* change validator tests which now pass validation

* Improve wording

Co-Authored-By: JJ Kasper <jj@jjsweb.site>

* Update adding-amp-components.md

Co-authored-by: JJ Kasper <jj@jjsweb.site>
Co-authored-by: Joe Haddad <timer150@gmail.com>
  • Loading branch information
3 people committed Feb 14, 2020
1 parent 1c247b5 commit ae9b13e
Show file tree
Hide file tree
Showing 8 changed files with 132 additions and 54 deletions.
32 changes: 29 additions & 3 deletions docs/advanced-features/amp-support/adding-amp-components.md
Expand Up @@ -4,7 +4,35 @@ description: Add components from the AMP community to AMP pages, and make your p

# Adding AMP Components

The AMP community provide [many components](https://amp.dev/documentation/components/) to make AMP pages more interactive. You can add these components to your page by using `next/head`, as in the following example:
The AMP community provides [many components](https://amp.dev/documentation/components/) to make AMP pages more interactive. Next.js will automatically import all components used on a page and there is no need to manually import AMP component scripts:

```jsx
export const config = { amp: true }

function MyAmpPage() {
const date = new Date()

return (
<div>
<p>Some time: {date.toJSON()}</p>
<amp-timeago
width="0"
height="15"
datetime={date.toJSON()}
layout="responsive"
>
.
</amp-timeago>
</div>
)
}

export default MyAmpPage
```

The above example uses the [`amp-timeago`](https://amp.dev/documentation/components/amp-timeago/?format=websites) component.

By default, the latest version of a component is always imported. If you want to customize the version, you can use `next/head`, as in the following example:

```jsx
import Head from 'next/head'
Expand Down Expand Up @@ -40,5 +68,3 @@ function MyAmpPage() {

export default MyAmpPage
```

The above example uses the [`amp-timeago`](https://amp.dev/documentation/components/amp-timeago/?format=websites) component.
2 changes: 1 addition & 1 deletion packages/next/package.json
Expand Up @@ -57,7 +57,7 @@
]
},
"dependencies": {
"@ampproject/toolbox-optimizer": "1.1.1",
"@ampproject/toolbox-optimizer": "2.0.0",
"@babel/core": "7.7.2",
"@babel/plugin-proposal-class-properties": "7.7.0",
"@babel/plugin-proposal-nullish-coalescing-operator": "7.7.4",
Expand Down
4 changes: 2 additions & 2 deletions test/integration/amp-export-validation/pages/cat.js
Expand Up @@ -2,7 +2,7 @@ export const config = { amp: true }

export default () => (
<div>
{/* I show a warning since the amp-video script isn't added */}
<amp-video src="/cats.mp4" height={400} width={800} />
{/* I show a warning since the width and height attribute is missing */}
<amp-video src="/cats.mp4" layout="responsive" />
</div>
)
2 changes: 0 additions & 2 deletions test/integration/amp-export-validation/pages/dog-cat.js
Expand Up @@ -4,7 +4,5 @@ export default () => (
<div>
{/* I throw an error since <amp-img/> should be used instead */}
<img src="/dog.gif" height={400} width={800} />
{/* I show a warning since the amp-video script isn't added */}
<amp-video src="/cats.mp4" height={400} width={800} />
</div>
)
7 changes: 2 additions & 5 deletions test/integration/amp-export-validation/test/index.test.js
Expand Up @@ -32,9 +32,6 @@ describe('AMP Validation on Export', () => {
expect(buildOutput).toMatch(
/error.*The parent tag of tag 'IMG-I-AMPHTML-INTRINSIC-SIZER' is 'div', but it can only be 'i-amphtml-sizer-intrinsic'/
)
expect(buildOutput).toMatch(
/warn.*The tag 'amp-video extension .js script' is missing or incorrect, but required by 'amp-video'/
)
})

it('should export AMP pages', async () => {
Expand Down Expand Up @@ -63,7 +60,7 @@ describe('AMP Validation on Export', () => {
stderr: true,
})
expect(stdout).toMatch(
/warn.*The tag 'amp-video extension \.js script' is missing/
/error.*The mandatory attribute 'height' is missing in tag 'amp-video'\./
)
await expect(access(join(outDir, 'cat.html'))).resolves.toBe(undefined)
await expect(stderr).not.toMatch(
Expand Down Expand Up @@ -117,7 +114,7 @@ describe('AMP Validation on Export', () => {
stderr: true,
})
expect(stdout).toMatch(
/warn.*The tag 'amp-video extension .js script' is missing or incorrect, but required by 'amp-video'/
/error.*The parent tag of tag 'IMG-I-AMPHTML-INTRINSIC-SIZER' is 'div', but it can only be 'i-amphtml-sizer-intrinsic'/
)
expect(stdout).toMatch(
/error.*The parent tag of tag 'IMG-I-AMPHTML-INTRINSIC-SIZER' is 'div', but it can only be 'i-amphtml-sizer-intrinsic'/
Expand Down
10 changes: 10 additions & 0 deletions test/integration/amphtml/pages/auto-import.js
@@ -0,0 +1,10 @@
export const config = { amp: true }

export default () => (
<amp-twitter
width="390"
height="330"
layout="responsive"
data-momentid="1018806709412876288"
></amp-twitter>
)
5 changes: 5 additions & 0 deletions test/integration/amphtml/test/index.test.js
Expand Up @@ -112,6 +112,11 @@ describe('AMP Usage', () => {
const html = await renderViaHTTP(appPort, '/only-amp')
await validateAMP(html)
})

it('should auto import extensions', async () => {
const html = await renderViaHTTP(appPort, '/auto-import')
await validateAMP(html)
})
})

describe('With AMP context', () => {
Expand Down
124 changes: 83 additions & 41 deletions yarn.lock
Expand Up @@ -2,36 +2,47 @@
# yarn lockfile v1


"@ampproject/toolbox-core@^1.1.1":
version "1.1.1"
resolved "https://registry.yarnpkg.com/@ampproject/toolbox-core/-/toolbox-core-1.1.1.tgz#540c8f3ab0f5d1faa1ba35282cd5f5f3f0e16a76"
integrity sha512-jcuVJUnGDRUEJgMYO6QVdf1dBy/oLZX3NjN2hYG48biFcPCvXevuv4xYFZMJsnsHSvXKg8y0qB8rANNyhTUN/A==
"@ampproject/toolbox-core@^2.0.0":
version "2.0.0"
resolved "https://registry.yarnpkg.com/@ampproject/toolbox-core/-/toolbox-core-2.0.0.tgz#3329a01eec8f767614385cc56cee8be32ccf7f32"
integrity sha512-xAJOmh6MPS2mdHNsK8mj1t8TLh6mlehirh0fOBsRhKCNCJXgg4Gfd2u5igy8VFq9sYnuWP/npFyjGX36qpXW5Q==
dependencies:
node-fetch "2.6.0"
cross-fetch "3.0.4"

"@ampproject/toolbox-optimizer@1.1.1":
version "1.1.1"
resolved "https://registry.yarnpkg.com/@ampproject/toolbox-optimizer/-/toolbox-optimizer-1.1.1.tgz#be66245c966ba9b0f5e3020109f87fea90ea377d"
integrity sha512-LTtTM5FSOrWuTJ6mOwPfZmpUDI6polrNz3tX2EmDmDkjDK+43vSpq1OHtukivIFHafdixJuoeki5dF3PC/ZoWw==
"@ampproject/toolbox-optimizer@2.0.0":
version "2.0.0"
resolved "https://registry.yarnpkg.com/@ampproject/toolbox-optimizer/-/toolbox-optimizer-2.0.0.tgz#96ea3d26bc7a9f19718a27c721e021a121003601"
integrity sha512-ZYRi7vB4ALC8DnTHQLchAeHMGsFml/Zr4fNWBlTiMGfvWGL0XTV9YyP4s24IDwAlunEgynmz0FTrGMJdRpNf2Q==
dependencies:
"@ampproject/toolbox-core" "^1.1.1"
"@ampproject/toolbox-runtime-version" "^1.1.1"
"@ampproject/toolbox-script-csp" "^1.1.1"
"@ampproject/toolbox-core" "^2.0.0"
"@ampproject/toolbox-runtime-version" "^2.0.0"
"@ampproject/toolbox-script-csp" "^2.0.0"
"@ampproject/toolbox-validator-rules" "^2.0.0"
css "2.2.4"
parse5 "5.1.0"
parse5-htmlparser2-tree-adapter "5.1.0"
domhandler "3.0.0"
domutils "2.0.0"
htmlparser2 "4.0.0"
normalize-html-whitespace "1.0.0"
terser "4.6.3"

"@ampproject/toolbox-runtime-version@^1.1.1":
version "1.1.1"
resolved "https://registry.yarnpkg.com/@ampproject/toolbox-runtime-version/-/toolbox-runtime-version-1.1.1.tgz#628fe5091db4f90b68960620e22ad64f9f2563bd"
integrity sha512-ibmw5p+0Sz+wingbX/Dyboe8a0+XDkMfFGSM7KFE0h2z3Op9MADup8ZPLeHT54Z7cYKmB6ob60FVHtQQDhEXNw==
"@ampproject/toolbox-runtime-version@^2.0.0":
version "2.0.0"
resolved "https://registry.yarnpkg.com/@ampproject/toolbox-runtime-version/-/toolbox-runtime-version-2.0.0.tgz#01202be490ce8baf8654127de35dff5f93e922a0"
integrity sha512-7XDlo7l4Ozpc/XWmJeYNF0ZfXCy7Vdh07spN+xEOst8gF99yaavZRNVkdgyTxLR3BpY9RIqqhSs6OxfkOKlRZQ==
dependencies:
"@ampproject/toolbox-core" "^1.1.1"
"@ampproject/toolbox-core" "^2.0.0"

"@ampproject/toolbox-script-csp@^1.1.1":
version "1.1.1"
resolved "https://registry.yarnpkg.com/@ampproject/toolbox-script-csp/-/toolbox-script-csp-1.1.1.tgz#0b049a1c86c99f300162a10e1b9ce83c6e354a45"
integrity sha512-gACGfsVKinCy/977FSrlVgo6jxTZ0lcTCvCnRlNwvSOcxJVm+jJR3sP7/F43fpak9Gsq/EwFaatfnNMbunPc+w==
"@ampproject/toolbox-script-csp@^2.0.0":
version "2.0.0"
resolved "https://registry.yarnpkg.com/@ampproject/toolbox-script-csp/-/toolbox-script-csp-2.0.0.tgz#7aa55fb693749e657b63985ebe49e1d3489a8b79"
integrity sha512-9mW3yiKwjORi0ViuayphVZii9MwiPhneZGZWy+kN44xr3SpN7iQC52/WWWTBOZX9z1zaUh8DqGc//VFY5ILSAw==

"@ampproject/toolbox-validator-rules@^2.0.0":
version "2.0.0"
resolved "https://registry.yarnpkg.com/@ampproject/toolbox-validator-rules/-/toolbox-validator-rules-2.0.0.tgz#eefdce2f7f773e4675d72c7a1068c70105a647c3"
integrity sha512-5f2IvT1m/zNtqfNXFE9V4ZtKofIttST65QL1wf4lKjBhJsbZgAAeR/u4DgOvftRVRmgn6IpUiWY1pt9xWaI5yA==
dependencies:
cross-fetch "3.0.4"

"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.5.5":
version "7.5.5"
Expand Down Expand Up @@ -5352,6 +5363,14 @@ cross-env@6.0.3:
dependencies:
cross-spawn "^7.0.0"

cross-fetch@3.0.4:
version "3.0.4"
resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.0.4.tgz#7bef7020207e684a7638ef5f2f698e24d9eb283c"
integrity sha512-MSHgpjQqgbT/94D4CyADeNoYh52zMkCX4pcJvPP5WqPsLFMKjr2TCMg381ox5qI0ii2dPwaLx/00477knXqXVw==
dependencies:
node-fetch "2.6.0"
whatwg-fetch "3.0.0"

cross-spawn@6.0.5, cross-spawn@^6.0.0, cross-spawn@^6.0.5:
version "6.0.5"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4"
Expand Down Expand Up @@ -6084,7 +6103,7 @@ doctrine@^3.0.0:
dependencies:
esutils "^2.0.2"

dom-serializer@0:
dom-serializer@0, dom-serializer@^0.2.1:
version "0.2.2"
resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.2.2.tgz#1afb81f533717175d478655debc5e332d9f9bb51"
integrity sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==
Expand Down Expand Up @@ -6127,6 +6146,13 @@ domexception@^1.0.1:
dependencies:
webidl-conversions "^4.0.2"

domhandler@3.0.0, domhandler@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-3.0.0.tgz#51cd13efca31da95bbb0c5bee3a48300e333b3e9"
integrity sha512-eKLdI5v9m67kbXQbJSNn1zjh0SDzvzWVWtX+qEI3eMjZw8daH9k8rlj1FZY9memPwjiskQFbe7vHVVJIAqoEhw==
dependencies:
domelementtype "^2.0.1"

domhandler@^2.3.0:
version "2.4.2"
resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.4.2.tgz#8805097e933d65e85546f726d60f5eb88b44f803"
Expand All @@ -6142,6 +6168,15 @@ domutils@1.5.1:
dom-serializer "0"
domelementtype "1"

domutils@2.0.0, domutils@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.0.0.tgz#15b8278e37bfa8468d157478c58c367718133c08"
integrity sha512-n5SelJ1axbO636c2yUtOGia/IcJtVtlhQbFiVDBZHKV5ReJO1ViX7sFEemtuyoAnBxk5meNSYgA8V4s0271efg==
dependencies:
dom-serializer "^0.2.1"
domelementtype "^2.0.1"
domhandler "^3.0.0"

domutils@^1.5.1, domutils@^1.7.0:
version "1.7.0"
resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a"
Expand Down Expand Up @@ -8093,6 +8128,16 @@ html-entities@^1.2.0:
resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-1.2.1.tgz#0df29351f0721163515dfb9e5543e5f6eed5162f"
integrity sha1-DfKTUfByEWNRXfueVUPl9u7VFi8=

htmlparser2@4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-4.0.0.tgz#6034658db65b7713a572a9ebf79f650832dceec8"
integrity sha512-cChwXn5Vam57fyXajDtPXL1wTYc8JtLbr2TN76FYu05itVVVealxLowe2B3IEznJG4p9HAYn/0tJaRlGuEglFQ==
dependencies:
domelementtype "^2.0.1"
domhandler "^3.0.0"
domutils "^2.0.0"
entities "^2.0.0"

htmlparser2@^3.9.1:
version "3.10.1"
resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.10.1.tgz#bd679dc3f59897b6a34bb10749c855bb53a9392f"
Expand Down Expand Up @@ -11172,6 +11217,11 @@ nopt@^4.0.1:
abbrev "1"
osenv "^0.1.4"

normalize-html-whitespace@1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/normalize-html-whitespace/-/normalize-html-whitespace-1.0.0.tgz#5e3c8e192f1b06c3b9eee4b7e7f28854c7601e34"
integrity sha512-9ui7CGtOOlehQu0t/OhhlmDyc71mKVlv+4vF+me4iZLPrNtRL2xoquEdfZxasC/bdQi/Hr3iTrpyRKIG+ocabA==

normalize-package-data@^2.0.0, normalize-package-data@^2.3.0, normalize-package-data@^2.3.2, normalize-package-data@^2.3.4, normalize-package-data@^2.3.5, normalize-package-data@^2.4.0:
version "2.5.0"
resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8"
Expand Down Expand Up @@ -11949,28 +11999,11 @@ parse-url@^5.0.0:
parse-path "^4.0.0"
protocols "^1.4.0"

parse5-htmlparser2-tree-adapter@5.1.0:
version "5.1.0"
resolved "https://registry.yarnpkg.com/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-5.1.0.tgz#a8244ee12bbd6b8937ad2a16ea43fe348aebcc86"
integrity sha512-OrI4DNmghGcwDB3XN8FKKN7g5vBmau91uqj+VYuwuj/r6GhFBMBNymsM+Z9z+Z1p4HHgI0UuQirQRgh3W5d88g==
dependencies:
parse5 "^5.1.0"

parse5@4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/parse5/-/parse5-4.0.0.tgz#6d78656e3da8d78b4ec0b906f7c08ef1dfe3f608"
integrity sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==

parse5@5.1.0:
version "5.1.0"
resolved "https://registry.yarnpkg.com/parse5/-/parse5-5.1.0.tgz#c59341c9723f414c452975564c7c00a68d58acd2"
integrity sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ==

parse5@^5.1.0:
version "5.1.1"
resolved "https://registry.yarnpkg.com/parse5/-/parse5-5.1.1.tgz#f68e4e5ba1852ac2cadc00f4555fff6c2abb6178"
integrity sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==

parseurl@~1.3.3:
version "1.3.3"
resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4"
Expand Down Expand Up @@ -15859,6 +15892,15 @@ terser@4.4.2:
source-map "~0.6.1"
source-map-support "~0.5.12"

terser@4.6.3:
version "4.6.3"
resolved "https://registry.yarnpkg.com/terser/-/terser-4.6.3.tgz#e33aa42461ced5238d352d2df2a67f21921f8d87"
integrity sha512-Lw+ieAXmY69d09IIc/yqeBqXpEQIpDGZqT34ui1QWXIUpR2RjbqEkT8X7Lgex19hslSqcWM5iMN2kM11eMsESQ==
dependencies:
commander "^2.20.0"
source-map "~0.6.1"
source-map-support "~0.5.12"

terser@^3.8.2:
version "3.17.0"
resolved "https://registry.yarnpkg.com/terser/-/terser-3.17.0.tgz#f88ffbeda0deb5637f9d24b0da66f4e15ab10cb2"
Expand Down

0 comments on commit ae9b13e

Please sign in to comment.