Commit Graph

123 Commits

Author SHA1 Message Date
Tobias Koppers 4494261bd7 Remove devCacheControlNoCache experimental option (hard-code no-cache) (#91503)
### What?

Removes the `experimental.devCacheControlNoCache` config option entirely
and hard-codes `no-cache, must-revalidate` as the dev server
`Cache-Control` header value.

Previously the option controlled whether the dev server responded with:
- `no-store, must-revalidate` (default, `false`)
- `no-cache, must-revalidate` (opt-in, `true`)

This PR first flips the default to `true`, then removes the option
altogether — making `no-cache, must-revalidate` unconditional in all dev
code paths.

### Why?

`no-cache` is strictly better than `no-store` for the dev server:
- `no-cache` allows the browser to revalidate (conditional
`If-None-Match`/`If-Modified-Since` requests), letting the server
respond with `304 Not Modified` when nothing changed → faster page loads
during development.
- `no-store` forces a full re-fetch every time, discarding valid cached
responses.

Since `no-cache` is the correct behavior for all dev users, the toggle
has no remaining value and can be removed to simplify the codebase.

### How?

**Two commits:**

1. `bcec825` — Flip the default from `false` → `true`; update
tests/fixtures/manifest to reflect the new default.

2. `e6e919f` — Remove the option entirely:
- Deleted `devCacheControlNoCache?: boolean` from `ExperimentalConfig`
interface, `config-schema.ts` Zod schema, `defaultConfig`,
`NextConfigRuntime`, and `getNextConfigRuntime()`.
- Replaced all four conditional ternaries in `base-server.ts`,
`router-server.ts`, `pages-handler.ts`, and `app-page.ts` with the
hard-coded string `'no-cache, must-revalidate'`.
- Deleted the `dev-cache-control-no-cache-disabled` test suite (was
testing the `false` path which no longer exists).
- Simplified the remaining `dev-cache-control-no-cache` test (removed
experimental framing).
   - Synced `rspack-dev-tests-manifest.json`.

---------

Co-authored-by: Tobias Koppers <sokra@users.noreply.github.com>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Vercel <vercel[bot]@users.noreply.github.com>
2026-03-17 20:13:01 +01:00
JJ Kasper da6fb315d5 Cleanup non-generic assertions in our deploy test suite (#90894)
This makes sure we don't have assertions that will only pass in one
environment e.g. these should work for running against bun and not just
node or against a local metadata URL not just a deployed https fully
qualified domain. Ensures others can leverage this test suite for their
own verification easily.
2026-03-04 15:59:07 -08:00
Jiachi Liu 023be2e88a metadata: use fixed segment in dynamic routes with static metadata files (#88113) 2026-01-07 10:55:09 +01:00
Wyatt Johnson 776625634d Remove deprecated experimental_ppr route-level configuration (#84871)
### What?

Removes the deprecated `experimental_ppr` route-level configuration
option from Next.js.

### Why?

The PPR configuration feature has been deprecated in favor of the cache
components feature flag. The `experimental_ppr` route-level option no
longer has any effect since incremental PPR is not supported with cache
components.

Rather than silently ignoring this configuration, this change ensures
that users receive an explicit error when they attempt to export
`experimental_ppr` from their routes. This provides clear feedback that
the configuration needs to be removed when migrating to the cache
components approach.

### How?

- Removed `experimental_ppr` from the segment config schema and types
(both Rust and TypeScript)
- Updated `checkIsRoutePPREnabled` to no longer accept the `appConfig`
parameter since route-level config is removed
- Added `experimental_ppr` to the list of possibly invalid exports when
cache components are enabled, ensuring users get an error instead of
silent failure
- Removed unused `reduceAppConfig` import that was no longer needed
after these changes
2025-10-15 13:03:00 -06:00
Hendrik Liebau c201b3d387 Allow metadataBase to be a string URL in addition to URL instance (#84297)
As of #49343, in dev mode only, we accidentally change the `metadataBase` from an `URL` instance to a URL string, when passing it to child layouts or pages via the `parent` argument in `generateMetadata`. This is because we clone the metadata object via `JSON.stringify`/`parse` and then freeze it, to prevent relying on mutating resolved metadata. The replacer/reviver functions we used to clone the metadata didn't properly handle preserving `URL` instances as intended, so they were turned into strings.

Because user code already had to handle the case of `metadataBase` potentially being a string at runtime in dev mode, we can just officially reflect that as well in our types, not only for the `ResolvedMetadata` input type, but also for the `Metadata` output type.

This also enables `'use cache'` being used in `generateMetadata`, because React currently does not support transporting `URL` instances from one environment to another (e.g. `Server` to `Cache`).

Note that all other URL properties in `Metadata` and `ResolvedMetadata` already allowed `string`, so this only affects `metadataBase`.

To resolve the ambiguity between dev and prod, we're now always transforming all URL instances to strings, before passing the resolved metadata to `generateMetadata`. This is also reflected in the `ResolvedMetadata` type.
2025-10-01 22:47:47 +02:00
M. Abdullah 3ea8310f20 fix(metadata): make formatDetection respect true/false properly (#83924)
### What?

Fixes the `FormatDetectionMeta` function so that it correctly respects
true vs false values.

### Why?

Previously, both true and false values output key=no. According to
Apple’s spec, Safari defaults to enabling detection when the tag is
absent, and only no should be added when explicitly disabled.

### How?

- Now false → outputs key=no
- true → omits the tag (defaults to Safari’s behavior)

### Reference

- [Apple docs on
format-detection](https://developer.apple.com/library/archive/documentation/AppleApplications/Reference/SafariHTMLRef/Articles/MetaTags.html#//apple_ref/doc/uid/TP40008193-SW1)

Fixes #83666

---------

Co-authored-by: Jiwon Choi <devjiwonchoi@gmail.com>
2025-09-26 21:25:15 +00:00
Jiwon Choi 1482af898d [dev] Serve static metadata from filesystem (#83460)
Current metadata files are compiled to `route.js` files. This happens
not only to metadata API (e.g., `icon.tsx`), but to static files as
well, which is unnecessary. In development, this leads to confusing logs
such as:

```
Compiled /favicon.ico in ...ms
```

Users may reasonably wonder why Next.js is "compiling" a static file.

Static files can be served directly from the filesystem, like
`_next/static/` assets. Therefore, in development, skip compilation of
static metadata files and serve them as static.

For production, we can follow up in a separate PR to skip compiling the
`route.js` files and emit static files to the dist directory, and also
serve from the filesystem there as well.

Closes [NEXT-4338](https://linear.app/vercel/issue/NEXT-4338)

---

TODO(s) to follow up:

- Fix Cache Components failing build with metadata files inside the
dynamic route.
- x-ref: [slack
thread](https://vercel.slack.com/archives/C06N3AXRQ82/p1738053808940719)

---------

Co-authored-by: Jiachi Liu <inbox@huozhi.im>
2025-09-10 14:25:41 +02:00
Jiachi Liu d8e1aca88c [metadata] update metadata routes cache headers (#83215) 2025-08-29 20:22:42 +02:00
Jiachi Liu 81bd026e75 [test] update the metadata deployment cache header tests (#83217) 2025-08-29 13:05:24 +02:00
Sebastian "Sebbie" Silbermann 259f9a6220 [test] Avoid flaky assertions due to dynamic metadata (#81373) 2025-07-08 12:32:36 +02:00
Sebastian "Sebbie" Silbermann 0b6a580c6c [test] Add repro for SSR bug when large chunks are deferred in Flight (#80661) 2025-06-20 12:57:03 +02:00
Tim Neutkens 6e51845ac4 Rename process.env.TURBOPACK to process.env.IS_TURBOPACK_TEST for tests (#77892)
Preparation for removing `process.env.TURBOPACK` being added to
Turbopack tests. That way we can properly test `next start` without
`process.env.TURBOPACK` being set.

<!-- 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(s) that you're making:

## For Contributors

### Improving Documentation

- Run `pnpm prettier-fix` to fix formatting issues before opening the
PR.
- Read the Docs Contribution Guide to ensure your contribution follows
the docs guidelines:
https://nextjs.org/docs/community/contribution-guide

### Adding or Updating Examples

- The "examples guidelines" are followed from our contributing doc
https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md
- Make sure the linting passes by running `pnpm build && pnpm lint`. See
https://github.com/vercel/next.js/blob/canary/contributing/repository/linting.md

### Fixing a bug

- Related issues linked using `fixes #number`
- Tests added. See:
https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs
- Errors have a helpful link attached, see
https://github.com/vercel/next.js/blob/canary/contributing.md

### Adding a feature

- Implements an existing feature request or RFC. Make sure the feature
request has been accepted for implementation before opening a PR. (A
discussion must be opened, see
https://github.com/vercel/next.js/discussions/new?category=ideas)
- Related issues/discussions are linked using `fixes #number`
- e2e tests added
(https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs)
- Documentation added
- Telemetry added. In case of a feature if it's used or not.
- Errors have a helpful link attached, see
https://github.com/vercel/next.js/blob/canary/contributing.md


## For Maintainers

- Minimal description (aim for explaining to someone not on the team to
understand the PR)
- When linking to a Slack thread, you might want to share details of the
conclusion
- Link both the Linear (Fixes NEXT-xxx) and the GitHub issues
- Add review comments if necessary to explain to the reviewer the logic
behind a change

### What?

### Why?

### How?

Closes NEXT-
Fixes #

-->
2025-04-07 14:07:55 +02:00
Josh Story c7a338df5a Resolve Viewport separately from Metadata (#77427)
Viewport blocks the root while Metadata no longer does. However Metadata
requires the reading of dynamic params for things like icon loading and
other features that require the path whereas viewport does not. Reading
the path in fallback prerenders is considered dynamic when DIO is
enabled which means that any dynamic route with a file based metadata
such as an icon will trigger dynamic at the root.

To Address this we simply resolve viewport separately from metadata.
2025-04-01 09:46:39 -07:00
Jiachi Liu 75831c08e8 [metadata]: add pinterest meta tag (#76988)
### What
Adds support for Pinterest's Rich Pin Data meta tag, while
future-proofing for additional Pinterest tags.

This currently works like so

```js
pinterest: {
  richPin: true
}
  ```
 And would resolve to:
 
```html
 <meta property="pinterest-rich-pin" content="true" />
 ```

x-ref: https://help.pinterest.com/en/business/article/rich-pins

Closes #70873

---------

Co-authored-by: Dominik Koch <dominik@koch-bautechnik.de>
2025-03-11 18:30:23 +01:00
Artem Zelenov 0c6f63572d fix: remove initial-scale=1 from viewport when set to false (#76397)
Co-authored-by: Jiachi Liu <inbox@huozhi.im>
2025-02-26 14:39:44 +01:00
Zach Jaensch 15915c3469 Add pagination SEO link tags (#74737)
<!-- 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(s) that you're making:

## For Contributors

### Improving Documentation

- Run `pnpm prettier-fix` to fix formatting issues before opening the
PR.
- Read the Docs Contribution Guide to ensure your contribution follows
the docs guidelines:
https://nextjs.org/docs/community/contribution-guide

### Adding or Updating Examples

- The "examples guidelines" are followed from our contributing doc
https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md
- Make sure the linting passes by running `pnpm build && pnpm lint`. See
https://github.com/vercel/next.js/blob/canary/contributing/repository/linting.md

### Fixing a bug

- Related issues linked using `fixes #number`
- Tests added. See:
https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs
- Errors have a helpful link attached, see
https://github.com/vercel/next.js/blob/canary/contributing.md

### Adding a feature

- Implements an existing feature request or RFC. Make sure the feature
request has been accepted for implementation before opening a PR. (A
discussion must be opened, see
https://github.com/vercel/next.js/discussions/new?category=ideas)
- Related issues/discussions are linked using `fixes #number`
- e2e tests added
(https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs)
- Documentation added
- Telemetry added. In case of a feature if it's used or not.
- Errors have a helpful link attached, see
https://github.com/vercel/next.js/blob/canary/contributing.md


## For Maintainers

- Minimal description (aim for explaining to someone not on the team to
understand the PR)
- When linking to a Slack thread, you might want to share details of the
conclusion
- Link both the Linear (Fixes NEXT-xxx) and the GitHub issues
- Add review comments if necessary to explain to the reviewer the logic
behind a change

-->

Apologies in advance if I have missed something in the contributing
process.

Fixes #52925


### What?

Adds metadata config option for pagination link tags.

### Why?

The `<link rel="prev"` and `<link rel="next"` are used by search
crawlers and can help with SEO performance.
For more information:
https://developers.google.com/search/blog/2011/09/pagination-with-relnext-and-relprev

### How?

Uses existing patterns for metadata config.

Co-authored-by: Jiachi Liu <inbox@huozhi.im>
2025-01-14 15:47:46 +01:00
Zack Tanner 564794df56 fix: metadataBase should take precedence when resolving relative ogImages (#73066)
When resolving opengraph / twitter images, we currently ignore the configured `metadataBase` value, which goes against the [documentation](https://nextjs.org/docs/app/api-reference/functions/generate-metadata#default-value) and doesn't seem correct, since an explicit `metadataBase` should be preferred over a fallback. 

This updates the handling to ensure an explicit `metadataBase` takes priority over the implicit path discovery. 

The one remaining special case here is for the "static metadata" case, aka the `opengraph-image` convention. We'll continue to prefer the fallback `metadataBase` in preview Vercel deploys & locally. 

Fixes #66957 
Closes NDX-260
2024-11-26 17:36:37 -08:00
Niaz Morshed Nayeem 3ee0924f02 Replace depricated apple-mobile-web-app-capable with `mobile-web-ap… (#70363)
Co-authored-by: マルコメ <akio.muto@bnt.benextgroup.jp>
Co-authored-by: Jiachi Liu <inbox@huozhi.im>
2024-10-01 15:56:10 +02:00
Wyatt Johnson 55950d37e4 refactor: added more strict app segment config parsing (#70479)
This enhances the current parsing completed by Next.js of configuration
from app segments. Previously a collection of fragile checks was used to
parse the different segment configuration options which performed no
validation on the inputs.

This uses the `zod` library (which we already use internally) to perform
validation on the configuration exported. A followup PR #70480 will add
more verbose error logging around the validation errors.
2024-09-30 21:02:12 -07:00
Josh Story 05f159dffc [Breaking] Update Dynamic APIs to be async (#68812)
Next.js has a number of dynamic APIs that aren't available during
prerendering. What happens when you access these APIs might differ
depending on the mode you are using, for instance if you have PPR turned
on or the newly introduced `dynamicIO` experimental mode. But regardless
of the mode the underlying API represents accessing something that might
only be available at render time (dynamic rendering) rather than
prerender time (build and revalidate rendering)

Unfortunately our current dynamic APIs make certain kinds of modeling
tricky because they are all synchronous. For instance if we wanted to
add a feature to Next.js where we started a dynamic render before a
Request even hits the server it would be interesting to be able to start
working on everything that does not rely on any dynamic data and then
once a real Request arrives we can continue the render and provide the
associated Request context through our dynamic APIs.

If our dynamic APIs were all async we could build something like this
because they represnt a value that will eventually resolve to some
Request value. This PR updates most existing dynamic APIs to be async
rather than sync. This is a breaking change and will need to be paired
with codemods to realistically adopt. Additionally since this change is
so invasive I have implemented it in a way to maximize backward
compatibility by still allowing most synchronous access. The combination
of codemods, typescript updates, and backward compat functionality
should make it possible for projects to upgrade to the latest version
with minimal effort and then follow up with a complete conversion over
time.

#### `cookies()`
`cookies()` now returns `Promise<ReadonlyRequestCookies>`. Synchronous
access to the underlying RequestCookies object is still supported to
facilitate migration.
```tsx
// ------------ preferred usage

// async Server Component
const token = (await cookies()).get('token')

// sync Server Component
import { use } from 'react'
//...
const token = use(cookies()).get('token')

// ------------ temporarily allowed usage

// javascript, dev warning at runtime
const token = cookies().get('token')

// typescript, dev warning at runtime
import { type UnsafeUnwrappedCookies } from 'next/headers'
// ...
const token = (cookies() as unknown as UnsafeUnwrappedCookies).get('token')
```

#### `headers()`
`headers()` now returns `Promise<ReadonlyHeaders>`. Synchronous access
to the underlying Headers object is still supported to facilitate
migration.
```tsx
// ------------ preferred usage

// async Server Component
const header = (await headers()).get('x-foo')

// sync Server Component
import { use } from 'react'
//...
const header = use(headers()).get('x-foo')

// ------------ temporarily allowed usage

// javascript, dev warning at runtime
const header = headers().get('x-foo')

// typescript, dev warning at runtime
import { type UnsafeUnwrappedHeaders } from 'next/headers'
// ...
const header = (headers() as unknown as UnsafeUnwrappedHeaders).get('x-foo')
```


#### `draftMode()`
`draftMode()` now returns `Promise<DraftMode>`. Synchronous access to
the underlying DraftMode object is still supported to facilitate
migration.
```tsx
// ------------ preferred usage

// async Server Component
if ((await draftMode()).isEnabled) { ... }

// sync Server Component
import { use } from 'react'
//...
if (use(draftMode()).isEnabled) { ... }

// ------------ temporarily allowed usage

// javascript, dev warning at runtime
if (draftMode().isEnabled) { ... }

// typescript, dev warning at runtime
import { type UnsafeUnwrappedDraftMode} from 'next/headers'
// ...
if ((draftMode() as unknown as UnsafeUnwrappedDraftMode).isEnabled) { ... }
```

#### `searchParams`
`searchParams` is now a `Promise<{...}>`. Synchronous access to the
underlying search params is still supported to facilitate migration.
```tsx
// ------------ preferred usage

// async Page Component
export default async function Page({
  searchParams
}: {
  searchParams: Promise<{ foo: string }>
}) {
  const fooSearchParam = (await searchParams).foo
}

// sync Page Component
import { use } from 'react'
export default function Page({
  searchParams
}: {
  searchParams: Promise<{ foo: string }>
}) {
  const fooSearchParam = use(searchParams).foo
}

// ------------ temporarily allowed usage

// javascript, dev warning at runtime
export default async function Page({ searchParams}) {
  const fooSearchParam = searchParams.foo
}

// typescript, dev warning at runtime
import { type UnsafeUnwrappedSearchParams } from 'next/server'
export default async function Page({
  searchParams
}: {
  searchParams: Promise<{ foo: string }>
}) {
  const syncSearchParams = (searchParams as unknown as UnsafeUnwrappedSearchParams<typeof searchParams>)
  const fooSearchParam = syncSearchParams.foo
}
```



#### `params`
`params` is now a `Promise<{...}>`. Synchronous access to the underlying
params is still supported to facilitate migration. It should be noted
that while params are not usually dynamic there are certain modes where
they can be such as fallback prerenders for PPR.
```tsx
// ------------ preferred usage

// async Segment Component
export default async function Layout({
  params
}: {
  params: Promise<{ foo: string }>
}) {
  const fooParam = (await params).foo
}

// sync Segment Component
import { use } from 'react'
export default function Layout({
  params
}: {
  params: Promise<{ foo: string }>
}) {
  const fooParam = use(params).foo
}

// ------------ temporarily allowed usage

// javascript, dev warning at runtime
export default async function Layout({ params}) {
  const fooParam = params.foo
}

// typescript, dev warning at runtime
import { type UnsafeUnwrappedParams } from 'next/headers'
export default async function Layout({
  params
}: {
  params: Promise<{ foo: string }>
}) {
  const syncParams = (params as unknown as UnsafeUnwrappedParams<typeof params>)
  const fooSearchParam = syncParams.foo
}
```

### Typescript Changes
When using typescript with Next.js currently it is up to you to author
types for Pages, Layouts and other Segment components that recieve props
like `params` and `searchParams`.

Next comes with some build-time type checking to ensure you have not
improperly typed various top level module exports however the current
type assertions for `params` and `searchParams` is `any`. This isn't
very helpful because it allows you to erroneously type these props.

`searchParams` is tricky because while the default type is a dictionary
object parsed using node.js url parsing it is possible to customize when
running a custom Next.js server. However we can ensure that you
correctly type the prop as a Promise so with this change the validated
type for `searchParams` will be `Promise<any>`.

In the long run we will look at updating the `searchParams` underlying
type to be URLSearchParams so we can move away from supporting
customized parsing during rendering and we can get even more explicit
about valid types.

`params` is more straight forward because the framework controls the
actual `params` prop implementation and no customization is possible. In
the long run we want to enforce you are only typing params that are
valid for the Layout level your file is located in but for now we are
updating the allowed type to be `Promise<{[key: string]: string |
string[] | undefined }>`.

These new type restrictions may also require fixes before being able to
successfully build a project that updates to include these breaking
changes. These changes will also not always be codemodable because it is
valid to type the entire component using an opaque type like `Props`
which our codemods may not have an ability to introspect or modify.
2024-09-25 15:44:37 -07:00
Maikel de30598167 fix: correct metadata url suffix (#69959) 2024-09-11 14:02:51 +00:00
Jiachi Liu 9568a4f876 Fix favicon merging with customized icons (#67982)
### What

Support merging the static metadata file conventions `favicon.ico` with
other customized metadata icon from the module export.


### Why

`favicon.ico` should be displayed everywhere as it's the icon
representative of the website for all pages. Any customized `icon` in
metadata export `export const metadata` or `export function
generateMetadata()` shouldn't override the `favicon.ico` file
convention.


Fixes #55767

---------

Co-authored-by: hrmny <8845940+ForsakenHarmony@users.noreply.github.com>
2024-08-07 18:36:23 +02:00
Maikel 060d9a16b4 feat: facebook metadata (#65713)
Add support for the `fb:app_id` & `fb:admins` meta tag in the
generateMetaData function

---------

Co-authored-by: Sam Ko <sam@vercel.com>
Co-authored-by: Jiachi Liu <inbox@huozhi.im>
2024-07-15 12:10:07 +02:00
Jiachi Liu 54f54423d8 test: break down metadata test suite into smaller ones (#67018)
### What

app-dir `metadata.test.ts` is pretty big and includes a lot of erroring
tests and navigation tests. Breaking them into smaller suites to avoid
the erroring on effect on others.

- metadata
- metadata-navigation
- metadata-thrown

Moved the metadata testing utils into `next-test-utils` for sharing
purpose.
Moved the hmr test to the bottom to avoid flakyness.
2024-06-19 14:46:21 +02:00
Jiachi Liu f893c18528 Append sitemap extension and optimize imafe metadata static generation (#66477)
### What

Optimizing the static generation for dynamic metadata routes

If you're not using `generateSitemaps()` or `generateSitemaps()`, you
don't need to change any file conventions.
If you're using multi sitemap routes, make sure the returned `id`
properties from `generateSitemaps()` don't need to contain `.xml`, since
we'll always append one for you.

Analyzing the exports of metadata routes and determine if we need to
make them as dynamic routes.

### Why

Previously, users are struggling with the multi routes of sitemap or
images.
For sitemap, the `.xml` extension in url doesn't get appended
consistently to the multi sitemap route between dev and prod.
For image routes, the generated image routes are always dynamic routes
which cannot get static optimized.

The reason is that we need to always generate a catch-all route (such as
`/icon/[[...id]]` to handle both single route case (e.g. without
`generateImageMetadata`, representing url `/icon`) or multi route (e.g.
with `generateImageMetadata`, representing url `/icon/[id]`), only
catch-all routes can do it. This approach fail the static optimization
and make mapping url pretty difficult as parsing the file to check the
module exports has to be done before it.

#### Benifits

For image routes urls, this approach could help on static generation
such as single `/opengraph-image` route can be treated as static, and
then it can get static optimized if possible.

**Before**: `/opengraph-image/[[...id]]` cannot be optimized
**After**: single route `/opengraph-image` and multi-route
`/opengraph-image/[id]` are both possible to be statically optimized

For sitemap, since we removed appending `.xml` for dynamic routes, it’s
hard for users to have `/sitemap.xml` url with dynamic route convention
`sitemap.js` . But users desire smooth migration and flexibility.

**Before**: In v15 rc we removed the `.xml` appending that `sitemap.js`
will generate url `/sitemap` makes users hard to migrate, as users need
to re-submit the new sitemap url.
**After**: Now we'll consistently generate the `.xml`. Single route will
become `/sitemap.xml`, and multi route will become `/sitemap/[id].xml`.
It's still better than v15 as the urls generation is consistent, no
difference between dev and prod.

Here's the url generation comparsion

#### Before

All the routes are dynamic which cannot be optimized, we only had a
hacky optimization for prodution build multi-routes sitemap routes

| | only default export | `export generateImageMetadata()` | `export
generateSitemaps()` |
| -- | -- | -- | -- |
| opengraph-image.js | /opengraph-image/[[...id]] |
/opengraph-image[[...id]]/ | /opengraph-image/[[...id]] |
| sitemap.js | /sitemap/[[...id]] | /sitemap/[[...id]] | dev:
`/sitemap/[[...id]]` prod: `/sitemap/[id]` |

#### After

Most of the single route will are to get statically optimized now, and
the multi-routes sitemap are able to get SSG now

| | only default export | `export generateImageMetadata()` | `export
generateSitemaps()` |
| -- | -- | -- | -- |
| opengraph-image.js | /opengraph-image | /opengraph-image/[id] | - |
| sitemap.js | /sitemap.xml | - | /sitemap/[id].xml |

Next.js will have less overhead of mapping urls, we can easily multiply
the urls generation simply based on file conventions.

x-ref: feedback from #65507 
Closes #66232
2024-06-10 17:34:06 +02:00
Zack Tanner 750ae91e30 disable flaky metadata test in turbopack (#66553)
[x-ref](https://github.com/vercel/next.js/actions/runs/9373686572/job/25809596665)

[x-ref](https://github.com/vercel/next.js/actions/runs/9369698964/job/25797174293#step:28:3566)

[x-ref](https://github.com/vercel/next.js/actions/runs/9358710911/job/25762395753#step:28:4509)

[x-ref](https://github.com/vercel/next.js/actions/runs/9377123789/job/25818561715?pr=66551#step:28:554)

<!-- 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(s) that you're making:

## For Contributors

### Improving Documentation

- Run `pnpm prettier-fix` to fix formatting issues before opening the
PR.
- Read the Docs Contribution Guide to ensure your contribution follows
the docs guidelines:
https://nextjs.org/docs/community/contribution-guide

### Adding or Updating Examples

- The "examples guidelines" are followed from our contributing doc
https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md
- Make sure the linting passes by running `pnpm build && pnpm lint`. See
https://github.com/vercel/next.js/blob/canary/contributing/repository/linting.md

### Fixing a bug

- Related issues linked using `fixes #number`
- Tests added. See:
https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs
- Errors have a helpful link attached, see
https://github.com/vercel/next.js/blob/canary/contributing.md

### Adding a feature

- Implements an existing feature request or RFC. Make sure the feature
request has been accepted for implementation before opening a PR. (A
discussion must be opened, see
https://github.com/vercel/next.js/discussions/new?category=ideas)
- Related issues/discussions are linked using `fixes #number`
- e2e tests added
(https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs)
- Documentation added
- Telemetry added. In case of a feature if it's used or not.
- Errors have a helpful link attached, see
https://github.com/vercel/next.js/blob/canary/contributing.md


## For Maintainers

- Minimal description (aim for explaining to someone not on the team to
understand the PR)
- When linking to a Slack thread, you might want to share details of the
conclusion
- Link both the Linear (Fixes NEXT-xxx) and the GitHub issues
- Add review comments if necessary to explain to the reviewer the logic
behind a change

### What?

### Why?

### How?

Closes NEXT-
Fixes #

-->
2024-06-04 20:45:56 -07:00
조계진 e2d0082784 Refactor app dir metadata test (#66331)
### What?
Because `createMultiHtmlMatcher` does not use `await` keyword internally
and is not an async function, all `await` in front of the match function
returned from `createMultiHtmlMatcher` was removed in
`test/e2e/app-dir/metadata/metadata.test.ts`.

The JSDoc for `createMultiHtmlMatcher` was also modified.

Co-authored-by: Jiachi Liu <inbox@huozhi.im>
2024-05-29 22:18:15 +00:00
Jiachi Liu ecbf5373f6 Only apply metadata manifest credentials for preview deployment (#64940)
### What

Follow up for #62873
Only apply credentials in metadata manifest tag for preview deployment

### Why

When the CORS header is "\*" and if you're including credentials in
request it will block by browser. For manifest's case, if it's fetching
from a publich CDN with responsing the CORS header "\*" and mismatching
with the current website domain it will get blocked. Previously we
introduced that change mostly for vercel deployment auth protection, now
we're going to check if it's preview deployment and also the same
origin, if yes then we'll include credentails for manifest request

Closes NEXT-3208
2024-04-30 20:50:42 +00:00
Wyatt Johnson c6320ed87a Replace createNextDescribe with nextTestSetup (#64817)
<!-- 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(s) that you're making:

## For Contributors

### Improving Documentation

- Run `pnpm prettier-fix` to fix formatting issues before opening the
PR.
- Read the Docs Contribution Guide to ensure your contribution follows
the docs guidelines:
https://nextjs.org/docs/community/contribution-guide

### Adding or Updating Examples

- The "examples guidelines" are followed from our contributing doc
https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md
- Make sure the linting passes by running `pnpm build && pnpm lint`. See
https://github.com/vercel/next.js/blob/canary/contributing/repository/linting.md

### Fixing a bug

- Related issues linked using `fixes #number`
- Tests added. See:
https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs
- Errors have a helpful link attached, see
https://github.com/vercel/next.js/blob/canary/contributing.md

### Adding a feature

- Implements an existing feature request or RFC. Make sure the feature
request has been accepted for implementation before opening a PR. (A
discussion must be opened, see
https://github.com/vercel/next.js/discussions/new?category=ideas)
- Related issues/discussions are linked using `fixes #number`
- e2e tests added
(https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs)
- Documentation added
- Telemetry added. In case of a feature if it's used or not.
- Errors have a helpful link attached, see
https://github.com/vercel/next.js/blob/canary/contributing.md


## For Maintainers

- Minimal description (aim for explaining to someone not on the team to
understand the PR)
- When linking to a Slack thread, you might want to share details of the
conclusion
- Link both the Linear (Fixes NEXT-xxx) and the GitHub issues
- Add review comments if necessary to explain to the reviewer the logic
behind a change

### What?

### Why?

### How?

Closes NEXT-
Fixes #

-->

I took some time and [wrote a
codemod](https://gist.github.com/wyattjoh/0d4464427506cb02062a4729ca906b62)
that replaces the old usage of the `createNextDescribe` with the new
`nextTestSetup`. You'll likely have to turn on hiding of whitespace in
order to review, but this should primarily introduce no changes to the
test structure other than using the new mechanism now.

Closes NEXT-3178
2024-04-25 12:06:12 -06:00
Jiwon Choi 2bd27e72e5 fix(next): Metadata.openGraph values not resolving basic values when type is set (#63620)
### What?

The string value of `Metadata.openGraph.emails` throws error:

```tsx
export const metadata = {
  openGraph: {
    type: 'article',
    emails: 'author@vercel.com',
  },
};
```

Error:

```sh
r.map is not a function
```

The type is:

```tsx
type OpenGraphMetadata = {
  // ...
  emails?: string | Array<string>
}
```

### Why?

Basic values such as `emails` and `phoneNumbers` were not included when
`ogType` was set while resolving the values.

### How?

Include basic values when resolving the metadata.

Fixes #63415
2024-04-15 21:17:48 +02:00
Sebastian Silbermann ed4d772359 Stop using baseUrl in root tsconfig (#64117) 2024-04-09 00:25:43 +02:00
Jiachi Liu 488984cc03 fix: default relative canonical url should not contain search (#63843)
### What

Strip the search query for the `urlPathname` passed down to metadata
handling.

### Why
This is because the `urlPathname` from `staticGenerationStore` contains
query, so it will contain `?rsc` query for client navigation, which lead
to the relative path canonical url (e.g. `./`) will have the search
query along with it. This PR is to remove that and make sure always uses
pathname.

Reported by @pacocoursey 

Closes NEXT-2963
2024-03-28 23:16:22 +00:00
JJ Kasper aa7ae420c6 Fix generateMetadata race condition (#63169)
This ensures we properly catch/handle `generateMetadata` errors during
eager evaluating of nested `generateMetadata` functions in the tree.
Previously if we eager evaluated a child metadata function that threw an
error e.g. `notFound()` and but the parent metadata function took longer
the thrown error would be an unhandled rejection causing the process to
crash depending on the environment.

Fixes: NEXT-2588


Closes NEXT-2786
2024-03-12 17:23:02 +00:00
Jiachi Liu ced7339aa6 Fix: missing crossorigin property on manifest link (#62873)
We didn't set the property of manifest before, this PR fixes the missing
prop

> If the manifest requires credentials to fetch, the crossorigin
attribute must be set to use-credentials, even if the manifest file is
in the same origin as the current page.
x-ref: https://developer.mozilla.org/en-US/docs/Web/Manifest


Fixes NEXT-2706
2024-03-06 02:04:28 +01:00
Jiachi Liu dc71a5721b Fix trailing slash for canonical url (#62109)
### What

We should respect the `trailingSlash` config for metadata canonical url,
this PR is adding the handling for strip or keep the trailing slash for
canonical url. Passing down trailingSlash config to metadata resolving
to decide how we handle it.

### Why

The tricky one was `/` pathname, when visiting the origin directly, that
it will always have at least `/` in the URL instance. But for the
default `origin`, it shouldn't show the `/` if the `trailingSlash`
config is `false`. Also it should show trailing slash for all pathnames
if that config is enabled.

BTW there's a `__NEXT_TRAILING_SLASH` env but since we're using the
fixed nextjs runtime module, so this can't be dynamically replaced in
the metadata resolving modules. So we didn't use it

Fixes #54070 
Closes NEXT-2424
2024-02-15 18:57:15 +01:00
Jiachi Liu 778fb87131 Support generating multi-meta tahs for metadata api other prop (#59106) 2023-11-30 16:44:49 +01:00
Jiachi Liu a301eb6a9f Viewport exports (#57302)
## 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.
2023-10-25 05:20:23 +00:00
OJ Kwon 3c3744631e fix(loader_tree): propagate metadata to corresponding layout (#56956)
### What?

- fixes test https://github.com/vercel/next.js/blob/17553c5e25c824ce04045066c24a8f138881473d/test/e2e/app-dir/metadata/metadata.test.ts#L487

The way next.js collects static metadata is read static metadata, and then read layout metadata to merge multiple metadatas into a single layout path (https://github.com/vercel/next.js/blob/17553c5e25c824ce04045066c24a8f138881473d/packages/next/src/lib/metadata/resolve-metadata.ts#L347-L352)

When turbopack creates LoaderTree for the corresponding directory tree, it extracts `page` but skips metadata  in result there are orphan components that have a metadata doesn't have layout metadata, as well as a component have a layout doesn't have metadata. Latter is being rendered as a page (since it have correct layout), which eventually falls back to the default metadata instead.

PR trickles down the metadata when extracting page (creating a new component with `page`) to consolidates those.

Also PR expands Metadata to have base_page property to capture where it has been originally exists, as we clone down metadata then do `fillMetadataSegment` against the current page where LoaderTree is being created it creates a wrong relative path. For example, currently

```
/icon.svg
 - opengragph/
      - static -> path being `/opengraph/.../icon.svg` instead of `/icon.svg`
```

When recursively traverse directory tree, capture each components with corresponding base_page to calculate instead.

Unfortunately this doesn't make pass all of the metadata tests; there are lot to dig more. Would like to scope PR in a reasonable size.


Closes WEB-1795
2023-10-21 21:24:40 +00:00
Tim Neutkens c6fe20a31f Remove specific hash checks for metadata.test.ts (#56843)
This ensures the tests pass in both webpack and Turbopack.

<!-- 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(s) that you're making:

## For Contributors

### Improving Documentation

- Run `pnpm prettier-fix` to fix formatting issues before opening the
PR.
- Read the Docs Contribution Guide to ensure your contribution follows
the docs guidelines:
https://nextjs.org/docs/community/contribution-guide

### Adding or Updating Examples

- The "examples guidelines" are followed from our contributing doc
https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md
- Make sure the linting passes by running `pnpm build && pnpm lint`. See
https://github.com/vercel/next.js/blob/canary/contributing/repository/linting.md

### Fixing a bug

- Related issues linked using `fixes #number`
- Tests added. See:
https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs
- Errors have a helpful link attached, see
https://github.com/vercel/next.js/blob/canary/contributing.md

### Adding a feature

- Implements an existing feature request or RFC. Make sure the feature
request has been accepted for implementation before opening a PR. (A
discussion must be opened, see
https://github.com/vercel/next.js/discussions/new?category=ideas)
- Related issues/discussions are linked using `fixes #number`
- e2e tests added
(https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs)
- Documentation added
- Telemetry added. In case of a feature if it's used or not.
- Errors have a helpful link attached, see
https://github.com/vercel/next.js/blob/canary/contributing.md


## For Maintainers

- Minimal description (aim for explaining to someone not on the team to
understand the PR)
- When linking to a Slack thread, you might want to share details of the
conclusion
- Link both the Linear (Fixes NEXT-xxx) and the GitHub issues
- Add review comments if necessary to explain to the reviewer the logic
behind a change

### What?

### Why?

### How?

Closes NEXT-
Fixes #

-->
2023-10-14 19:54:55 +02:00
Max Leiter 4c3b7f9b7a Export RedirectType from next/navigation (#54729)
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

---------
2023-08-29 11:05:44 -07:00
Jiachi Liu 50ff54ee29 Use summary_large_image as twitter card if images present by default (#53919)
This is an improvement for twitter card, if there's image present we could use `summary_large_image` to make the twitter card look better instead of using `summary` by default, so that users could benefit from the large image card display on twitter
2023-08-11 17:52:45 +00:00
Jiachi Liu ab14895ada Fix dynamic route not-found boundary matching (#53564)
### What & Why

The dynamic not-found boundary didn't work as expected as it was using the `pathname` to match how many levels of the segements should be matched. For dynamic routes this doesn't work, unlike normal page, the unmatched segment can also hit the not found boundary in the same level.

### How

Use `segment` of loader tree nodes to determine if not-found boundary searching is reached to the end instead of using `pathname`. 
> NOTE: For production `/_not-found` case since it's a valid page on production and still has the original tree, so we handle that as a special case to use the not found loader tree (with empty child routes) to render.

Fixes #53344
2023-08-04 16:07:58 +00:00
Jiachi Liu cc4879d1dc Move metadata error under error boundaries (#53551)
### What & Why

Using `notFound()` in `generateMetadata()` or in page will lead to unacught global not found error when you do navigation, this is because `head` cache is actually not inside the error boundary as designed to stay in the beginning of the content. But in this way we won't be able to catch the notFound error thrown from metadata API. So we created a new approach that can separate the error itself from metadata result, and throw as error under the error boundaries, and metadata itself will always be safe to render.

### How

We use a new promise that resolve the `error` thrown from metadata resolving, and let the render result always return successfully and always has a value, using default metadata when there's error thrown. Create two components, one rendering the metadata tags, and another `MetadataOutlet` to throw the error when the resolving is failed but rendered under error boundaries.



```jsx
const [MetadataTree, MetadataOutlet] = createMetadataComponents(/*...*/)
const ComponentTree = createComponentTree({ metadataOutlet: <MetadataOutlet /> })

renderRSC(
  <AppRourer head={<MetadataTree />}>
    <ComponentTree />
  </AppRourer>
)
```

`metadataOutlet` will stay next to page component in the layout hierarchy

discuessed with @gnoff 

Minor changes: 

* When there's rendering root layout layer, not found boundary should be `DefaultNotFound` if the custom one doesn't exisit


Fixes #53371
Fixes #53149
2023-08-04 15:32:36 +00:00
Jiachi Liu de873d02b3 Prefer svg icon instead favicon if possible (#53343)
### What?

Change the `favicon.ico` metadata `sizes` property from always `"any"`
to using the actual size possible

### Why?

When chrome/firefox browsers search for icon it needs the proper
metadata to determine which one to use, giving `favicon.ico` sizes with
`"any"` will prevent it loading the `icon.svg` as default icon when
available.

Changing to set proper size of `favicon.ico` (as the `favicon.ico` sizes
could be 16x16, 32x32, etc.) fixes the issue.

It works (loading svg icon) for chrome and firefox:

Firefox
<img width="505" alt="image"
src="https://github.com/vercel/next.js/assets/4800338/6873e595-479d-4d9e-ae5c-39e5f938fcf5">

Chrome
<img width="460" alt="image"
src="https://github.com/vercel/next.js/assets/4800338/03bbe4c7-ef76-4f34-a611-337b0d4b97a3">

It loads favicon.ico for Safari:
Using the `test/e2e/app-dir/metadata` app it shows the favicon.ico for
Safari
<img width="1000" alt="image"
src="https://github.com/vercel/next.js/assets/4800338/92cc8714-ea5e-432d-8144-2a4a42ee4ce2">

Can't have it as an e2e test as I tested it always loads the
`favicon.ico` in headless mode which can't determine the behaviors

Fixes #52002

Co-authored-by: JJ Kasper <jj@jjsweb.site>
2023-07-31 07:32:39 -07:00
Jiachi Liu 1fefb4a8d2 Reland "Refine the not-found rendering process for app router" (#52985)
Reland #52790
Reverts vercel/next.js#52977

was failed due to failed job
[vercel/next.js/actions/runs/5616458194/job/15220295829](https://github.com/vercel/next.js/actions/runs/5616458194/job/15220295829)

Should be fine to resolve with
https://github.com/vercel/next.js/pull/52979 now

Fixes #52718
Fixes #52739

---------

Co-authored-by: Alex Kirszenberg <alex.kirszenberg@vercel.com>
Co-authored-by: Tobias Koppers <tobias.koppers@googlemail.com>
2023-07-21 10:09:30 -07:00
JJ Kasper d7335b75d1 Revert "Refine the not-found rendering process for app router" (#52977)
Reverts vercel/next.js#52790

Reverting temporarily as this breaks turbopack's not found handling due
to the app tree being generated there not having the necessary parallel
routes in the `_not-found` entry x-ref:
https://github.com/vercel/next.js/blob/0df8aac935741808ee6aee78a8b545b2c1405f29/packages/next-swc/crates/next-core/src/app_structure.rs#L677-L681

x-ref:
https://github.com/vercel/next.js/actions/runs/5616458194/job/15220295829
2023-07-20 20:39:05 -07:00
Jiachi Liu cb24c555a6 Refine the not-found rendering process for app router (#52790)
### What

This PR changes the flow of not-found rendering process. 

### Why

`not-found.js` was rendered in two ways before:
* 1 is SSR rendering the not-found as 404
* 2 is triggering the error on RSC rendering then the error will be
preserved in inline flight data, on the client it will recover the error
and trigger the proper error boundary.

The solution has been through a jounery:
No top-level not found boundary -> introduce metadata API -> then we
create a top level root not found boundary -> then we delete it due to
duplicated rendering of root layout -> now this

So the solution before this PR is still having a root not found boundary
wrapped in the `AppRouter`, it's being used in a lot of places including
HMR. As we discovered it's doing duplicated rendering of root layout,
then we removed it and it started failing with rendering `not-found` but
missing root layout. In this PR we redesign the process.

### How

Now the rendering architecture looks like:

* For normal root not-found and certain level of not-found boundary
they're still covered by `LayoutRouter`
* For other error renderings including not-found
* Fully remove the top level not-found boundary, when it renders with
404 error it goes to render the fallback page
* During rendering the fallback page it will check if it should just
renders a 404 error page or render nothing and let the error from inline
flight data to trigger the error boundary

pseudo code
```
try {
  render AppRouter > PageComponent
} catch (err) {
  create ErrorComponent by determine err
  render AppRouter > ErrorComponent
}
```

In this way if the error is thrown from top-level like the page itself
or even from metadata, we can still catch them and render the proper
error page based on the error type.

The problematic is the HMR: introduces a new development mode meta tag
`<meta name="next-error">` to indicate it's 404 so that we don't do
refresh. This reverts the change brougt in #51637 as it will also has
the duplicated rendering problem for root layout if it's included in the
top level not found boundary.

Also fixes the root layout missing issue:

Fixes #52718
Fixes #52739

---------

Co-authored-by: Shu Ding <g@shud.in>
2023-07-20 14:12:06 -07:00
Jiachi Liu a28ae633e4 Support metadata exports for server components not-found (#52678)
### What?

Support metadata exports for `not-found.js` conventions

### Why?

We want to define metadata such as title or description basic properties for error pages, including 404 and 500 which referrs to `error.js` and `not-found.js` convention. See more requests in #45620 

Did some research around metadata support for not-found and error convention. It's possible to support in `not-found.js` when it's server components as currently metadata is only available but for `error.js` it has to be client components for now so it's hard to support it for now as it's a boundary.

### How?

We determine the convention if we're going to render is page or `not-found` boundary then we traverse the loader tree based on the convention type. One special case is for redirection the temporary metadata is not generated yet, we leave it as default now.

Fixes #52636
2023-07-14 22:33:47 +00:00
Jiachi Liu d10f105b74 Fix icons metadata missing from layout (#52673)
### What

This was an issue introduced in #52416 when we check the images and icons property while merging with static file conventions. Where we should check if the properties are present but we only checked if they value is falsy. So when you're using `icons` with array value it breaks.

Now we properly check all the possible case of `metadata.icons` value, so then decide if we are using the static file convention or the icons property of defined metadata.

Also add few more tests cases to cover icons resolving.
2023-07-14 12:04:31 +00:00
Jiachi Liu 76eec86a6b Set sizes prop to any for svg icons (#52609)
For `link` tag's `sizes` property, the property is defined as:

> This attribute defines the sizes of the icons for visual media contained in the resource. It must be present only if the [rel](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/link#rel) contains a value of icon or a non-standard type such as Apple's apple-touch-icon. It may have the following values:
`any`, meaning that the icon can be scaled to any size as it is in a vector format, like image/svg+xml.

x-ref: https://html.spec.whatwg.org/#attr-link-sizes
x-ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/link (`sizes` property definition section) 

Closes #52002
Closes NEXT-133
2023-07-13 00:33:27 +00:00