### What?
Clarify the "Forms and Mutations" docs.
### Why?
This may be opinionated, but I believe this section of the docs starts out assuming that the user knows how the `<form>` HTML works. Coming from the client side React world, most developers are used to using state in forms. Clarifying that this data is accessible via the standard web API [FormData](https://developer.mozilla.org/en-US/docs/Web/API/FormData/FormData) is essential for both transitioning developers and new developers.
by @jridgewell:
### What?
This integrates Turbopack's HRM protocol within the existing HMR
WebSocket, and implements the server-side of the Next's and Turbopack's
protocols for use in next-api.
### Why?
HMR makes the development experience.
### How?
The (new) Turbopack HMR protocol allows reusing the existing
`sendMessage` and `addMessageListener` API's already used by our HMR
singleton in Pages. (App apparently doesn't have a per-chunk HMR, only
per-page, so it's HMR signals are describe below.)
For the next-api server-side, I implemented the following events:
- `reloadPage`, for Pages when `_document` changes
- `middlewareChanges` when middleware is added/deleted, or modified
- `serverOnlyChanges` for Pages when a loaded page's server graph
changes
- `serverComponentChanges` for App when a loaded app page's server graph
changes
We reuse the already implemented `addedPage`, `removedPage`, and
`devPagesManifestUpdate` (done via webpack, so we should eventually port
that over to the Turbopack listeners).
I don't know exactly where `built`, `building`, and `sync` should be
integrated, so they're just not sent currently. Additionally, the
client-sent events aren't implemented in the new HMR server.
Depends on https://github.com/vercel/turbo/pull/5814
Closes WEB-1453
---------
Co-authored-by: Justin Ridgewell <justin@ridgewell.name>
Noticed this condition was repeated quite often, this pulls it out to the top and reuses the variable.
Also made a small change to `getDefineEnv` to sort the argument similarly between all calls and change optional properties to be required with `undefined` in order to make the list explicit. Looking at the code it seems that `getDefineEnv` in `setup-dev.ts` is missing some information and that will break when `.env` / tsconfig changes 🤔
### What
When you only have `pages/` folder and custom `_app.js`, editing the
`_app.js` file when unexpectedly lead to full page reload. This is
because the `pages/_app` chunk is included into `pages/_document` chunk
as they all pass through the `next-route-loader` which forms the router
module and other userland modules including `/_app` and `/_document`.
That leads to a change: whenever you modify `_app.js`, chunk hash of
`/_document` will always be updated as it's built as a new chunk.
Found this difference by looking at the document chunk with nextjs in
early 13.4.x releases.
### How
We'll check at the entries creation point to filter out `/_app` and
`/_document` so that we won't have them both bundled for `_document`
chunk. Then when we won't trigger the hmr path to reload the page since
_document chunk hash is updated.
Closes NEXT-1568
Fixes#53614
This bundles a collection of Typescript updates that correct typings
across the servers:
- Manifest typings have been narrowed
- Some methods have been moved to abstract methods on classes
- Added some type guard functions for route matches
- Utilized early returns in logic to reduce nesting
- Added mutability modifiers to some properties to prevent accidental
mutations
- Removed some useless assigns from unused catch error params:
```ts
try {
await something
} catch (_) {}
// Is the same as
try {
await something
} catch {}
```
This does not introduce any new functionality, simply some QOL
improvements.
I've introduced a bug with memory watching in development in this PR: #53523.
Specifically when calling `cleanup` the process would exit because the `exit` listener on the childprocess would be called which then calls `process.exit(0)`. This caused a condition where calling `worker.end()` would immediately quit the process.
This PR ensures the cleanup listeners for childprocess are disabled (`.off(`) so that when we call `worker.end()` the process is terminated without the main process being terminated.
## Initial Pass
The initial pass applies to all user code. If an import (`foo`) matches one of the packages from our list, say:
```js
// user code
import { a } from 'foo'
import { otherThings } from './code'
```
The initial pass transforms it into:
```js
// user code
import { a } from '__barrel_optimize__?names=a!=!foo'
import { otherThings } from './code'
```
## Barrel Optimizations
This `__barrel_optimize__` loader is used to optimize the imports of "barrel" files that have many
re-exports. Currently, both Node.js and Webpack have to enter all of these
submodules even if we only need a few of them.
For example, say a file `foo.js` with the following contents:
```js
export { a } from './a'
export { b } from './b'
export { c } from './c'
...
```
If the user imports `a` only, this loader will accept the `names` option to
be `['a']`. Then, it request the `__barrel_transform__` SWC loader to load
`foo.js` (via `this.loadModule` Webpack API) and receive the following info:
```js
export const __next_private_export_map__ = '[["./a","a","a"],["./b","b","b"],["./c","c","c"],...]'
```
The export map, generated by SWC, is a JSON that represents the exports of
that module, their original file, and their original name (since you can do
`export { a as b }`).
Then, this loader can safely remove all the exports that are not needed and
re-export the ones from `names`:
```js
export { a } from './a'
```
That's the basic situation and also the happy path.
## Wildcard Exports
For wildcard exports (e.g. `export * from './a'`), it becomes a bit more complicated.
Say `foo.js` with the following contents:
```js
export * from './a'
export * from './b'
export * from './c'
...
```
If the user imports `bar` from it, SWC can never know which files are going to be
exporting `bar`. So, we have to keep all the wildcard exports and do the same
process recursively. This loader will return the following output:
```js
export * from '__barrel_optimize__?names=bar&wildcard!=!./a'
export * from '__barrel_optimize__?names=bar&wildcard!=!./b'
export * from '__barrel_optimize__?names=bar&wildcard!=!./c'
...
```
The "!=!" tells Webpack to use the same loader to process './a', './b', and './c'.
After the recursive process, the "inner loaders" will either return an empty string
or:
```js
export * from './target'
```
Where `target` is the file that exports `bar`.
## Non-Barrel Files
If the file is not a barrel, we can't apply any optimizations. That's because
we can't easily remove things from the file. For example, say `foo.js` with:
```js
const v = 1
export function b () {
return v
}
```
If the user imports `b` only, we can't remove the `const v = 1` even though
the file is side-effect free. In these caes, this loader will simply re-export
`foo.js`:
```js
export * from './foo'
```
Besides these cases, this loader also carefully handles the module cache so
SWC won't analyze the same file twice, and no instance of the same file will
be accidentally created as different instances.
---
- [x] Disable this loader for Jest
- [x] Add tests for SWC loader caching
- [x] Add tests for external modules
- [x] Add tests for pages
- [x] Add tests for recursive `export *`s
---
Closes#54038, closes#54286.
* Share util `isGroupSegment`
* Refactor `normalizePathname` to`normalizeSegments` in `src/client/components/router-reducer/compute-changed-path.ts` to avoid extra call of path join and split
Fix#45301
If you deploy Next.js with in front Cloudflare, empty prefetch responses will be cached because there is no `cache-control` header and the extension is .json, Cloudflare considers these requests cacheable assets
If you want a test for this I would like to know if there is an existing one where I can add the header check
### What?
This adds to the docs a guide for migrating a Vite application to
Next.js. It also contains a section that lists the reasons why one would
want to switch from Vite to Next.js.
### Why?
This guide is helpful for developers that want to switch to Next.js but
don't know how difficult that would be and how to do it. The "Why?" list
is also helpful to developers who haven't yet been convinced to switch
or need help formulating the reasons to switch to decision-makers.
This guide was [first published on the Inngest
blog](https://www.inngest.com/blog/migrating-from-vite-to-nextjs). To
our own surprise, we were able to [migrate from Vite to
Next.js](https://github.com/inngest/inngest/pull/479) our [Dev Server
app](https://github.com/inngest/inngest/tree/main#the-inngest-dev-server)
in less than a day, which motivated us to share our learnings with the
community.
### How?
The guide aims to have the minimum number of steps to get a working
Next.js application so that
the reader can then adopt Next.js features incrementally. This means the
migration of the router isn't part of this guide. However, this would be
something valuable to document at a later time so that the reader can
also learn how to migrate to the App Router and get all the Next.js
benefits.
## What?
- Updated the heading structure in the documentation to maintain a consistent hierarchy.
- All primary points now use `###` for better readability and understanding of content structure.
## Why?
While reviewing the documentation, I noticed that the heading levels were inconsistent between sections 1, 2, and 3-5.
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
---------
Previously the code used in both edge and node runtimes used _almost_ the same code. This unifies the two into the base server implementation while also preserving the specific case handled by the split.
This also moves the `/_next/data` route matching to a cached value to prevent it from creating the `RegExp` on every request evaluation.
Adding a default app router not-found error page in production. We introduced a custom global not-found page if you have `not-found.js` file under app directory. Next.js will still routed you to default pages 404 if there's no routes matched when you don't have a custom `not-found.js`.
This PR creates a default layout (only having `html` and `body`) and will use the default not-found component as children to build a default 404 page for app router, and server will route to that page when there's any app router pages existed. This will also fix the hmr issue that when you hit a pathname doesn't exist, nextjs will compile `/_error` for you which is not expected, now we're using `/not-found` instead
Closes NEXT-1359
for internal:
https://vercel.slack.com/archives/C03S8ED1DKM/p1691700057242999
### Problem
- The existing [`redirect()`
function](https://nextjs.org/docs/app/api-reference/functions/redirect)
can't control the status code.
- The existing [`redirect()`
function](https://nextjs.org/docs/app/api-reference/functions/redirect)
returns a 307 HTTP redirect response while it returns a 308-equivalent
meta tag `<meta http-equiv="refresh" content="0;url=/foo"/>` in
streaming response (e.g., suspense boundary), making the behavior
inconsistent.
### Solution
Adding a new `permanentRedirect()` function and changing the meta tag
default accordingly.
| func | HTTP status | meta tag |
|---|:---:|---|
| `redirect()` | 307 | `<meta http-equiv="refresh"
content="1;url=/foo"/>` |
| `permanentRedirect()` | 308 | `<meta http-equiv="refresh"
content="0;url=/foo"/>` |
ref.
https://developers.google.com/search/docs/crawling-indexing/301-redirects
---------
Co-authored-by: JJ Kasper <jj@jjsweb.site>
Co-authored-by: Tim Neutkens <tim@timneutkens.nl>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
add if statement, because typescript throws error: revalidatePath require `string`, but `searchParams.get('path')` returns `string|null` type
Co-authored-by: JJ Kasper <22380829+ijjk@users.noreply.github.com>
This replaces the existing recursive directory reading beheviour with a more efficient implementation. Rather than previously doing actual recursion with the function calls to go deeper into each directory, this has been rewritten to instead use a while loop and a stack. This should improve memory usage for projects with very deep directory structures.
The updated design that performs directory scanning on all directories found at each layer, allowing more filesystem calls to be sent to the OS instead of waiting like the previous implementation did.
**Currently the new implementation is about 3x faster.**
### What?
fix the paths for app pages with route groups (e. g. `(dashboard)`)
Closes WEB-1463
---------
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
## What?
This PR fixes issue #54304. As discussed in the issue it was suspected that the values of weights were not being sorted correctly. The weights were being sorted in lexicographical order.
In order for Google fonts to work, Google Fonts need the values of weights present in the url in sorted order.
Due to this the url which was being generated for Google Fonts which had a value of "1000" in weight was giving an error and the font was not working.
## Why I Think This Solution Works?
Let's assume that we have an object named axes with the property named named "wght" which will have the value of weights as following:
```
const axes = {
wght: ["100", "200", "300", "400", "500", "600", "700", "800", "900", '1000']
}
```
Let's create another variable named "display" with the value set as "swap" and create another variable named "fontFamily" with the value as "DM Sans" (this is the font which was being used in the issue).
```
const fontFamily = "DM Sans";
const display = "swap";
```
If we call the function using them
```
const FONT_URL = getGoogleFontsUrl(fontFamily, axes, display);
console.log("The font url is: ", FONT_URL)
Output Will Be:
The font url is: https://fonts.googleapis.com/css2?family=DM+Sans:wght@100;1000;200;300;400;500;600;700;800;900&display=swap
```
It will give the incorrect value which was shown in the issue.
If you see at line number 56 there was no comparison function passed in the sort function which is what was suspected earlier and it was sorting the values lexicographically.
Create another variable inside the function above line 54 where we are updating the value of "url" variable.
```
const variantValues = variants.map((variant) => variant.map(([, val]) => val).join(','))
console.log("Variant Values: ", variantValues)
Output Will Be:
Variant Values: ["100", "200", "300", "400", "500", "600", "700", "800", "900", "1000"]
```
Now call the function again with the same values you will see the values in the correct order but as soon as you call "sort" function it will give you incorrect sorted values which is what is happening in the "url" variable.
```
const variantValues = variants.map((variant) => variant.map(([, val]) => val).join(',')).sort()
console.log("Variant Values: ", variantValues)
Output Will Be:
["100", "1000", "200", "300", "400", "500", "600", "700", "800", "900"]
(As you can see the values are sorted incorrectly)
```
There was one case when I implemented this solution. When "ital" is also passed then the values are in "ital,wght" format and because of it the sorting was giving incorrect result for this case.
Let's update the "axes" variable which we made previously to contain these values:
```
const axes = {
wght: ["500","300", "400"],
ital: ["0","1"]
}
```
Now when we run the function it gives us the result as:
`
https://fonts.googleapis.com/css2?family=DM+Sans:ital,wght@0,500;0,300;0,400;1,500;1,300;1,400&display=swap`
Where as the expected result was:
`https://fonts.googleapis.com/css2?family=DM+Sans:ital,wght@0,300;0,400;0,500;1,300;1,400;1,500&display=swap`
So, I rewrote the "sort" function to also handle this case.
## What Did I Do To Fix It?
I passed the comparison function inside the "sort" function which was being to ensure that the elements are compared as integers, and thus the sorting will be done numerically.
Which gave me the correct output as url:
`https://fonts.googleapis.com/css2?family=DM+Sans:wght@100;200;300;400;500;600;700;800;900;1000&display=swap`
With values being sorted correctly and if you visit the link you will see the response instead of the error.
Any thought's or suggestions would be greatly appreciated.
Noticed there were two cases in `next-server.ts` that leverage `this as any` to call functions defined only in next-dev-server.
This change ensures the types are correct, which is useful for refactoring, e.g. renaming the function in `next-dev-server` would cause the original code to break unexpectedly.