@nx/next 22.1.1 → 22.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/migrations.json +25 -0
- package/package.json +10 -10
- package/src/migrations/update-22-2-0/create-ai-instructions-for-next-16.d.ts +3 -0
- package/src/migrations/update-22-2-0/create-ai-instructions-for-next-16.d.ts.map +1 -0
- package/src/migrations/update-22-2-0/create-ai-instructions-for-next-16.js +16 -0
- package/src/migrations/update-22-2-0/files/ai-instructions-for-next-16.md +845 -0
package/migrations.json
CHANGED
|
@@ -5,6 +5,15 @@
|
|
|
5
5
|
"version": "22.0.0-beta.0",
|
|
6
6
|
"description": "Updates next.config.js files to add SVGR webpack configuration directly instead of using the nx.svgr option in withNx.",
|
|
7
7
|
"factory": "./src/migrations/update-22-0-0/add-svgr-to-next-config"
|
|
8
|
+
},
|
|
9
|
+
"update-22-2-0-create-ai-instructions-for-next-16": {
|
|
10
|
+
"cli": "nx",
|
|
11
|
+
"version": "22.2.0-beta.1",
|
|
12
|
+
"requires": {
|
|
13
|
+
"next": ">=16.0.0"
|
|
14
|
+
},
|
|
15
|
+
"description": "Create AI Instructions to help migrate users workspaces to Next.js 16.",
|
|
16
|
+
"factory": "./src/migrations/update-22-2-0/create-ai-instructions-for-next-16"
|
|
8
17
|
}
|
|
9
18
|
},
|
|
10
19
|
"packageJsonUpdates": {
|
|
@@ -40,6 +49,22 @@
|
|
|
40
49
|
"alwaysAddToPackageJson": false
|
|
41
50
|
}
|
|
42
51
|
}
|
|
52
|
+
},
|
|
53
|
+
"22.2.0-beta.1": {
|
|
54
|
+
"version": "22.2.0-beta.1",
|
|
55
|
+
"requires": {
|
|
56
|
+
"next": "^15.0.0"
|
|
57
|
+
},
|
|
58
|
+
"packages": {
|
|
59
|
+
"next": {
|
|
60
|
+
"version": "~16.0.1",
|
|
61
|
+
"alwaysAddToPackageJson": false
|
|
62
|
+
},
|
|
63
|
+
"eslint-config-next": {
|
|
64
|
+
"version": "^16.0.1",
|
|
65
|
+
"alwaysAddToPackageJson": false
|
|
66
|
+
}
|
|
67
|
+
}
|
|
43
68
|
}
|
|
44
69
|
}
|
|
45
70
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nx/next",
|
|
3
|
-
"version": "22.1.
|
|
3
|
+
"version": "22.1.3",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "The Next.js plugin for Nx contains executors and generators for managing Next.js applications and libraries within an Nx workspace. It provides:\n\n\n- Scaffolding for creating, building, serving, linting, and testing Next.js applications.\n\n- Integration with building, serving, and exporting a Next.js application.\n\n- Integration with React libraries within the workspace. \n\nWhen using Next.js in Nx, you get the out-of-the-box support for TypeScript, Playwright, Cypress, and Jest. No need to configure anything: watch mode, source maps, and typings just work.",
|
|
6
6
|
"repository": {
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"next": ">=14.0.0 <17.0.0"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@nx/devkit": "22.1.
|
|
38
|
+
"@nx/devkit": "22.1.3",
|
|
39
39
|
"@babel/plugin-proposal-decorators": "^7.22.7",
|
|
40
40
|
"@svgr/webpack": "^8.1.0",
|
|
41
41
|
"copy-webpack-plugin": "^10.2.4",
|
|
@@ -44,17 +44,17 @@
|
|
|
44
44
|
"semver": "^7.6.3",
|
|
45
45
|
"tslib": "^2.3.0",
|
|
46
46
|
"webpack-merge": "^5.8.0",
|
|
47
|
-
"@nx/js": "22.1.
|
|
48
|
-
"@nx/eslint": "22.1.
|
|
49
|
-
"@nx/react": "22.1.
|
|
50
|
-
"@nx/web": "22.1.
|
|
51
|
-
"@nx/webpack": "22.1.
|
|
47
|
+
"@nx/js": "22.1.3",
|
|
48
|
+
"@nx/eslint": "22.1.3",
|
|
49
|
+
"@nx/react": "22.1.3",
|
|
50
|
+
"@nx/web": "22.1.3",
|
|
51
|
+
"@nx/webpack": "22.1.3",
|
|
52
52
|
"@phenomnomnominal/tsquery": "~5.0.1"
|
|
53
53
|
},
|
|
54
54
|
"devDependencies": {
|
|
55
|
-
"@nx/cypress": "22.1.
|
|
56
|
-
"@nx/playwright": "22.1.
|
|
57
|
-
"nx": "22.1.
|
|
55
|
+
"@nx/cypress": "22.1.3",
|
|
56
|
+
"@nx/playwright": "22.1.3",
|
|
57
|
+
"nx": "22.1.3"
|
|
58
58
|
},
|
|
59
59
|
"publishConfig": {
|
|
60
60
|
"access": "public"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-ai-instructions-for-next-16.d.ts","sourceRoot":"","sources":["../../../../../../packages/next/src/migrations/update-22-2-0/create-ai-instructions-for-next-16.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAElC,wBAA8B,6BAA6B,CAAC,IAAI,EAAE,IAAI,qBAerE"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = createAiInstructionsForNext16;
|
|
4
|
+
const path_1 = require("path");
|
|
5
|
+
const fs_1 = require("fs");
|
|
6
|
+
async function createAiInstructionsForNext16(tree) {
|
|
7
|
+
const pathToAiInstructions = (0, path_1.join)(__dirname, 'files', 'ai-instructions-for-next-16.md');
|
|
8
|
+
if (!(0, fs_1.existsSync)(pathToAiInstructions)) {
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
const contents = (0, fs_1.readFileSync)(pathToAiInstructions, 'utf-8');
|
|
12
|
+
tree.write('ai-migrations/MIGRATE_NEXT_16.md', contents);
|
|
13
|
+
return [
|
|
14
|
+
`We created 'ai-migrations/MIGRATE_NEXT_16.md' with instructions for an AI Agent to help migrate your Next.js projects to Next.js 16.`,
|
|
15
|
+
];
|
|
16
|
+
}
|
|
@@ -0,0 +1,845 @@
|
|
|
1
|
+
# Next.js 16 Migration Instructions for LLM
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
These instructions guide you through migrating an Nx workspace containing Next.js projects from Next.js 15 to Next.js 16. Work systematically through each breaking change category.
|
|
6
|
+
|
|
7
|
+
## Pre-Migration Checklist
|
|
8
|
+
|
|
9
|
+
1. **Identify all Next.js projects**:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
nx show projects --with-target build | xargs -I {} nx show project {} --json | jq -r 'select(.targets.build.executor | contains("next")) | .name'
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Or search for Next.js configuration files:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
find . -name "next.config.*" -not -path "*/node_modules/*"
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
2. **Update packages**:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npm install next@latest react@latest react-dom@latest
|
|
25
|
+
npm install -D @types/react @types/react-dom # if using TypeScript
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
3. **Verify minimum requirements**:
|
|
29
|
+
- Node.js 20.9+ (Node.js 18 is no longer supported)
|
|
30
|
+
- TypeScript 5.1.0+
|
|
31
|
+
- Browser support: Chrome 111+, Edge 111+, Firefox 111+, Safari 16.4+
|
|
32
|
+
|
|
33
|
+
## Migration Steps by Category
|
|
34
|
+
|
|
35
|
+
### 1. Async Request APIs (Major Breaking Change)
|
|
36
|
+
|
|
37
|
+
This is the most impactful change in Next.js 16. All dynamic request APIs are now asynchronous.
|
|
38
|
+
|
|
39
|
+
**Search Patterns**:
|
|
40
|
+
|
|
41
|
+
- `cookies()` usage in server components
|
|
42
|
+
- `headers()` usage in server components
|
|
43
|
+
- `draftMode()` usage
|
|
44
|
+
- `params` in page, layout, route handlers, and metadata files
|
|
45
|
+
- `searchParams` in page components
|
|
46
|
+
|
|
47
|
+
#### 1.1 Page Components with params
|
|
48
|
+
|
|
49
|
+
**Changes Required**:
|
|
50
|
+
|
|
51
|
+
```tsx
|
|
52
|
+
// BEFORE (Next.js 15)
|
|
53
|
+
export default function Page({ params }) {
|
|
54
|
+
const { slug } = params;
|
|
55
|
+
return <h1>{slug}</h1>;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// AFTER (Next.js 16)
|
|
59
|
+
export default async function Page(props) {
|
|
60
|
+
const { slug } = await props.params;
|
|
61
|
+
return <h1>{slug}</h1>;
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
**Action Items**:
|
|
66
|
+
|
|
67
|
+
- [ ] Make all page components that use `params` async
|
|
68
|
+
- [ ] Add `await` before accessing `props.params`
|
|
69
|
+
- [ ] Update TypeScript types if applicable
|
|
70
|
+
|
|
71
|
+
#### 1.2 Page Components with searchParams
|
|
72
|
+
|
|
73
|
+
**Changes Required**:
|
|
74
|
+
|
|
75
|
+
```tsx
|
|
76
|
+
// BEFORE (Next.js 15)
|
|
77
|
+
export default function Page({ searchParams }) {
|
|
78
|
+
const query = searchParams.q;
|
|
79
|
+
return <Results query={query} />;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// AFTER (Next.js 16)
|
|
83
|
+
export default async function Page(props) {
|
|
84
|
+
const searchParams = await props.searchParams;
|
|
85
|
+
const query = searchParams.q;
|
|
86
|
+
return <Results query={query} />;
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
**Action Items**:
|
|
91
|
+
|
|
92
|
+
- [ ] Make all page components that use `searchParams` async
|
|
93
|
+
- [ ] Add `await` before accessing `props.searchParams`
|
|
94
|
+
|
|
95
|
+
#### 1.3 Layout Components with params
|
|
96
|
+
|
|
97
|
+
**Changes Required**:
|
|
98
|
+
|
|
99
|
+
```tsx
|
|
100
|
+
// BEFORE (Next.js 15)
|
|
101
|
+
export default function Layout({ children, params }) {
|
|
102
|
+
const { locale } = params;
|
|
103
|
+
return <div data-locale={locale}>{children}</div>;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// AFTER (Next.js 16)
|
|
107
|
+
export default async function Layout(props) {
|
|
108
|
+
const { locale } = await props.params;
|
|
109
|
+
return <div data-locale={locale}>{props.children}</div>;
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
#### 1.4 Route Handlers
|
|
114
|
+
|
|
115
|
+
**Changes Required**:
|
|
116
|
+
|
|
117
|
+
```tsx
|
|
118
|
+
// BEFORE (Next.js 15)
|
|
119
|
+
export async function GET(request, { params }) {
|
|
120
|
+
const { id } = params;
|
|
121
|
+
return Response.json({ id });
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// AFTER (Next.js 16)
|
|
125
|
+
export async function GET(request, props) {
|
|
126
|
+
const { id } = await props.params;
|
|
127
|
+
return Response.json({ id });
|
|
128
|
+
}
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
#### 1.5 cookies() and headers()
|
|
132
|
+
|
|
133
|
+
**Changes Required**:
|
|
134
|
+
|
|
135
|
+
```tsx
|
|
136
|
+
// BEFORE (Next.js 15)
|
|
137
|
+
import { cookies, headers } from 'next/headers';
|
|
138
|
+
|
|
139
|
+
export default function Page() {
|
|
140
|
+
const cookieStore = cookies();
|
|
141
|
+
const headersList = headers();
|
|
142
|
+
const theme = cookieStore.get('theme');
|
|
143
|
+
const userAgent = headersList.get('user-agent');
|
|
144
|
+
return <div>...</div>;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// AFTER (Next.js 16)
|
|
148
|
+
import { cookies, headers } from 'next/headers';
|
|
149
|
+
|
|
150
|
+
export default async function Page() {
|
|
151
|
+
const cookieStore = await cookies();
|
|
152
|
+
const headersList = await headers();
|
|
153
|
+
const theme = cookieStore.get('theme');
|
|
154
|
+
const userAgent = headersList.get('user-agent');
|
|
155
|
+
return <div>...</div>;
|
|
156
|
+
}
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
#### 1.6 draftMode()
|
|
160
|
+
|
|
161
|
+
**Changes Required**:
|
|
162
|
+
|
|
163
|
+
```tsx
|
|
164
|
+
// BEFORE (Next.js 15)
|
|
165
|
+
import { draftMode } from 'next/headers';
|
|
166
|
+
|
|
167
|
+
export default function Page() {
|
|
168
|
+
const { isEnabled } = draftMode();
|
|
169
|
+
return <div>{isEnabled ? 'Draft' : 'Published'}</div>;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// AFTER (Next.js 16)
|
|
173
|
+
import { draftMode } from 'next/headers';
|
|
174
|
+
|
|
175
|
+
export default async function Page() {
|
|
176
|
+
const { isEnabled } = await draftMode();
|
|
177
|
+
return <div>{isEnabled ? 'Draft' : 'Published'}</div>;
|
|
178
|
+
}
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
#### 1.7 generateMetadata with params
|
|
182
|
+
|
|
183
|
+
**Changes Required**:
|
|
184
|
+
|
|
185
|
+
```tsx
|
|
186
|
+
// BEFORE (Next.js 15)
|
|
187
|
+
export async function generateMetadata({ params }) {
|
|
188
|
+
const { slug } = params;
|
|
189
|
+
return { title: slug };
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// AFTER (Next.js 16)
|
|
193
|
+
export async function generateMetadata(props) {
|
|
194
|
+
const { slug } = await props.params;
|
|
195
|
+
return { title: slug };
|
|
196
|
+
}
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
#### 1.8 Automated Migration
|
|
200
|
+
|
|
201
|
+
Run the Next.js codemod for automated migration:
|
|
202
|
+
|
|
203
|
+
```bash
|
|
204
|
+
npx @next/codemod@canary upgrade latest
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
Generate type helpers for safer migrations (Next.js 15.5+):
|
|
208
|
+
|
|
209
|
+
```bash
|
|
210
|
+
npx next typegen
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
This generates `PageProps`, `LayoutProps`, and `RouteContext` helpers.
|
|
214
|
+
|
|
215
|
+
### 2. Image Generation Functions
|
|
216
|
+
|
|
217
|
+
**Search Pattern**: `generateImageMetadata`, `default function Image` in opengraph-image or twitter-image files
|
|
218
|
+
|
|
219
|
+
**Changes Required**:
|
|
220
|
+
|
|
221
|
+
```tsx
|
|
222
|
+
// BEFORE (Next.js 15)
|
|
223
|
+
export function generateImageMetadata({ params }) {
|
|
224
|
+
const { slug } = params;
|
|
225
|
+
return [{ id: '1' }];
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
export default function Image({ params, id }) {
|
|
229
|
+
const slug = params.slug;
|
|
230
|
+
return new ImageResponse(/* ... */);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// AFTER (Next.js 16)
|
|
234
|
+
export async function generateImageMetadata({ params }) {
|
|
235
|
+
const { slug } = await params;
|
|
236
|
+
return [{ id: '1' }];
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
export default async function Image({ params, id }) {
|
|
240
|
+
const { slug } = await params;
|
|
241
|
+
const imageId = await id;
|
|
242
|
+
return new ImageResponse(/* ... */);
|
|
243
|
+
}
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
**Action Items**:
|
|
247
|
+
|
|
248
|
+
- [ ] Make `generateImageMetadata` functions async
|
|
249
|
+
- [ ] Make Image components async
|
|
250
|
+
- [ ] Add `await` for both `params` and `id` access
|
|
251
|
+
|
|
252
|
+
### 3. Sitemap Generation
|
|
253
|
+
|
|
254
|
+
**Search Pattern**: `sitemap` functions with `id` parameter
|
|
255
|
+
|
|
256
|
+
**Changes Required**:
|
|
257
|
+
|
|
258
|
+
```tsx
|
|
259
|
+
// BEFORE (Next.js 15)
|
|
260
|
+
export default async function sitemap({ id }) {
|
|
261
|
+
const start = id * 50000;
|
|
262
|
+
// ...
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// AFTER (Next.js 16)
|
|
266
|
+
export default async function sitemap({ id }) {
|
|
267
|
+
const resolvedId = await id;
|
|
268
|
+
const start = resolvedId * 50000;
|
|
269
|
+
// ...
|
|
270
|
+
}
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
### 4. Turbopack Configuration
|
|
274
|
+
|
|
275
|
+
Turbopack is now the default bundler for development.
|
|
276
|
+
|
|
277
|
+
**Search Pattern**: `--turbo` or `--turbopack` flags in package.json scripts, `turbopack` in next.config
|
|
278
|
+
|
|
279
|
+
#### 4.1 Remove Explicit Turbopack Flags
|
|
280
|
+
|
|
281
|
+
```json
|
|
282
|
+
// BEFORE (Next.js 15)
|
|
283
|
+
{
|
|
284
|
+
"scripts": {
|
|
285
|
+
"dev": "next dev --turbo"
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// AFTER (Next.js 16) - Turbopack is default
|
|
290
|
+
{
|
|
291
|
+
"scripts": {
|
|
292
|
+
"dev": "next dev"
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
#### 4.2 Opt Out to Webpack (if needed)
|
|
298
|
+
|
|
299
|
+
```json
|
|
300
|
+
{
|
|
301
|
+
"scripts": {
|
|
302
|
+
"build": "next build --webpack"
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
#### 4.3 Move Turbopack Config Out of Experimental
|
|
308
|
+
|
|
309
|
+
```ts
|
|
310
|
+
// BEFORE (Next.js 15)
|
|
311
|
+
const nextConfig = {
|
|
312
|
+
experimental: {
|
|
313
|
+
turbopack: {
|
|
314
|
+
/* options */
|
|
315
|
+
},
|
|
316
|
+
},
|
|
317
|
+
};
|
|
318
|
+
|
|
319
|
+
// AFTER (Next.js 16)
|
|
320
|
+
const nextConfig = {
|
|
321
|
+
turbopack: {
|
|
322
|
+
/* options */
|
|
323
|
+
},
|
|
324
|
+
};
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
#### 4.4 Update Sass Imports (Turbopack Specific)
|
|
328
|
+
|
|
329
|
+
```scss
|
|
330
|
+
/* BEFORE */
|
|
331
|
+
@import '~bootstrap/dist/css/bootstrap.min.css';
|
|
332
|
+
|
|
333
|
+
/* AFTER - Remove tilde prefix */
|
|
334
|
+
@import 'bootstrap/dist/css/bootstrap.min.css';
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
**Action Items**:
|
|
338
|
+
|
|
339
|
+
- [ ] Remove `--turbo` and `--turbopack` flags from scripts
|
|
340
|
+
- [ ] Move `turbopack` config from `experimental` to root level
|
|
341
|
+
- [ ] Remove tilde (`~`) prefix from Sass imports
|
|
342
|
+
- [ ] Add `--webpack` flag if Webpack is required
|
|
343
|
+
|
|
344
|
+
### 5. Middleware to Proxy Rename
|
|
345
|
+
|
|
346
|
+
**Search Pattern**: `middleware.ts` or `middleware.js` files
|
|
347
|
+
|
|
348
|
+
**Changes Required**:
|
|
349
|
+
|
|
350
|
+
```bash
|
|
351
|
+
# Rename the file
|
|
352
|
+
mv middleware.ts proxy.ts
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
```ts
|
|
356
|
+
// BEFORE (middleware.ts)
|
|
357
|
+
export function middleware(request) {
|
|
358
|
+
// ...
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
// AFTER (proxy.ts)
|
|
362
|
+
export function proxy(request) {
|
|
363
|
+
// ...
|
|
364
|
+
}
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
**Config Updates**:
|
|
368
|
+
|
|
369
|
+
```js
|
|
370
|
+
// BEFORE
|
|
371
|
+
{
|
|
372
|
+
skipMiddlewareUrlNormalize: true;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
// AFTER
|
|
376
|
+
{
|
|
377
|
+
skipProxyUrlNormalize: true;
|
|
378
|
+
}
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
**Important**: The Edge runtime is no longer supported in `proxy`. It now uses Node.js runtime.
|
|
382
|
+
|
|
383
|
+
**Action Items**:
|
|
384
|
+
|
|
385
|
+
- [ ] Rename `middleware.ts/js` to `proxy.ts/js`
|
|
386
|
+
- [ ] Rename exported function from `middleware` to `proxy`
|
|
387
|
+
- [ ] Update config option names
|
|
388
|
+
- [ ] Remove Edge runtime usage from proxy files
|
|
389
|
+
|
|
390
|
+
### 6. Parallel Routes default.js Requirement
|
|
391
|
+
|
|
392
|
+
**Search Pattern**: Directories starting with `@` in the app folder (parallel route slots)
|
|
393
|
+
|
|
394
|
+
All parallel route slots now require an explicit `default.js` file.
|
|
395
|
+
|
|
396
|
+
**Changes Required**:
|
|
397
|
+
|
|
398
|
+
```tsx
|
|
399
|
+
// Create app/@modal/default.tsx for each parallel route slot
|
|
400
|
+
import { notFound } from 'next/navigation';
|
|
401
|
+
|
|
402
|
+
export default function Default() {
|
|
403
|
+
notFound(); // or return null
|
|
404
|
+
}
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
**Action Items**:
|
|
408
|
+
|
|
409
|
+
- [ ] Find all parallel route slots (`app/@*/`)
|
|
410
|
+
- [ ] Create `default.tsx` in each slot that doesn't have one
|
|
411
|
+
|
|
412
|
+
### 7. Image Optimization Changes
|
|
413
|
+
|
|
414
|
+
#### 7.1 Local Images with Query Strings
|
|
415
|
+
|
|
416
|
+
```tsx
|
|
417
|
+
// Now requires explicit configuration
|
|
418
|
+
<Image src="/assets/photo?v=1" alt="Photo" width="100" height="100" />
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
```js
|
|
422
|
+
// next.config.js
|
|
423
|
+
module.exports = {
|
|
424
|
+
images: {
|
|
425
|
+
localPatterns: [
|
|
426
|
+
{
|
|
427
|
+
pathname: '/assets/**',
|
|
428
|
+
search: '?v=1',
|
|
429
|
+
},
|
|
430
|
+
],
|
|
431
|
+
},
|
|
432
|
+
};
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
#### 7.2 Default Value Changes
|
|
436
|
+
|
|
437
|
+
Add these to `next.config.js` if you need the old defaults:
|
|
438
|
+
|
|
439
|
+
```js
|
|
440
|
+
module.exports = {
|
|
441
|
+
images: {
|
|
442
|
+
// minimumCacheTTL changed from 60 to 14400 seconds
|
|
443
|
+
minimumCacheTTL: 60,
|
|
444
|
+
|
|
445
|
+
// Value 16 removed from default imageSizes
|
|
446
|
+
imageSizes: [16, 32, 48, 64, 96, 128, 256, 384],
|
|
447
|
+
|
|
448
|
+
// qualities now defaults to [75] only
|
|
449
|
+
qualities: [50, 75, 100],
|
|
450
|
+
|
|
451
|
+
// Local IP now blocked by default
|
|
452
|
+
dangerouslyAllowLocalIP: true, // only for private networks
|
|
453
|
+
|
|
454
|
+
// Maximum redirects changed from unlimited to 3
|
|
455
|
+
maximumRedirects: 5,
|
|
456
|
+
},
|
|
457
|
+
};
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
#### 7.3 Deprecated images.domains
|
|
461
|
+
|
|
462
|
+
```js
|
|
463
|
+
// BEFORE - Remove this
|
|
464
|
+
module.exports = {
|
|
465
|
+
images: {
|
|
466
|
+
domains: ['example.com'],
|
|
467
|
+
},
|
|
468
|
+
};
|
|
469
|
+
|
|
470
|
+
// AFTER - Use remotePatterns instead
|
|
471
|
+
module.exports = {
|
|
472
|
+
images: {
|
|
473
|
+
remotePatterns: [
|
|
474
|
+
{
|
|
475
|
+
protocol: 'https',
|
|
476
|
+
hostname: 'example.com',
|
|
477
|
+
},
|
|
478
|
+
],
|
|
479
|
+
},
|
|
480
|
+
};
|
|
481
|
+
```
|
|
482
|
+
|
|
483
|
+
**Action Items**:
|
|
484
|
+
|
|
485
|
+
- [ ] Add `localPatterns` for images with query strings
|
|
486
|
+
- [ ] Migrate `images.domains` to `images.remotePatterns`
|
|
487
|
+
- [ ] Review and update default values if needed
|
|
488
|
+
|
|
489
|
+
### 8. Caching API Updates
|
|
490
|
+
|
|
491
|
+
#### 8.1 Remove unstable\_ Prefix
|
|
492
|
+
|
|
493
|
+
```ts
|
|
494
|
+
// BEFORE (Next.js 15)
|
|
495
|
+
import {
|
|
496
|
+
unstable_cacheLife as cacheLife,
|
|
497
|
+
unstable_cacheTag as cacheTag,
|
|
498
|
+
} from 'next/cache';
|
|
499
|
+
|
|
500
|
+
// AFTER (Next.js 16)
|
|
501
|
+
import { cacheLife, cacheTag } from 'next/cache';
|
|
502
|
+
```
|
|
503
|
+
|
|
504
|
+
#### 8.2 New Cache Functions
|
|
505
|
+
|
|
506
|
+
**revalidateTag with cacheLife profile**:
|
|
507
|
+
|
|
508
|
+
```ts
|
|
509
|
+
'use server';
|
|
510
|
+
import { revalidateTag } from 'next/cache';
|
|
511
|
+
|
|
512
|
+
export async function updateArticle(articleId: string) {
|
|
513
|
+
revalidateTag(`article-${articleId}`, 'max');
|
|
514
|
+
}
|
|
515
|
+
```
|
|
516
|
+
|
|
517
|
+
**updateTag (new)**:
|
|
518
|
+
|
|
519
|
+
```ts
|
|
520
|
+
'use server';
|
|
521
|
+
import { updateTag } from 'next/cache';
|
|
522
|
+
|
|
523
|
+
export async function updateUserProfile(userId: string, profile: Profile) {
|
|
524
|
+
await db.users.update(userId, profile);
|
|
525
|
+
updateTag(`user-${userId}`);
|
|
526
|
+
}
|
|
527
|
+
```
|
|
528
|
+
|
|
529
|
+
**refresh (new)**:
|
|
530
|
+
|
|
531
|
+
```ts
|
|
532
|
+
'use server';
|
|
533
|
+
import { refresh } from 'next/cache';
|
|
534
|
+
|
|
535
|
+
export async function markNotificationAsRead(notificationId: string) {
|
|
536
|
+
await db.notifications.markAsRead(notificationId);
|
|
537
|
+
refresh();
|
|
538
|
+
}
|
|
539
|
+
```
|
|
540
|
+
|
|
541
|
+
**Action Items**:
|
|
542
|
+
|
|
543
|
+
- [ ] Remove `unstable_` prefix from `cacheLife` and `cacheTag` imports
|
|
544
|
+
- [ ] Consider using new `updateTag` and `refresh` functions
|
|
545
|
+
|
|
546
|
+
### 9. React Compiler Support
|
|
547
|
+
|
|
548
|
+
React Compiler is now stable and supported:
|
|
549
|
+
|
|
550
|
+
```ts
|
|
551
|
+
// next.config.ts
|
|
552
|
+
const nextConfig = {
|
|
553
|
+
reactCompiler: true,
|
|
554
|
+
};
|
|
555
|
+
|
|
556
|
+
export default nextConfig;
|
|
557
|
+
```
|
|
558
|
+
|
|
559
|
+
Install the plugin:
|
|
560
|
+
|
|
561
|
+
```bash
|
|
562
|
+
npm install -D babel-plugin-react-compiler
|
|
563
|
+
```
|
|
564
|
+
|
|
565
|
+
**Note**: Expect higher compile times with React Compiler enabled.
|
|
566
|
+
|
|
567
|
+
### 10. Scroll Behavior Override
|
|
568
|
+
|
|
569
|
+
Next.js no longer overrides `scroll-behavior: smooth` during navigation.
|
|
570
|
+
|
|
571
|
+
To restore previous behavior:
|
|
572
|
+
|
|
573
|
+
```tsx
|
|
574
|
+
// app/layout.tsx
|
|
575
|
+
export default function RootLayout({ children }) {
|
|
576
|
+
return (
|
|
577
|
+
<html lang="en" data-scroll-behavior="smooth">
|
|
578
|
+
<body>{children}</body>
|
|
579
|
+
</html>
|
|
580
|
+
);
|
|
581
|
+
}
|
|
582
|
+
```
|
|
583
|
+
|
|
584
|
+
### 11. ESLint Migration
|
|
585
|
+
|
|
586
|
+
The `next lint` command has been removed. Migrate to ESLint CLI directly.
|
|
587
|
+
|
|
588
|
+
```bash
|
|
589
|
+
# Run migration codemod
|
|
590
|
+
npx @next/codemod@canary next-lint-to-eslint-cli .
|
|
591
|
+
```
|
|
592
|
+
|
|
593
|
+
Remove from `next.config.js`:
|
|
594
|
+
|
|
595
|
+
```js
|
|
596
|
+
// Remove this
|
|
597
|
+
{
|
|
598
|
+
eslint: {
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
```
|
|
602
|
+
|
|
603
|
+
**Action Items**:
|
|
604
|
+
|
|
605
|
+
- [ ] Run the ESLint migration codemod
|
|
606
|
+
- [ ] Remove `eslint` config from `next.config.js`
|
|
607
|
+
- [ ] Update CI scripts to use `eslint` directly instead of `next lint`
|
|
608
|
+
|
|
609
|
+
### 12. Feature Removals
|
|
610
|
+
|
|
611
|
+
#### 12.1 AMP Support Removed
|
|
612
|
+
|
|
613
|
+
- All AMP APIs have been deleted
|
|
614
|
+
- Remove `useAmp` hook usage
|
|
615
|
+
- Remove `amp` config option
|
|
616
|
+
- Delete AMP-specific pages
|
|
617
|
+
|
|
618
|
+
#### 12.2 Runtime Configuration Removed
|
|
619
|
+
|
|
620
|
+
```js
|
|
621
|
+
// BEFORE - Remove these
|
|
622
|
+
module.exports = {
|
|
623
|
+
serverRuntimeConfig: { dbUrl: process.env.DATABASE_URL },
|
|
624
|
+
publicRuntimeConfig: { apiUrl: '/api' },
|
|
625
|
+
};
|
|
626
|
+
```
|
|
627
|
+
|
|
628
|
+
**Migration for server-side config**:
|
|
629
|
+
|
|
630
|
+
```tsx
|
|
631
|
+
// Use environment variables directly
|
|
632
|
+
async function fetchData() {
|
|
633
|
+
const dbUrl = process.env.DATABASE_URL;
|
|
634
|
+
return await db.query(dbUrl, 'SELECT * FROM users');
|
|
635
|
+
}
|
|
636
|
+
```
|
|
637
|
+
|
|
638
|
+
**Migration for client-side config**:
|
|
639
|
+
|
|
640
|
+
```bash
|
|
641
|
+
# .env.local
|
|
642
|
+
NEXT_PUBLIC_API_URL="/api"
|
|
643
|
+
```
|
|
644
|
+
|
|
645
|
+
```tsx
|
|
646
|
+
'use client';
|
|
647
|
+
export default function Component() {
|
|
648
|
+
const apiUrl = process.env.NEXT_PUBLIC_API_URL;
|
|
649
|
+
// ...
|
|
650
|
+
}
|
|
651
|
+
```
|
|
652
|
+
|
|
653
|
+
#### 12.3 devIndicators Options Removed
|
|
654
|
+
|
|
655
|
+
Remove these from `next.config.js`:
|
|
656
|
+
|
|
657
|
+
- `appIsrStatus`
|
|
658
|
+
- `buildActivity`
|
|
659
|
+
- `buildActivityPosition`
|
|
660
|
+
|
|
661
|
+
#### 12.4 experimental.dynamicIO Renamed
|
|
662
|
+
|
|
663
|
+
```js
|
|
664
|
+
// BEFORE
|
|
665
|
+
{
|
|
666
|
+
experimental: {
|
|
667
|
+
dynamicIO: true;
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
// AFTER
|
|
672
|
+
{
|
|
673
|
+
cacheComponents: true;
|
|
674
|
+
}
|
|
675
|
+
```
|
|
676
|
+
|
|
677
|
+
#### 12.5 unstable_rootParams Removed
|
|
678
|
+
|
|
679
|
+
This API is removed. Await alternative API in a future minor release.
|
|
680
|
+
|
|
681
|
+
**Action Items**:
|
|
682
|
+
|
|
683
|
+
- [ ] Remove all AMP-related code
|
|
684
|
+
- [ ] Migrate runtime configuration to environment variables
|
|
685
|
+
- [ ] Remove deprecated devIndicators options
|
|
686
|
+
- [ ] Rename `dynamicIO` to `cacheComponents`
|
|
687
|
+
|
|
688
|
+
### 13. Development Changes
|
|
689
|
+
|
|
690
|
+
#### 13.1 Concurrent dev and build
|
|
691
|
+
|
|
692
|
+
Development now outputs to `.next/dev` (separate from build).
|
|
693
|
+
|
|
694
|
+
**Update Turbopack tracing command**:
|
|
695
|
+
|
|
696
|
+
```bash
|
|
697
|
+
npx next internal trace .next/dev/trace-turbopack
|
|
698
|
+
```
|
|
699
|
+
|
|
700
|
+
## Post-Migration Validation
|
|
701
|
+
|
|
702
|
+
### 1. Run Build Per Project
|
|
703
|
+
|
|
704
|
+
```bash
|
|
705
|
+
# Build each Next.js project individually
|
|
706
|
+
nx run PROJECT_NAME:build
|
|
707
|
+
```
|
|
708
|
+
|
|
709
|
+
### 2. Run Development Server
|
|
710
|
+
|
|
711
|
+
```bash
|
|
712
|
+
# Start dev server to verify Turbopack works
|
|
713
|
+
nx run PROJECT_NAME:serve
|
|
714
|
+
```
|
|
715
|
+
|
|
716
|
+
### 3. Run All Affected Builds
|
|
717
|
+
|
|
718
|
+
```bash
|
|
719
|
+
# Build all affected projects
|
|
720
|
+
nx affected -t build
|
|
721
|
+
```
|
|
722
|
+
|
|
723
|
+
### 4. Run Full Validation
|
|
724
|
+
|
|
725
|
+
```bash
|
|
726
|
+
# Run full CI validation
|
|
727
|
+
nx prepush
|
|
728
|
+
```
|
|
729
|
+
|
|
730
|
+
### 5. Review Migration Checklist
|
|
731
|
+
|
|
732
|
+
- [ ] All async request APIs updated
|
|
733
|
+
- [ ] All page/layout components using params are async
|
|
734
|
+
- [ ] Turbopack configuration updated
|
|
735
|
+
- [ ] Middleware renamed to proxy
|
|
736
|
+
- [ ] Parallel routes have default.js files
|
|
737
|
+
- [ ] Image configuration updated
|
|
738
|
+
- [ ] Cache imports updated (removed unstable\_ prefix)
|
|
739
|
+
- [ ] AMP code removed
|
|
740
|
+
- [ ] Runtime config migrated to env vars
|
|
741
|
+
- [ ] ESLint configuration migrated
|
|
742
|
+
- [ ] All projects build successfully
|
|
743
|
+
- [ ] Development servers start correctly
|
|
744
|
+
|
|
745
|
+
## Common Issues and Solutions
|
|
746
|
+
|
|
747
|
+
### Issue: "cookies() expects to be called in a synchronous context"
|
|
748
|
+
|
|
749
|
+
**Solution**: Make the function async and await `cookies()`
|
|
750
|
+
|
|
751
|
+
### Issue: "params should be awaited before accessing properties"
|
|
752
|
+
|
|
753
|
+
**Solution**: Add `await` before accessing `props.params`
|
|
754
|
+
|
|
755
|
+
### Issue: Build fails with Turbopack
|
|
756
|
+
|
|
757
|
+
**Solution**: Add `--webpack` flag to build script, then gradually address Turbopack compatibility
|
|
758
|
+
|
|
759
|
+
### Issue: Middleware not working after rename
|
|
760
|
+
|
|
761
|
+
**Solution**: Ensure both file and function are renamed from `middleware` to `proxy`
|
|
762
|
+
|
|
763
|
+
### Issue: Parallel route not rendering
|
|
764
|
+
|
|
765
|
+
**Solution**: Add `default.tsx` file to the parallel route slot
|
|
766
|
+
|
|
767
|
+
### Issue: Images with query strings not loading
|
|
768
|
+
|
|
769
|
+
**Solution**: Add `localPatterns` configuration for those images
|
|
770
|
+
|
|
771
|
+
### Issue: TypeScript errors with params types
|
|
772
|
+
|
|
773
|
+
**Solution**: Run `npx next typegen` to generate type helpers, then use `PageProps`, `LayoutProps` types
|
|
774
|
+
|
|
775
|
+
## Files to Review
|
|
776
|
+
|
|
777
|
+
Create a checklist of all files that need review:
|
|
778
|
+
|
|
779
|
+
```bash
|
|
780
|
+
# Find all pages with potential params usage
|
|
781
|
+
find . -path "*/app/*" -name "page.tsx" -o -name "page.ts" | xargs grep -l "params\|searchParams"
|
|
782
|
+
|
|
783
|
+
# Find all layouts
|
|
784
|
+
find . -path "*/app/*" -name "layout.tsx" -o -name "layout.ts"
|
|
785
|
+
|
|
786
|
+
# Find all route handlers
|
|
787
|
+
find . -path "*/app/*" -name "route.ts" -o -name "route.tsx"
|
|
788
|
+
|
|
789
|
+
# Find middleware files
|
|
790
|
+
find . -name "middleware.ts" -o -name "middleware.js"
|
|
791
|
+
|
|
792
|
+
# Find files using cookies/headers
|
|
793
|
+
rg "from 'next/headers'" --type ts --type tsx
|
|
794
|
+
|
|
795
|
+
# Find next.config files
|
|
796
|
+
find . -name "next.config.*" -not -path "*/node_modules/*"
|
|
797
|
+
|
|
798
|
+
# Find parallel routes
|
|
799
|
+
find . -path "*/app/@*" -type d
|
|
800
|
+
```
|
|
801
|
+
|
|
802
|
+
## Migration Strategy for Large Workspaces
|
|
803
|
+
|
|
804
|
+
1. **Migrate in phases**: Start with a small project, validate, then expand
|
|
805
|
+
2. **Use the codemod**: Run `npx @next/codemod@canary upgrade latest` for automated fixes
|
|
806
|
+
3. **Generate types**: Run `npx next typegen` for type-safe migrations
|
|
807
|
+
4. **Run tests frequently**: After each configuration change, run affected tests
|
|
808
|
+
5. **Document issues**: Keep track of project-specific issues and solutions
|
|
809
|
+
|
|
810
|
+
## Useful Commands During Migration
|
|
811
|
+
|
|
812
|
+
```bash
|
|
813
|
+
# Find all Next.js projects
|
|
814
|
+
nx show projects --with-target build
|
|
815
|
+
|
|
816
|
+
# Build specific project
|
|
817
|
+
nx build PROJECT_NAME
|
|
818
|
+
|
|
819
|
+
# Serve specific project
|
|
820
|
+
nx serve PROJECT_NAME
|
|
821
|
+
|
|
822
|
+
# Build all affected
|
|
823
|
+
nx affected -t build
|
|
824
|
+
|
|
825
|
+
# View project details
|
|
826
|
+
nx show project PROJECT_NAME --web
|
|
827
|
+
|
|
828
|
+
# Clear Nx cache if needed
|
|
829
|
+
nx reset
|
|
830
|
+
```
|
|
831
|
+
|
|
832
|
+
---
|
|
833
|
+
|
|
834
|
+
## Notes for LLM Execution
|
|
835
|
+
|
|
836
|
+
When executing this migration:
|
|
837
|
+
|
|
838
|
+
1. **Work systematically**: Complete one category before moving to the next
|
|
839
|
+
2. **Test after each change**: Don't batch all changes without validation
|
|
840
|
+
3. **Keep user informed**: Report progress through each section
|
|
841
|
+
4. **Handle errors promptly**: If builds fail, fix immediately before proceeding
|
|
842
|
+
5. **Use the codemod first**: Let `@next/codemod` handle repetitive async/await changes
|
|
843
|
+
6. **Prioritize breaking changes**: Focus on async APIs first as they're most impactful
|
|
844
|
+
7. **Create meaningful commits**: Group related changes together with clear messages
|
|
845
|
+
8. **Use TodoWrite tool**: Track migration progress for visibility
|