## 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
```ts
// 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
```ts
// 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.
A continuation of #51864 with RedirectType used in an e2e test and some
ts-ignores removed from the codebase. Happy to split it into two PRs but
I left comments in the two consequential files
---------
### Issue
x-ref:
https://github.com/vercel/next.js/actions/runs/5469070005/jobs/9957658991?pr=52282#step:27:526
metadata tests are failing as flaky recently, then after digging into
it, noticed it as a hmr issue.
**Steps to repro with metadata test app**
The later (after the 1st one) visited page with client components
imports sometimes throw an full reload refresh warning
> Fast Refresh will perform a full reload when you edit a file that's
imported by modules
outside of the React rendering tree.
Turns out there's some unexpected hmr events when `"sync"` event is
triggered, and client tries to apply the updates but then failed. This
PR excludes the triggering by `"sync"` for RSC pages updates. `'sync'`
event with errors/warnings will still be handled and then `'built'`
event will be handled with hot reload updates
Possibly related to #40184
* Add `manifest.webmanifest` and `manifest.(j|t)xs?` support for
manifest.json route
* Add `Manifest` type for it for autocomplete purpose.
Remove the exports for `SitemapFile` and `RobotsFile` globally, will
discuss how to re-export them with better naming later
Small fix for `Robots` typing, should allow `string | string[]` for user
agent of single Robots
Closes NEXT-839
---------
* Use next-swc to detect invalid metadata exports
* In client components page under app dir, metadata exports are not
available
* In server components page under app dir, metadata and gM exports can
be exported together
Move sync metadata / async metadata typing resolving test to UT
Closes NEXT-368
---------
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
Resolves the comments from beta docs
* fix typing of `metadata.authors` rendering
* add `metadata.manifest` field
## Bug
- [x] Related issues linked using `fixes #number`
- [x] Integration tests added
- [ ] Errors have a helpful link attached, see [`contributing.md`](https://github.com/vercel/next.js/blob/canary/contributing.md)
The very-newly-released `generateMetadata` function currently does not
allow itself to be synchronous. It leads to situations like this
```ts
export async function generateMetadata() {
return { title: "Hello, world!" };
}
```
where there's evidently no reason to use `async`, but it's forced by
Next.js.
This PR aims to remove this restriction: `generateMetadata` can be
synchronous now.
## Bug
- [x] Related issues linked using `fixes #45685`
- [ ] Integration tests added
- [ ] Errors have a helpful link attached, see
[`contributing.md`](https://github.com/vercel/next.js/blob/canary/contributing.md)
## 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]
[e2e](https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs)
tests added
- [ ] Documentation added
- [ ] Telemetry added. In case of a feature if it's used or not.
- [ ] Errors have a helpful link attached, see
[`contributing.md`](https://github.com/vercel/next.js/blob/canary/contributing.md)
## Documentation / Examples
- [ ] Make sure the linting passes by running `pnpm build && pnpm lint`
- [ ] The "examples guidelines" are followed from [our contributing
doc](https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md)
Signed-off-by: Vu Van Dung <me@joulev.dev>
Co-authored-by: Jiachi Liu <inbox@huozhi.im>
Closes NEXT-397
Resolve `metadata` and `generateMetadata()` exports along with head
during rendering, this is the easy way for now to collect all the
metadata properly. Since we can access segment params and search params
only in rendering, so I moved all the resolving logic from loader to
render process.
<!--
Thanks for opening a PR! Your contribution is much appreciated.
To make sure your PR is handled as smoothly as possible we request that
you follow the checklist sections below.
Choose the right checklist for the change that you're making:
-->
## Feature
- [x] 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]
[e2e](https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs)
tests added
- [ ] Documentation added
- [ ] Telemetry added. In case of a feature if it's used or not.
- [ ] Errors have a helpful link attached, see
[`contributing.md`](https://github.com/vercel/next.js/blob/canary/contributing.md)
---------
Co-authored-by: Tim Neutkens <tim@timneutkens.nl>