Skip to content

Viewport exports #57302

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 15 commits into from
Oct 25, 2023
Merged

Viewport exports #57302

merged 15 commits into from
Oct 25, 2023

Conversation

huozhi
Copy link
Member

@huozhi huozhi commented Oct 24, 2023

Story Time

Metadata API introduced two exports metadata and generateMetadata to the pages and layouts under app router, as partial prerendering work is going on and people are desiring to render the metadata asynchronizly, this change will be the preparation for moving to the dynamic & asynchronized land. In short, if we can render the metadata asynchronizedly, it will benefit the performance of the initial page loading and client page transiation a lot. Any slow data fetching can be handled while the essential page "shell" is rendered.

For meta tags, there're few ones will visually affect your web page, such as <meta name="viewport">, <meta name="theme color"> and <meta name="color-scheme">, rendering them lately after the page frame is ready might bring flickering to the page such as revreting whole page's theme color or shaking due to viewport updates. Those meta are not majorly the "metadata" for SEO, but more for user experience when opening the page. If we're rendering everything as async meta tags, it won't be ideal due to the flickering on your web pages.

Solution Preparation

We'll want to render the meta tags separately to make sure the visual ones are rendered as blocking along with web page, and then the ones for SEO or bots can be flushed later by later, like a suspense boundary keeps emitting them into the head of html.

We optionally picked up 3 meta tag "viewport", "theme-color" and "color-scheme" to be render first into the web page with html "shell", to guarantee the layout viewport and basic styling are rendered first.

This PR introduced two module export in the page and layout files: viewport and generateViewport, in order to separate the visual meta tags from the SEO metadata.

API

// page.js | layout.js
export const viewport = {
  // viewport meta tag
  width: 'device-width',
  initialScale: 1,
  maximumScale: 1,
  interactiveWidget: 'resizes-visual',
  // visual meta tags
  colorScheme: 'dark',
  themeColor: { color: 'cyan', media: '(prefers-color-scheme: dark)' },
}

There's also a dynamic API like what we did for metadata API

// page.js | layout.js
export function generateViewport() {
   return { ... }
}

Notice

This PR won't get SEO metadata rendered asyncronizedly, instead it's a preparation for the later work in partial prerendering and async metadata. We'll encourage the Next.js community moving to the new metadata viewport API if you're customzing those 3 meta tags. Usually you don't have to change viewport itself, so mostly like only theme-color and color-scheme could relate to it.

@ijjk
Copy link
Member

ijjk commented Oct 24, 2023

Tests Passed

@ijjk
Copy link
Member

ijjk commented Oct 24, 2023

Stats from current PR

Default Build (Increase detected ⚠️)
General Overall increase ⚠️
vercel/next.js canary vercel/next.js metadata-viewport-api Change
buildDuration 10.1s 10.1s N/A
buildDurationCached 5.9s 5.9s N/A
nodeModulesSize 175 MB 175 MB ⚠️ +132 kB
nextStartRea..uration (ms) 415ms 416ms N/A
Client Bundles (main, webpack)
vercel/next.js canary vercel/next.js metadata-viewport-api Change
199-HASH.js gzip 32.3 kB 32.4 kB N/A
3f784ff6-HASH.js gzip 53.2 kB 53.2 kB N/A
99.HASH.js gzip 182 B 182 B
framework-HASH.js gzip 45.5 kB 45.5 kB
main-app-HASH.js gzip 254 B 252 B N/A
main-HASH.js gzip 35.3 kB 35.4 kB N/A
webpack-HASH.js gzip 1.75 kB 1.75 kB N/A
Overall change 45.7 kB 45.7 kB
Legacy Client Bundles (polyfills)
vercel/next.js canary vercel/next.js metadata-viewport-api Change
polyfills-HASH.js gzip 31 kB 31 kB
Overall change 31 kB 31 kB
Client Pages
vercel/next.js canary vercel/next.js metadata-viewport-api Change
_app-HASH.js gzip 206 B 205 B N/A
_error-HASH.js gzip 182 B 180 B N/A
amp-HASH.js gzip 506 B 505 B N/A
css-HASH.js gzip 322 B 323 B N/A
dynamic-HASH.js gzip 2.59 kB 2.59 kB
edge-ssr-HASH.js gzip 260 B 259 B N/A
head-HASH.js gzip 350 B 350 B
hooks-HASH.js gzip 369 B 369 B
image-HASH.js gzip 4.38 kB 4.38 kB N/A
index-HASH.js gzip 256 B 256 B
link-HASH.js gzip 2.67 kB 2.67 kB N/A
routerDirect..HASH.js gzip 316 B 318 B N/A
script-HASH.js gzip 385 B 384 B N/A
withRouter-HASH.js gzip 319 B 319 B
1afbb74e6ecf..834.css gzip 106 B 106 B
Overall change 3.99 kB 3.99 kB
Client Build Manifests
vercel/next.js canary vercel/next.js metadata-viewport-api Change
_buildManifest.js gzip 484 B 482 B N/A
Overall change 0 B 0 B
Rendered Page Sizes
vercel/next.js canary vercel/next.js metadata-viewport-api Change
index.html gzip 528 B 530 B N/A
link.html gzip 542 B 543 B N/A
withRouter.html gzip 524 B 524 B
Overall change 524 B 524 B
Edge SSR bundle Size Overall increase ⚠️
vercel/next.js canary vercel/next.js metadata-viewport-api Change
edge-ssr.js gzip 96 kB 96 kB N/A
page.js gzip 139 kB 140 kB ⚠️ +406 B
Overall change 139 kB 140 kB ⚠️ +406 B
Middleware size
vercel/next.js canary vercel/next.js metadata-viewport-api Change
middleware-b..fest.js gzip 623 B 625 B N/A
middleware-r..fest.js gzip 150 B 151 B N/A
middleware.js gzip 25.8 kB 25.8 kB N/A
edge-runtime..pack.js gzip 1.92 kB 1.92 kB
Overall change 1.92 kB 1.92 kB
Diff details
Diff for page.js

Diff too large to display

Diff for edge-ssr.js

Diff too large to display

Commit: 6bcc069

@huozhi huozhi changed the title (wip) screen metadata (wip) viewport metadata Oct 24, 2023
@huozhi huozhi requested a review from gnoff October 24, 2023 21:35
Copy link
Contributor

@gnoff gnoff left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good. We'll end up needing to separate the resolvers into their own flows later when we move the metadata rendering to a suspense boundary but for now this seems landable. lmk when all tests pass and I'll do a final review and stamp

@huozhi huozhi changed the title (wip) viewport metadata Viewport exports Oct 25, 2023
@huozhi huozhi marked this pull request as ready for review October 25, 2023 03:48
@huozhi huozhi requested a review from wyattjoh as a code owner October 25, 2023 03:48
@huozhi huozhi requested a review from gnoff October 25, 2023 03:48
@gnoff
Copy link
Contributor

gnoff commented Oct 25, 2023

@huozhi typo in your description

generateMetadata should be generateViewport

Comment on lines +9 to +10
width: 'device-width',
initialScale: 1,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

all keys should be present here since the Resolved type should have no optional members

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I shared the type there because it's almost the same, another resolved viewport layout type might introduce a few extra bytes but very little gain there

@kodiakhq kodiakhq bot merged commit a301eb6 into canary Oct 25, 2023
@kodiakhq kodiakhq bot deleted the metadata-viewport-api branch October 25, 2023 05:20
@leerob
Copy link
Member

leerob commented Oct 25, 2023

Just to clarify, if I use viewport or theme-color in the current metadata, they will continue to work, but we'll start to recommend moving to this now, correct?

@gnoff
Copy link
Contributor

gnoff commented Oct 25, 2023

Unfortunately no, we have to do the breaking change part in Next 14 so they have to already not work in the old API when we launch. If we delivered viewport in an earlier minor in 13 we could have had both for a while but we just didn't do the work in time for a prior patch release.

If you do use those tags in the current metadata API you get a warning to move them to the viewport API. Might be worth looking at that warning and also how we might make this codemodable. That said these particular metadata are not likely invasive in a codebase so once you know you need to move it to upgrade it shouldn't be too big a chore to do so

shuding pushed a commit that referenced this pull request Oct 25, 2023
…#57436)

This PR adds the codemods transforming certain fields from `metadata`
export to `viewport` export, will still preserve rest metadata export
properties. We don't cover `generateMetadata` to `generateViewport` as
there might be more complex logic inside the function which is hard to
apply the codemods rules.

TLDR: Codemods for #57302
@huozhi
Copy link
Member Author

huozhi commented Oct 25, 2023

Land a codemod for this migration in #57436

@github-actions github-actions bot added the locked label Nov 9, 2023
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Nov 9, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants