From 7d8b814df608da6c803e752993f6195414cd473d Mon Sep 17 00:00:00 2001 From: JJ Kasper Date: Wed, 5 May 2021 23:02:07 -0500 Subject: [PATCH] Land - Font optimizations - Adobe Fonts / Typekit support (#24834) This updates this initial PR here https://github.com/vercel/next.js/pull/18146 to resolve merge conflicts and updates tests since we aren't able to update that PR itself. ## Feature - [ ] Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR. - [ ] Related issues linked using `fixes #number` - [x] Integration tests added - [x] Documentation added - [ ] Telemetry added. In case of a feature if it's used or not. Closes: https://github.com/vercel/next.js/pull/18146 --- docs/basic-features/font-optimization.md | 2 +- packages/next/next-server/lib/constants.ts | 5 +- packages/next/next-server/lib/head.tsx | 7 +- .../with-google/manifest-snapshot.json | 22 + .../fixtures/with-google/next.config.js | 1 + .../with-google}/pages/_document.js | 0 .../{ => fixtures/with-google}/pages/amp.js | 0 .../{ => fixtures/with-google}/pages/index.js | 0 .../{ => fixtures/with-google}/pages/nonce.js | 0 .../{ => fixtures/with-google}/pages/stars.js | 0 .../with-google}/pages/static-head.js | 0 .../with-google}/pages/with-font.js | 0 .../with-google}/pages/without-font.js | 0 .../{ => fixtures/with-google}/server.js | 0 .../with-typekit/manifest-snapshot.json | 14 + .../fixtures/with-typekit/next.config.js | 1 + .../fixtures/with-typekit/pages/_document.js | 27 ++ .../fixtures/with-typekit/pages/amp.js | 9 + .../fixtures/with-typekit/pages/index.js | 7 + .../fixtures/with-typekit/pages/nonce.js | 19 + .../fixtures/with-typekit/pages/stars.js | 26 ++ .../with-typekit/pages/static-head.js | 15 + .../fixtures/with-typekit/pages/with-font.js | 27 ++ .../with-typekit/pages/without-font.js | 26 ++ .../fixtures/with-typekit/server.js | 111 +++++ .../font-optimization/test/index.test.js | 423 ++++++++++-------- .../test/manifest-snapshot.json | 14 - 27 files changed, 545 insertions(+), 211 deletions(-) create mode 100644 test/integration/font-optimization/fixtures/with-google/manifest-snapshot.json create mode 100644 test/integration/font-optimization/fixtures/with-google/next.config.js rename test/integration/font-optimization/{ => fixtures/with-google}/pages/_document.js (100%) rename test/integration/font-optimization/{ => fixtures/with-google}/pages/amp.js (100%) rename test/integration/font-optimization/{ => fixtures/with-google}/pages/index.js (100%) rename test/integration/font-optimization/{ => fixtures/with-google}/pages/nonce.js (100%) rename test/integration/font-optimization/{ => fixtures/with-google}/pages/stars.js (100%) rename test/integration/font-optimization/{ => fixtures/with-google}/pages/static-head.js (100%) rename test/integration/font-optimization/{ => fixtures/with-google}/pages/with-font.js (100%) rename test/integration/font-optimization/{ => fixtures/with-google}/pages/without-font.js (100%) rename test/integration/font-optimization/{ => fixtures/with-google}/server.js (100%) create mode 100644 test/integration/font-optimization/fixtures/with-typekit/manifest-snapshot.json create mode 100644 test/integration/font-optimization/fixtures/with-typekit/next.config.js create mode 100644 test/integration/font-optimization/fixtures/with-typekit/pages/_document.js create mode 100644 test/integration/font-optimization/fixtures/with-typekit/pages/amp.js create mode 100644 test/integration/font-optimization/fixtures/with-typekit/pages/index.js create mode 100644 test/integration/font-optimization/fixtures/with-typekit/pages/nonce.js create mode 100644 test/integration/font-optimization/fixtures/with-typekit/pages/stars.js create mode 100644 test/integration/font-optimization/fixtures/with-typekit/pages/static-head.js create mode 100644 test/integration/font-optimization/fixtures/with-typekit/pages/with-font.js create mode 100644 test/integration/font-optimization/fixtures/with-typekit/pages/without-font.js create mode 100644 test/integration/font-optimization/fixtures/with-typekit/server.js delete mode 100644 test/integration/font-optimization/test/manifest-snapshot.json diff --git a/docs/basic-features/font-optimization.md b/docs/basic-features/font-optimization.md index aebf952d77376..1c63fda0332ca 100644 --- a/docs/basic-features/font-optimization.md +++ b/docs/basic-features/font-optimization.md @@ -74,7 +74,7 @@ class MyDocument extends Document { export default MyDocument ``` -Automatic Webfont Optimization currently supports Google Fonts, with support for other font providers coming soon. We're also planning to add control over [loading strategies](https://github.com/vercel/next.js/issues/21555) and `font-display` values. +Automatic Webfont Optimization currently supports Google Fonts and Typekit with support for other font providers coming soon. We're also planning to add control over [loading strategies](https://github.com/vercel/next.js/issues/21555) and `font-display` values. ## Disabling Optimization diff --git a/packages/next/next-server/lib/constants.ts b/packages/next/next-server/lib/constants.ts index c07b817533ce2..eed0b3877ba92 100644 --- a/packages/next/next-server/lib/constants.ts +++ b/packages/next/next-server/lib/constants.ts @@ -37,5 +37,8 @@ export const TEMPORARY_REDIRECT_STATUS = 307 export const PERMANENT_REDIRECT_STATUS = 308 export const STATIC_PROPS_ID = '__N_SSG' export const SERVER_PROPS_ID = '__N_SSP' -export const OPTIMIZED_FONT_PROVIDERS = ['https://fonts.googleapis.com/css'] +export const OPTIMIZED_FONT_PROVIDERS = [ + 'https://fonts.googleapis.com/css', + 'https://use.typekit.net/', +] export const STATIC_STATUS_PAGES = ['/500'] diff --git a/packages/next/next-server/lib/head.tsx b/packages/next/next-server/lib/head.tsx index 2a6fa5a40e13b..f035ef5797485 100644 --- a/packages/next/next-server/lib/head.tsx +++ b/packages/next/next-server/lib/head.tsx @@ -147,9 +147,10 @@ function reduceComponents( c.type === 'link' && c.props['href'] && // TODO(prateekbh@): Replace this with const from `constants` when the tree shaking works. - ['https://fonts.googleapis.com/css'].some((url) => - c.props['href'].startsWith(url) - ) + [ + 'https://fonts.googleapis.com/css', + 'https://use.typekit.net/', + ].some((url) => c.props['href'].startsWith(url)) ) { const newProps = { ...(c.props || {}) } newProps['data-href'] = newProps['href'] diff --git a/test/integration/font-optimization/fixtures/with-google/manifest-snapshot.json b/test/integration/font-optimization/fixtures/with-google/manifest-snapshot.json new file mode 100644 index 0000000000000..766f70f7ae879 --- /dev/null +++ b/test/integration/font-optimization/fixtures/with-google/manifest-snapshot.json @@ -0,0 +1,22 @@ +[ + { + "url": "https://fonts.googleapis.com/css?family=Voces", + "content": "@font-face{font-family:'Voces';font-style:normal;font-weight:400;src:url(https://fonts.gstatic.com/s/voces/v12/-F6_fjJyLyU8d7PGDmk.woff) format('woff')}@font-face{font-family:'Voces';font-style:normal;font-weight:400;src:url(https://fonts.gstatic.com/s/voces/v12/-F6_fjJyLyU8d7PIDm_6pClI_ik.woff2) format('woff2');unicode-range:U+0100-024F,U+0259,U+1E00-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:'Voces';font-style:normal;font-weight:400;src:url(https://fonts.gstatic.com/s/voces/v12/-F6_fjJyLyU8d7PGDm_6pClI.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}" + }, + { + "url": "https://fonts.googleapis.com/css2?family=Modak", + "content": "@font-face{font-family:'Modak';font-style:normal;font-weight:400;src:url(https://fonts.gstatic.com/s/modak/v8/EJRYQgs1XtIEsnME.woff) format('woff')}@font-face{font-family:'Modak';font-style:normal;font-weight:400;src:url(https://fonts.gstatic.com/s/modak/v8/EJRYQgs1XtIEskMB-hR77LKVTy8.woff2) format('woff2');unicode-range:U+0900-097F,U+1CD0-1CF6,U+1CF8-1CF9,U+200C-200D,U+20A8,U+20B9,U+25CC,U+A830-A839,U+A8E0-A8FB}@font-face{font-family:'Modak';font-style:normal;font-weight:400;src:url(https://fonts.gstatic.com/s/modak/v8/EJRYQgs1XtIEskMO-hR77LKVTy8.woff2) format('woff2');unicode-range:U+0100-024F,U+0259,U+1E00-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:'Modak';font-style:normal;font-weight:400;src:url(https://fonts.gstatic.com/s/modak/v8/EJRYQgs1XtIEskMA-hR77LKV.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}" + }, + { + "url": "https://fonts.googleapis.com/css2?family=Modak", + "content": "@font-face{font-family:'Modak';font-style:normal;font-weight:400;src:url(https://fonts.gstatic.com/s/modak/v8/EJRYQgs1XtIEsnME.woff) format('woff')}@font-face{font-family:'Modak';font-style:normal;font-weight:400;src:url(https://fonts.gstatic.com/s/modak/v8/EJRYQgs1XtIEskMB-hR77LKVTy8.woff2) format('woff2');unicode-range:U+0900-097F,U+1CD0-1CF6,U+1CF8-1CF9,U+200C-200D,U+20A8,U+20B9,U+25CC,U+A830-A839,U+A8E0-A8FB}@font-face{font-family:'Modak';font-style:normal;font-weight:400;src:url(https://fonts.gstatic.com/s/modak/v8/EJRYQgs1XtIEskMO-hR77LKVTy8.woff2) format('woff2');unicode-range:U+0100-024F,U+0259,U+1E00-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:'Modak';font-style:normal;font-weight:400;src:url(https://fonts.gstatic.com/s/modak/v8/EJRYQgs1XtIEskMA-hR77LKV.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}" + }, + { + "url": "https://fonts.googleapis.com/css2?family=Roboto:wght@700", + "content": "@font-face{font-family:'Roboto';font-style:normal;font-weight:700;src:url(https://fonts.gstatic.com/s/roboto/v27/KFOlCnqEu92Fr1MmWUlvAA.woff) format('woff')}@font-face{font-family:'Roboto';font-style:normal;font-weight:700;src:url(https://fonts.gstatic.com/s/roboto/v27/KFOlCnqEu92Fr1MmWUlfCRc4AMP6lbBP.woff2) format('woff2');unicode-range:U+0460-052F,U+1C80-1C88,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:'Roboto';font-style:normal;font-weight:700;src:url(https://fonts.gstatic.com/s/roboto/v27/KFOlCnqEu92Fr1MmWUlfABc4AMP6lbBP.woff2) format('woff2');unicode-range:U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:'Roboto';font-style:normal;font-weight:700;src:url(https://fonts.gstatic.com/s/roboto/v27/KFOlCnqEu92Fr1MmWUlfCBc4AMP6lbBP.woff2) format('woff2');unicode-range:U+1F00-1FFF}@font-face{font-family:'Roboto';font-style:normal;font-weight:700;src:url(https://fonts.gstatic.com/s/roboto/v27/KFOlCnqEu92Fr1MmWUlfBxc4AMP6lbBP.woff2) format('woff2');unicode-range:U+0370-03FF}@font-face{font-family:'Roboto';font-style:normal;font-weight:700;src:url(https://fonts.gstatic.com/s/roboto/v27/KFOlCnqEu92Fr1MmWUlfCxc4AMP6lbBP.woff2) format('woff2');unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+1EA0-1EF9,U+20AB}@font-face{font-family:'Roboto';font-style:normal;font-weight:700;src:url(https://fonts.gstatic.com/s/roboto/v27/KFOlCnqEu92Fr1MmWUlfChc4AMP6lbBP.woff2) format('woff2');unicode-range:U+0100-024F,U+0259,U+1E00-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:'Roboto';font-style:normal;font-weight:700;src:url(https://fonts.gstatic.com/s/roboto/v27/KFOlCnqEu92Fr1MmWUlfBBc4AMP6lQ.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}" + }, + { + "url": "https://fonts.googleapis.com/css2?family=Roboto:wght@400;700;900&display=swap", + "content": "@font-face{font-family:'Roboto';font-style:normal;font-weight:400;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v27/KFOmCnqEu92Fr1Me5g.woff) format('woff')}@font-face{font-family:'Roboto';font-style:normal;font-weight:700;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v27/KFOlCnqEu92Fr1MmWUlvAA.woff) format('woff')}@font-face{font-family:'Roboto';font-style:normal;font-weight:900;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v27/KFOlCnqEu92Fr1MmYUtvAA.woff) format('woff')}@font-face{font-family:'Roboto';font-style:normal;font-weight:400;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v27/KFOmCnqEu92Fr1Mu72xKKTU1Kvnz.woff2) format('woff2');unicode-range:U+0460-052F,U+1C80-1C88,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:'Roboto';font-style:normal;font-weight:400;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v27/KFOmCnqEu92Fr1Mu5mxKKTU1Kvnz.woff2) format('woff2');unicode-range:U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:'Roboto';font-style:normal;font-weight:400;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v27/KFOmCnqEu92Fr1Mu7mxKKTU1Kvnz.woff2) format('woff2');unicode-range:U+1F00-1FFF}@font-face{font-family:'Roboto';font-style:normal;font-weight:400;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v27/KFOmCnqEu92Fr1Mu4WxKKTU1Kvnz.woff2) format('woff2');unicode-range:U+0370-03FF}@font-face{font-family:'Roboto';font-style:normal;font-weight:400;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v27/KFOmCnqEu92Fr1Mu7WxKKTU1Kvnz.woff2) format('woff2');unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+1EA0-1EF9,U+20AB}@font-face{font-family:'Roboto';font-style:normal;font-weight:400;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v27/KFOmCnqEu92Fr1Mu7GxKKTU1Kvnz.woff2) format('woff2');unicode-range:U+0100-024F,U+0259,U+1E00-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:'Roboto';font-style:normal;font-weight:400;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v27/KFOmCnqEu92Fr1Mu4mxKKTU1Kg.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:'Roboto';font-style:normal;font-weight:700;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v27/KFOlCnqEu92Fr1MmWUlfCRc4AMP6lbBP.woff2) format('woff2');unicode-range:U+0460-052F,U+1C80-1C88,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:'Roboto';font-style:normal;font-weight:700;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v27/KFOlCnqEu92Fr1MmWUlfABc4AMP6lbBP.woff2) format('woff2');unicode-range:U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:'Roboto';font-style:normal;font-weight:700;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v27/KFOlCnqEu92Fr1MmWUlfCBc4AMP6lbBP.woff2) format('woff2');unicode-range:U+1F00-1FFF}@font-face{font-family:'Roboto';font-style:normal;font-weight:700;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v27/KFOlCnqEu92Fr1MmWUlfBxc4AMP6lbBP.woff2) format('woff2');unicode-range:U+0370-03FF}@font-face{font-family:'Roboto';font-style:normal;font-weight:700;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v27/KFOlCnqEu92Fr1MmWUlfCxc4AMP6lbBP.woff2) format('woff2');unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+1EA0-1EF9,U+20AB}@font-face{font-family:'Roboto';font-style:normal;font-weight:700;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v27/KFOlCnqEu92Fr1MmWUlfChc4AMP6lbBP.woff2) format('woff2');unicode-range:U+0100-024F,U+0259,U+1E00-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:'Roboto';font-style:normal;font-weight:700;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v27/KFOlCnqEu92Fr1MmWUlfBBc4AMP6lQ.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:'Roboto';font-style:normal;font-weight:900;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v27/KFOlCnqEu92Fr1MmYUtfCRc4AMP6lbBP.woff2) format('woff2');unicode-range:U+0460-052F,U+1C80-1C88,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:'Roboto';font-style:normal;font-weight:900;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v27/KFOlCnqEu92Fr1MmYUtfABc4AMP6lbBP.woff2) format('woff2');unicode-range:U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:'Roboto';font-style:normal;font-weight:900;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v27/KFOlCnqEu92Fr1MmYUtfCBc4AMP6lbBP.woff2) format('woff2');unicode-range:U+1F00-1FFF}@font-face{font-family:'Roboto';font-style:normal;font-weight:900;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v27/KFOlCnqEu92Fr1MmYUtfBxc4AMP6lbBP.woff2) format('woff2');unicode-range:U+0370-03FF}@font-face{font-family:'Roboto';font-style:normal;font-weight:900;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v27/KFOlCnqEu92Fr1MmYUtfCxc4AMP6lbBP.woff2) format('woff2');unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+1EA0-1EF9,U+20AB}@font-face{font-family:'Roboto';font-style:normal;font-weight:900;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v27/KFOlCnqEu92Fr1MmYUtfChc4AMP6lbBP.woff2) format('woff2');unicode-range:U+0100-024F,U+0259,U+1E00-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:'Roboto';font-style:normal;font-weight:900;font-display:swap;src:url(https://fonts.gstatic.com/s/roboto/v27/KFOlCnqEu92Fr1MmYUtfBBc4AMP6lQ.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}" + } +] diff --git a/test/integration/font-optimization/fixtures/with-google/next.config.js b/test/integration/font-optimization/fixtures/with-google/next.config.js new file mode 100644 index 0000000000000..4ba52ba2c8df6 --- /dev/null +++ b/test/integration/font-optimization/fixtures/with-google/next.config.js @@ -0,0 +1 @@ +module.exports = {} diff --git a/test/integration/font-optimization/pages/_document.js b/test/integration/font-optimization/fixtures/with-google/pages/_document.js similarity index 100% rename from test/integration/font-optimization/pages/_document.js rename to test/integration/font-optimization/fixtures/with-google/pages/_document.js diff --git a/test/integration/font-optimization/pages/amp.js b/test/integration/font-optimization/fixtures/with-google/pages/amp.js similarity index 100% rename from test/integration/font-optimization/pages/amp.js rename to test/integration/font-optimization/fixtures/with-google/pages/amp.js diff --git a/test/integration/font-optimization/pages/index.js b/test/integration/font-optimization/fixtures/with-google/pages/index.js similarity index 100% rename from test/integration/font-optimization/pages/index.js rename to test/integration/font-optimization/fixtures/with-google/pages/index.js diff --git a/test/integration/font-optimization/pages/nonce.js b/test/integration/font-optimization/fixtures/with-google/pages/nonce.js similarity index 100% rename from test/integration/font-optimization/pages/nonce.js rename to test/integration/font-optimization/fixtures/with-google/pages/nonce.js diff --git a/test/integration/font-optimization/pages/stars.js b/test/integration/font-optimization/fixtures/with-google/pages/stars.js similarity index 100% rename from test/integration/font-optimization/pages/stars.js rename to test/integration/font-optimization/fixtures/with-google/pages/stars.js diff --git a/test/integration/font-optimization/pages/static-head.js b/test/integration/font-optimization/fixtures/with-google/pages/static-head.js similarity index 100% rename from test/integration/font-optimization/pages/static-head.js rename to test/integration/font-optimization/fixtures/with-google/pages/static-head.js diff --git a/test/integration/font-optimization/pages/with-font.js b/test/integration/font-optimization/fixtures/with-google/pages/with-font.js similarity index 100% rename from test/integration/font-optimization/pages/with-font.js rename to test/integration/font-optimization/fixtures/with-google/pages/with-font.js diff --git a/test/integration/font-optimization/pages/without-font.js b/test/integration/font-optimization/fixtures/with-google/pages/without-font.js similarity index 100% rename from test/integration/font-optimization/pages/without-font.js rename to test/integration/font-optimization/fixtures/with-google/pages/without-font.js diff --git a/test/integration/font-optimization/server.js b/test/integration/font-optimization/fixtures/with-google/server.js similarity index 100% rename from test/integration/font-optimization/server.js rename to test/integration/font-optimization/fixtures/with-google/server.js diff --git a/test/integration/font-optimization/fixtures/with-typekit/manifest-snapshot.json b/test/integration/font-optimization/fixtures/with-typekit/manifest-snapshot.json new file mode 100644 index 0000000000000..42681af1533b5 --- /dev/null +++ b/test/integration/font-optimization/fixtures/with-typekit/manifest-snapshot.json @@ -0,0 +1,14 @@ +[ + { + "url": "https://use.typekit.net/plm1izr.css", + "content": "@import url(\"https://p.typekit.net/p.css?s=1&k=plm1izr&ht=tk&f=32266&a=23152309&app=typekit&e=css\");@font-face{font-family:\"birra-2\";src:url(\"https://use.typekit.net/af/23e0ad/00000000000000003b9b410c/27/l?primer=7cdcb44be4a7db8877ffa5c0007b8dd865b3bbc383831fe2ea177f62257a9191&fvd=n7&v=3\") format(\"woff2\"),url(\"https://use.typekit.net/af/23e0ad/00000000000000003b9b410c/27/d?primer=7cdcb44be4a7db8877ffa5c0007b8dd865b3bbc383831fe2ea177f62257a9191&fvd=n7&v=3\") format(\"woff\"),url(\"https://use.typekit.net/af/23e0ad/00000000000000003b9b410c/27/a?primer=7cdcb44be4a7db8877ffa5c0007b8dd865b3bbc383831fe2ea177f62257a9191&fvd=n7&v=3\") format(\"opentype\");font-display:auto;font-style:normal;font-weight:700}.tk-birra-2{font-family:\"birra-2\",serif}@import url(\"https://p.typekit.net/p.css?s=1&k=plm1izr&ht=tk&f=32266&a=23152309&app=typekit&e=css\");@font-face{font-family:\"birra-2\";src:url(\"https://use.typekit.net/af/23e0ad/00000000000000003b9b410c/27/l?primer=7cdcb44be4a7db8877ffa5c0007b8dd865b3bbc383831fe2ea177f62257a9191&fvd=n7&v=3\") format(\"woff2\"),url(\"https://use.typekit.net/af/23e0ad/00000000000000003b9b410c/27/d?primer=7cdcb44be4a7db8877ffa5c0007b8dd865b3bbc383831fe2ea177f62257a9191&fvd=n7&v=3\") format(\"woff\"),url(\"https://use.typekit.net/af/23e0ad/00000000000000003b9b410c/27/a?primer=7cdcb44be4a7db8877ffa5c0007b8dd865b3bbc383831fe2ea177f62257a9191&fvd=n7&v=3\") format(\"opentype\");font-display:auto;font-style:normal;font-weight:700}.tk-birra-2{font-family:\"birra-2\",serif}" + }, + { + "url": "https://use.typekit.net/ucs7mcf.css", + "content": "@import url(\"https://p.typekit.net/p.css?s=1&k=ucs7mcf&ht=tk&f=43886&a=23152309&app=typekit&e=css\");@font-face{font-family:\"flegrei\";src:url(\"https://use.typekit.net/af/74a5d1/00000000000000003b9b3d6e/27/l?primer=7cdcb44be4a7db8877ffa5c0007b8dd865b3bbc383831fe2ea177f62257a9191&fvd=n4&v=3\") format(\"woff2\"),url(\"https://use.typekit.net/af/74a5d1/00000000000000003b9b3d6e/27/d?primer=7cdcb44be4a7db8877ffa5c0007b8dd865b3bbc383831fe2ea177f62257a9191&fvd=n4&v=3\") format(\"woff\"),url(\"https://use.typekit.net/af/74a5d1/00000000000000003b9b3d6e/27/a?primer=7cdcb44be4a7db8877ffa5c0007b8dd865b3bbc383831fe2ea177f62257a9191&fvd=n4&v=3\") format(\"opentype\");font-display:auto;font-style:normal;font-weight:400}.tk-flegrei{font-family:\"flegrei\",sans-serif}@import url(\"https://p.typekit.net/p.css?s=1&k=ucs7mcf&ht=tk&f=43886&a=23152309&app=typekit&e=css\");@font-face{font-family:\"flegrei\";src:url(\"https://use.typekit.net/af/74a5d1/00000000000000003b9b3d6e/27/l?primer=7cdcb44be4a7db8877ffa5c0007b8dd865b3bbc383831fe2ea177f62257a9191&fvd=n4&v=3\") format(\"woff2\"),url(\"https://use.typekit.net/af/74a5d1/00000000000000003b9b3d6e/27/d?primer=7cdcb44be4a7db8877ffa5c0007b8dd865b3bbc383831fe2ea177f62257a9191&fvd=n4&v=3\") format(\"woff\"),url(\"https://use.typekit.net/af/74a5d1/00000000000000003b9b3d6e/27/a?primer=7cdcb44be4a7db8877ffa5c0007b8dd865b3bbc383831fe2ea177f62257a9191&fvd=n4&v=3\") format(\"opentype\");font-display:auto;font-style:normal;font-weight:400}.tk-flegrei{font-family:\"flegrei\",sans-serif}" + }, + { + "url": "https://use.typekit.net/erd0sed.css", + "content": "@import url(\"https://p.typekit.net/p.css?s=1&k=erd0sed&ht=tk&f=43885&a=23152309&app=typekit&e=css\");@font-face{font-family:\"pantelleria\";src:url(\"https://use.typekit.net/af/1f141c/00000000000000003b9b3d6f/27/l?primer=7cdcb44be4a7db8877ffa5c0007b8dd865b3bbc383831fe2ea177f62257a9191&fvd=n4&v=3\") format(\"woff2\"),url(\"https://use.typekit.net/af/1f141c/00000000000000003b9b3d6f/27/d?primer=7cdcb44be4a7db8877ffa5c0007b8dd865b3bbc383831fe2ea177f62257a9191&fvd=n4&v=3\") format(\"woff\"),url(\"https://use.typekit.net/af/1f141c/00000000000000003b9b3d6f/27/a?primer=7cdcb44be4a7db8877ffa5c0007b8dd865b3bbc383831fe2ea177f62257a9191&fvd=n4&v=3\") format(\"opentype\");font-display:auto;font-style:normal;font-weight:400}.tk-pantelleria{font-family:\"pantelleria\",sans-serif}@import url(\"https://p.typekit.net/p.css?s=1&k=erd0sed&ht=tk&f=43885&a=23152309&app=typekit&e=css\");@font-face{font-family:\"pantelleria\";src:url(\"https://use.typekit.net/af/1f141c/00000000000000003b9b3d6f/27/l?primer=7cdcb44be4a7db8877ffa5c0007b8dd865b3bbc383831fe2ea177f62257a9191&fvd=n4&v=3\") format(\"woff2\"),url(\"https://use.typekit.net/af/1f141c/00000000000000003b9b3d6f/27/d?primer=7cdcb44be4a7db8877ffa5c0007b8dd865b3bbc383831fe2ea177f62257a9191&fvd=n4&v=3\") format(\"woff\"),url(\"https://use.typekit.net/af/1f141c/00000000000000003b9b3d6f/27/a?primer=7cdcb44be4a7db8877ffa5c0007b8dd865b3bbc383831fe2ea177f62257a9191&fvd=n4&v=3\") format(\"opentype\");font-display:auto;font-style:normal;font-weight:400}.tk-pantelleria{font-family:\"pantelleria\",sans-serif}" + } +] diff --git a/test/integration/font-optimization/fixtures/with-typekit/next.config.js b/test/integration/font-optimization/fixtures/with-typekit/next.config.js new file mode 100644 index 0000000000000..4ba52ba2c8df6 --- /dev/null +++ b/test/integration/font-optimization/fixtures/with-typekit/next.config.js @@ -0,0 +1 @@ +module.exports = {} diff --git a/test/integration/font-optimization/fixtures/with-typekit/pages/_document.js b/test/integration/font-optimization/fixtures/with-typekit/pages/_document.js new file mode 100644 index 0000000000000..33cd61eee7ef8 --- /dev/null +++ b/test/integration/font-optimization/fixtures/with-typekit/pages/_document.js @@ -0,0 +1,27 @@ +import * as React from 'react' +/// @ts-ignore +import Document, { Main, NextScript, Head } from 'next/document' + +export default class MyDocument extends Document { + constructor(props) { + super(props) + const { __NEXT_DATA__, ids } = props + if (ids) { + __NEXT_DATA__.ids = ids + } + } + + render() { + return ( + + + + + +
+ + + + ) + } +} diff --git a/test/integration/font-optimization/fixtures/with-typekit/pages/amp.js b/test/integration/font-optimization/fixtures/with-typekit/pages/amp.js new file mode 100644 index 0000000000000..53ac86b915b16 --- /dev/null +++ b/test/integration/font-optimization/fixtures/with-typekit/pages/amp.js @@ -0,0 +1,9 @@ +import React from 'react' + +const Page = () => { + return
Hi!
+} + +export const config = { amp: true } + +export default Page diff --git a/test/integration/font-optimization/fixtures/with-typekit/pages/index.js b/test/integration/font-optimization/fixtures/with-typekit/pages/index.js new file mode 100644 index 0000000000000..39cf2d1f7b376 --- /dev/null +++ b/test/integration/font-optimization/fixtures/with-typekit/pages/index.js @@ -0,0 +1,7 @@ +import React from 'react' + +const Page = () => { + return
Hi!
+} + +export default Page diff --git a/test/integration/font-optimization/fixtures/with-typekit/pages/nonce.js b/test/integration/font-optimization/fixtures/with-typekit/pages/nonce.js new file mode 100644 index 0000000000000..2c6b7e91af930 --- /dev/null +++ b/test/integration/font-optimization/fixtures/with-typekit/pages/nonce.js @@ -0,0 +1,19 @@ +import React from 'react' +import Head from 'next/head' + +const Page = () => { + return ( + <> + + + +
Hi!
+ + ) +} + +export default Page diff --git a/test/integration/font-optimization/fixtures/with-typekit/pages/stars.js b/test/integration/font-optimization/fixtures/with-typekit/pages/stars.js new file mode 100644 index 0000000000000..c8ebb251db270 --- /dev/null +++ b/test/integration/font-optimization/fixtures/with-typekit/pages/stars.js @@ -0,0 +1,26 @@ +import Head from 'next/head' + +function Home({ stars }) { + return ( +
+ + Create Next App + + + + +
+
Next stars: {stars}
+
+
+ ) +} + +Home.getInitialProps = async () => { + return { stars: Math.random() * 1000 } +} + +export default Home diff --git a/test/integration/font-optimization/fixtures/with-typekit/pages/static-head.js b/test/integration/font-optimization/fixtures/with-typekit/pages/static-head.js new file mode 100644 index 0000000000000..9b0ba8af28a32 --- /dev/null +++ b/test/integration/font-optimization/fixtures/with-typekit/pages/static-head.js @@ -0,0 +1,15 @@ +import React from 'react' +import Head from 'next/head' + +const Page = () => { + return ( + <> + + + +
Hi!
+ + ) +} + +export default Page diff --git a/test/integration/font-optimization/fixtures/with-typekit/pages/with-font.js b/test/integration/font-optimization/fixtures/with-typekit/pages/with-font.js new file mode 100644 index 0000000000000..b1a1fa4011d49 --- /dev/null +++ b/test/integration/font-optimization/fixtures/with-typekit/pages/with-font.js @@ -0,0 +1,27 @@ +import Head from 'next/head' +import Link from 'next/link' + +const WithFont = () => { + return ( + <> + + + + +
+ Page with custom fonts +
+
+ Without font +
+ + ) +} + +export const getServerSideProps = async () => { + return { + props: {}, + } +} + +export default WithFont diff --git a/test/integration/font-optimization/fixtures/with-typekit/pages/without-font.js b/test/integration/font-optimization/fixtures/with-typekit/pages/without-font.js new file mode 100644 index 0000000000000..2185cb252e07e --- /dev/null +++ b/test/integration/font-optimization/fixtures/with-typekit/pages/without-font.js @@ -0,0 +1,26 @@ +import Head from 'next/head' +import Link from 'next/link' + +const WithoutFont = () => { + return ( + <> + + + +
+ Page without custom fonts +
+
+ With font +
+ + ) +} + +export const getServerSideProps = async () => { + return { + props: {}, + } +} + +export default WithoutFont diff --git a/test/integration/font-optimization/fixtures/with-typekit/server.js b/test/integration/font-optimization/fixtures/with-typekit/server.js new file mode 100644 index 0000000000000..6a98fa3d30806 --- /dev/null +++ b/test/integration/font-optimization/fixtures/with-typekit/server.js @@ -0,0 +1,111 @@ +const http = require('http') +const url = require('url') +const fs = require('fs') +const path = require('path') +const server = http.createServer(async (req, res) => { + let { pathname } = url.parse(req.url) + pathname = pathname.replace(/\/$/, '') + let isDataReq = false + if (pathname.startsWith('/_next/data')) { + isDataReq = true + pathname = pathname + .replace(`/_next/data/${process.env.BUILD_ID}/`, '/') + .replace(/\.json$/, '') + } + console.log('serving', pathname) + + if (pathname === '/favicon.ico') { + res.statusCode = 404 + return res.end() + } + + if (pathname.startsWith('/_next/static/')) { + res.write( + fs.readFileSync( + path.join( + __dirname, + './.next/static/', + decodeURI(pathname.slice('/_next/static/'.length)) + ), + 'utf8' + ) + ) + return res.end() + } else { + const ext = isDataReq ? 'json' : 'html' + if ( + fs.existsSync( + path.join(__dirname, `./.next/serverless/pages${pathname}.${ext}`) + ) + ) { + res.write( + fs.readFileSync( + path.join(__dirname, `./.next/serverless/pages${pathname}.${ext}`), + 'utf8' + ) + ) + return res.end() + } + + let re + try { + re = require(`./.next/serverless/pages${pathname}`) + } catch { + const d = decodeURI(pathname) + if ( + fs.existsSync( + path.join(__dirname, `./.next/serverless/pages${d}.${ext}`) + ) + ) { + res.write( + fs.readFileSync( + path.join(__dirname, `./.next/serverless/pages${d}.${ext}`), + 'utf8' + ) + ) + return res.end() + } + + const routesManifest = require('./.next/routes-manifest.json') + const { dynamicRoutes } = routesManifest + dynamicRoutes.some(({ page, regex }) => { + if (new RegExp(regex).test(pathname)) { + if ( + fs.existsSync( + path.join(__dirname, `./.next/serverless/pages${page}.${ext}`) + ) + ) { + res.write( + fs.readFileSync( + path.join(__dirname, `./.next/serverless/pages${page}.${ext}`), + 'utf8' + ) + ) + res.end() + return true + } + + re = require(`./.next/serverless/pages${page}`) + return true + } + return false + }) + } + if (!res.finished) { + try { + return await (typeof re.render === 'function' + ? re.render(req, res) + : re.default(req, res)) + } catch (e) { + console.log('FAIL_FUNCTION', e) + res.statusCode = 500 + res.write('FAIL_FUNCTION') + res.end() + } + } + } +}) + +server.listen(process.env.PORT, () => { + console.log('ready on', process.env.PORT) +}) diff --git a/test/integration/font-optimization/test/index.test.js b/test/integration/font-optimization/test/index.test.js index 317a3477d39a8..76b5d4b5d9c4a 100644 --- a/test/integration/font-optimization/test/index.test.js +++ b/test/integration/font-optimization/test/index.test.js @@ -1,6 +1,8 @@ /* eslint-env jest */ +import cheerio from 'cheerio' import { join } from 'path' +import fs from 'fs-extra' import { killApp, findPort, @@ -9,17 +11,10 @@ import { renderViaHTTP, initNextServerScript, } from 'next-test-utils' -import fs from 'fs-extra' -import cheerio from 'cheerio' jest.setTimeout(1000 * 60 * 2) -const appDir = join(__dirname, '../') -const nextConfig = join(appDir, 'next.config.js') -let builtServerPagesDir -let builtPage -let appPort -let app +const fixturesDir = join(__dirname, '..', 'fixtures') const fsExists = (file) => fs @@ -27,7 +22,7 @@ const fsExists = (file) => .then(() => true) .catch(() => false) -async function getBuildId() { +async function getBuildId(appDir) { return fs.readFile(join(appDir, '.next', 'BUILD_ID'), 'utf8') } @@ -36,196 +31,240 @@ const startServerlessEmulator = async (dir, port) => { const env = Object.assign( {}, { ...process.env }, - { PORT: port, BUILD_ID: await getBuildId() } + { PORT: port, BUILD_ID: await getBuildId(dir) } ) return initNextServerScript(scriptPath, /ready on/i, env) } -function runTests() { - it('should inline the google fonts for static pages', async () => { - const html = await renderViaHTTP(appPort, '/index') - expect(await fsExists(builtPage('font-manifest.json'))).toBe(true) - expect(html).toContain( - '' - ) - expect(html).toMatch( - /