followup to: https://github.com/vercel/next.js/pull/60645
### Background
When prerendering the determination of whether a prerender is fully
static or partially static should not be directly related to whether
there is a postponed state or not. When rendering RSC it is possible to
postpone because a dynamic API was used but then on the client (SSR) the
postpone is never encountered. This can happen when a server component
is passed to a client component and the client component conditionally
renders the server component.
Today if this happens the entire output would be considered static when
in fact the flight data encoded into the page and used for bootstrapping
the client router contains dynamic holes. Today this is blocked by an
error that incorrectly assumes that this case means the user caught the
postpone in the client layer but as shown above this may not be the
case.
### Implementation
A more capable model is to think of the outcome of a prerender as having
3 possible states
1. Dynamic HTML: The HTML produces by the prerender has dynamic holes.
we save the static prelude but expect to resume the render later to
complete the HTML. This means we will resume the RSC part of the render
as well
2. Dynamic Data: The HTML is completely static but the RSC data encoded
into the page is dynamic. We don't want to resume the render but we do
need to produce new inlined RSC data during a Request.
3. Static: The HTML is completely static and so is the RSC data encoded
into the page. We save the entire HTML output and there will be no
dynamic continuation when this route is visited.
Really 1 & 3 are the same as today (Partially static & Fully Static
respectively) but case 2 which today errors in a confusing way is now
supported.
In addition implementing the Dynamic Data case the old warning about
catching postpones is removed. The reason we don't want this is that
catching postpones is potentially a valid way to do optimistic UI. We
probably want a first-party API for it at some point (and maybe we'll
add the warning back in once we do) but imagine you do something dynamic
like look up a user but during prerender you want to render as if the
user is logged out. you could call `getUser()` in a try catch and render
fallback UI if it throws. In this case we'd detect a dynamic API was
used but we wouldn't have a corresponding postpone state which would put
us in the Dynamic Data case (2).
Another item to note is that we can produce a fully static result even
if there is a postponed state because users may call postpone themselves
even if they are not calling dynamic APIs like headers or cookies. When
this happens we don't want to statically capture a page with postponed
boundaries in it. Instead we immediately resume the render and abort it
with a postponed abort signal. This will cause the boundaries to
immediately enter client render mode which should speed up recovery on
the client.
#### Technical Note
Another note about the implementation is that you'll see that regardless
of which case we are in, if there is a postponed state but we consider
the page to be Dynamic Data meaning we want to serialize all the HTML
and NOT do a resume in the dynamic continuation then we immediately
resume the render with and already aborted AbortSignal. The purpose here
is to mark any boundaries which have dynamic holes as being
client-rendered.
As a general rule if the render produces a postponed state we must do
one of the following
1. save the postponed state and ensure there is a dynamic continuation
that calls resume
2. immediately resume the render and save the concatenated output and
ensure the dynamic continuation does NOT call resume.
or said another way, every postponed state must be resumed (even if it
didn't come from Next's dynamic APIs)
#### Perf considerations
This PR modifies a few key areas to improve perf.
Reduces quantity of *Stream instances where possible as these add
significant overhead
Reduces extra closures to lower allocations and keep functions in
monomorphic form where possible
Closes NEXT-2164
Requires vercel/turbo#6388
This uses the structure implemented in vercel/turbo#6388 to support formatted text when reporting. Right now only the `Line` and basic `String` cases are handled.
Remove the Server CSS manifest and related logic, and use the chunkGroup
CSS files instead for each entry to inject stylesheet links.
Why was that manifest needed in the first place? When implementing CSS
collection for RSC and nested layout initially, we collect CSS imports
at each layer and create corresponding client entries. But then soon got
hit by the problem of duplication and improper tree-shaking. Two layers
can have the same CSS imported so we solved it in a way that "if an
upper layer imports this module, skip it in child layers". Note that
this is deduped by module, so we need to keep the information of "layer
(entry) → CSS modules" somewhere, in a manifest.
Another reason is that we create the client entry before Webpack
optimizes modules, so we can inject the client entry into the same
compilation. But that means the collected client modules from the server
layer are not properly optimized (DCE). **This is a general issue at the
moment that's not specifically related to CSS, although using that
manifest to collect DCE'd info and join the original collected CSS files
with that info temporarily solved it.** That's why I disabled some tests
related to font CSS collection and want to improve it in a more general
way.
Why is that not needed anymore? Main reason is to keep a good balance
between duplication and number of chunks, and delegate the decision to
Webpack's splitChunks plugin. It is not possible to get to a point of 0
duplication unless we ship every CSS module as a single chunk. And since
in #50406 we made the duplication better but at the chunk asset level,
instead of the original module level.
Prior work: #50406, #50610.
## What?
Removes `experimental.appDir` this was leftover from when I flipped the
switch.
Kept the config file as in the future we might add future flags and
such. It also helps that it has the types comment included so you always
get types.
<!-- 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 or adding/fixing 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 #
-->
---------
Co-authored-by: JJ Kasper <jj@jjsweb.site>
This PR updates the way we preload fonts. Previously we tracked which
fonts we needed to preload for each layer and rendered a `<link
rel="preload" href="..." as="font" />` tag for each preloadable font.
This unfortunately gets blocked by data fetching and we want to be able
to hint these preloads as soon as possible. Now that React support Float
methods in RSC we can use `ReactDOM.preload(..., { as: "font" })` to
implement this functionality
This PR makes the following changes
1. expose a `preloadFont` method through the RSC graph
2. expose a `preconnect` metho through the RSC graph
3. refactor the preloads generation to use `preloadFont` instead of
rendering a preload link
4. If there are no fonts to preload but fonts are being used in CSS then
a `preconnect` asset origin is called instead of rendering a preconnect
link
5. instead of emitting a data attribute per font preload indicating
whether the project is using size-adjust we now emit a single global
meta tag. In the future we may get more granular about which fonts are
being size adjusted. In the meantime the current hueristic is to add
`-s` to the filename so it can still be inferred.
In the process of completing this work I discovered there were some bugs
in how the preconnect logic was originally implemented. Previously it
was possible to get multiple preconnects per render. Additionally the
preconnect href was always `"/"` which is not correct if you are hosting
your fonts at a CDN. The refactor fixed both of these issues
I want to do a larger refactor of the asset loading logic in App-Render
but I'll save that for a couple weeks from now
Additionally, the serialized output of preloads now omits the word
anonymous when using crossorigin so tests were updated to reflect
`crossorigin=""`
Additionally, tests were updated to no longer look for the size-adjust
data attribute on preloads
Additionally, There is a note about leaving a `{null}` render in place
to avoid a conflict with how the router models lazy trees. I'll follow
up with a PR addressing this
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
Enables using `next/font` by adding `@next/font` as a dependency and
reexporting its loaders.
Always generates the `font-loader-manifest` as we can't know beforehand
if the user intends to use `next/font` or not.
Also adds telemetry for `next/font` usage.
The tests are updated to use `next/font`. But `@next/font` is tested in
`test/e2e/next-font/index.test.ts` and `test/e2e/app-dir/next-font` as
well to ensure it doesn't break.
Fixes NEXT-351
## Bug
- [ ] Related issues linked using `fixes #number`
- [ ] 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`
- [ ]
[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)
Adds `data-next-font` data attribute to the preload tag if added by
`@next/font`.
```js
// Using `size-adjust` fallback font.
<link data-next-font="size-adjust" rel="preload" href="..." as="font" type="font/woff2" crossorigin="anonymous">
// Not using `size-adjust` fallback font.
<link data-next-font="" rel="preload" href="..." as="font" type="font/woff2" crossorigin="anonymous">
```
If no fonts are preloaded, the tag is added on the preconnect tag.
Fixes NEXT-350
## Bug
- [ ] Related issues linked using `fixes #number`
- [ ] 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`
- [ ]
[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)
Fixes typo and makes sure both loaders always have a default value.
## Bug
- [ ] Related issues linked using `fixes #number`
- [ ] Integration tests added
- [ ] Errors have a helpful link attached, see `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`
- [ ] Integration 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`
## 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)
Adds default config if @next/font is a dependency. Warns instead of
errors when subsets is missing.
[slack
ref](https://vercel.slack.com/archives/C03KED0D4N7/p1666226599615489?thread_ts=1666225686.389179&cid=C03KED0D4N7)
## Bug
- [ ] Related issues linked using `fixes #number`
- [ ] Integration tests added
- [ ] Errors have a helpful link attached, see `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`
- [ ] Integration 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`
## Documentation / Examples
- [ ] Make sure the linting passes by running `pnpm lint`
- [ ] The "examples guidelines" are followed from [our contributing
doc](https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md)
Co-authored-by: JJ Kasper <jj@jjsweb.site>
This PR updates app configurations from `export const config = { ... }`
to be directly exported.
## Bug
- [ ] Related issues linked using `fixes #number`
- [ ] Integration tests added
- [ ] Errors have a helpful link attached, see `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`
- [ ] Integration 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`
## Documentation / Examples
- [ ] Make sure the linting passes by running `pnpm lint`
- [ ] The "examples guidelines" are followed from [our contributing
doc](https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md)
Co-authored-by: JJ Kasper <jj@jjsweb.site>
Remove `browsersListForSwc` since it is enabled by default now, and disable `legacyBrowsers` by default.
This PR also bumps the default browserslist to the following:
- Chrome 64+
- Edge 79+
- Firefox 67+
- Opera 51+
- Safari 12+
See related RFC:
- Closes#33227
Co-authored-by: JJ Kasper <22380829+ijjk@users.noreply.github.com>
Fixes tree shaking for font loaders in server components.
## Bug
- [ ] Related issues linked using `fixes #number`
- [ ] Integration tests added
- [ ] Errors have a helpful link attached, see `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`
- [ ] Integration 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`
## Documentation / Examples
- [ ] Make sure the linting passes by running `pnpm lint`
- [ ] The "examples guidelines" are followed from [our contributing doc](https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md)
Reduces the amount of options for local fonts. Adds additional regression tests.
## Bug
- [ ] Related issues linked using `fixes #number`
- [ ] Integration tests added
- [ ] Errors have a helpful link attached, see `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`
- [ ] Integration 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`
## Documentation / Examples
- [ ] Make sure the linting passes by running `pnpm lint`
- [ ] The "examples guidelines" are followed from [our contributing doc](https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md)
Check that the module has assets. This might not always be the case in
app dev if there was an error. Test added to make sure it recovers
correctly.
## Bug
- [ ] Related issues linked using `fixes #number`
- [ ] Integration tests added
- [ ] Errors have a helpful link attached, see `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`
- [ ] Integration 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`
## Documentation / Examples
- [ ] Make sure the linting passes by running `pnpm lint`
- [ ] The "examples guidelines" are followed from [our contributing
doc](https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md)
Co-authored-by: JJ Kasper <jj@jjsweb.site>
Changes how font loaders are configured in next config, makes more sense since options can be optional. Also adds error for when font loaders are used from within node_modules.
## Bug
- [ ] Related issues linked using `fixes #number`
- [ ] Integration tests added
- [ ] Errors have a helpful link attached, see `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`
- [ ] Integration 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`
## Documentation / Examples
- [ ] Make sure the linting passes by running `pnpm lint`
- [ ] The "examples guidelines" are followed from [our contributing doc](https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md)
Finds the font files connected to font loader modules and adds them to
the font loader manifest. They're then collected and rendered similarly
to CSS links in app-render.
Adds support for generating a fallback font by providing font override
metrics for the given local font. Also adds support for providing a CSS
variable name that then can be accessed through the `.variable` export,
it contains the hashed font family name.
## Bug
- [ ] Related issues linked using `fixes #number`
- [ ] Integration tests added
- [ ] Errors have a helpful link attached, see `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`
- [ ] Integration 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`
## Documentation / Examples
- [ ] Make sure the linting passes by running `pnpm lint`
- [ ] The "examples guidelines" are followed from [our contributing
doc](https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md)
Co-authored-by: JJ Kasper <jj@jjsweb.site>
Makes sure font loader CSS ends up correctly in the Flight Manifest and Flight Client Entries.
## Bug
- [ ] Related issues linked using `fixes #number`
- [ ] Integration tests added
- [ ] Errors have a helpful link attached, see `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`
- [ ] Integration 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`
## Documentation / Examples
- [ ] Make sure the linting passes by running `pnpm lint`
- [ ] The "examples guidelines" are followed from [our contributing doc](https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md)