Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hot reload and debugger broken on dynamic pages in Next.js 14.2.0-canary.43 with --turbo (broken for all versions of --turbo) - vscode debugger #63740

Closed
avianion opened this issue Mar 26, 2024 · 19 comments
Labels
bug Issue was opened via the bug report template. linear: turbopack Confirmed issue that is tracked by the Turbopack team. Turbopack Related to Turbopack with Next.js.

Comments

@avianion
Copy link

avianion commented Mar 26, 2024

Link to the code that reproduces this issue

https://github.com/avianion/nextjs-turbo-broken-dynamic-page-hot-reload-and-vscode-debugger

To Reproduce

To Reproduce:

Set up a Next.js project with Turbopack (--turbo).
Create a dynamic page (e.g., pages/posts/[id].js).
Run the development server.
Make changes to the dynamic page.
Observe that the hot reload does not work, and the vscode debugger breaks.

Current vs. Expected behavior

Current vs. Expected behavior:
Current behavior: Hot reload does not work on dynamic pages, and the debugger breaks, overloading the jest-worker. Next.js searches for the dynamic page in the list of pages but cannot find it.
Expected behavior: Hot reload should work seamlessly on dynamic pages, allowing changes to be reflected immediately without reloading the entire page. The debugger should function correctly without breaking or overloading the jest-worker.

Provide environment information

Operating System:
  Platform: win32
  Arch: x64
  Version: Windows 10 Pro
Binaries:
  Node: 20.0.0
  npm: 9.6.4
  Yarn: 1.22.19
  pnpm: 7.29.1
Relevant packages:
  next: 14.2.0-canary.43
  react: 18.2.0
  react-dom: 18.2.0

Which area(s) are affected? (Select all that apply)

Turbopack (--turbo)

Which stage(s) are affected? (Select all that apply)

next dev (local)

Additional context

I am running Next.js in a Docker container on Windows 11.
The issue specifically occurs on dynamic pages (e.g., [id]).
I suspect this might be related to how Next.js handles dynamic pages in combination with Turborepo.

PACK-2881

@avianion avianion added the bug Issue was opened via the bug report template. label Mar 26, 2024
@github-actions github-actions bot added the Turbopack Related to Turbopack with Next.js. label Mar 26, 2024
@avianion avianion changed the title Title: Hot reload and debugger broken on dynamic pages in Next.js 14.2.0-canary.43 with --turbo (broken for all versions of --turbo) - vscode debugger Hot reload and debugger broken on dynamic pages in Next.js 14.2.0-canary.43 with --turbo (broken for all versions of --turbo) - vscode debugger Mar 26, 2024
@sokra sokra added the linear: turbopack Confirmed issue that is tracked by the Turbopack team. label Mar 30, 2024
@wottpal
Copy link

wottpal commented Apr 20, 2024

Same issue here and assuming it's related to dynamic pages specifically. Everything works fine when omitting --turbo.

@avianion
Copy link
Author

I can't believe this is not fixed yet. This is literally a development breaking bug for people who use dynamic page routes.

And I assume that's a lot of people.

I've been diligently following up and trying with each new canary version to no avail for the past few weeks.

I am wondering when all turbopack tests are done will it still work or will there be issues outstanding?

@timneutkens
Copy link
Member

Hey, thank you for trying out Turbopack and sharing your experience!

Sorry we haven't been able to get back to your particular issue yet. It landed on the backlog as we weren't able to reproduce the specific issue of hot reloading not working, only that vscode debugger does not work which was not release candidate blocking (bug that could be fixed before the stable release).

I've opened a PR on your reproduction to have some code that might reproduce it based on the steps provided: PR.
The provided repository only holds the reproduction template without changes, maybe you made the changes but didn't push them to the repository?

Could you share more details about what you're seeing exactly? From reading the reproduction steps it sounds like you're trying to report 2 separate issues:

  • HMR does not work on dynamic routes
  • VS Code debugger does attach to code

However from running the reproduction steps I was only able to confirm one issue:

  • VS Code debugger does not attach to code (both on dynamic routes as well as normal routes)

We tried running the reproduction both on macOS and Windows and HMR/Fast Refresh are being applied correctly.

Could you please share additional details so that we can investigate it further? Then we can implement a fix for your particular case.
We're going to have a look at the vscode debugger issue regardless 👍

Thanks in advance!

@timneutkens
Copy link
Member

Just did some investigating with @sokra and found that the reason it doesn't apply is that VS Code's debugger has built-in handling for webpack specific sourcemap mapping, i.e. webpack:// and such. In order to support Turbopack out of the box we have to send a PR to the VS Code extension (going to do that now). On the Turbopack side of things we're renaming one of the paths so that it becomes turbopack://: vercel/turbo#8034

In the meantime, while we work on landing the change in VS Code, you can use a launch.json config that has Turbopack specific sourceMapPathOverrides.

E.g. I was able to attach the debugger using this config:

{
  // Use IntelliSense to learn about possible attributes.
  // Hover to view descriptions of existing attributes.
  // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Launch",
      "type": "node",
      "request": "launch",
      "cwd": "${workspaceFolder}",
      "runtimeExecutable": "npm",
      "runtimeArgs": ["run", "dev"],
      "skipFiles": ["<node_internals>/**"],
      "sourceMapPathOverrides": {
        "webpack:///./~/*": "${workspaceFolder}/node_modules/*",
        "webpack://?:*/*": "${workspaceFolder}/*",
        // Temporary Turbopack path
        "/turbopack/[project]/*": "${workspaceFolder}/*",
        // Eventual Turbopack path
        "turbopack://[project]/*": "${workspaceFolder}/*"
      }
    }
  ]
}

@timneutkens
Copy link
Member

As discussed above I've opened a PR on VS Code's JavaScript debugger extension: https://vercel.slack.com/archives/C06BW4K7XPT/p1713960193753119

@avianion
Copy link
Author

Hi @timneutkens

This launch config worked fine for me for the VScode debugger. Although your PR might make it better and easier for others.

  "configurations": [
    {
      "name": "Docker Nextjs Debug",
      "type": "node",
      "request": "attach",
      "address": "chat.lvh.me",
      "localRoot": "${workspaceFolder}",
      "remoteRoot": "/app",
      "sourceMaps": true,
      "cwd": "${workspaceFolder}",
      "port": 9230,
      "sourceMapPathOverrides": {
        "/turbopack/[project]/*": "${webRoot}/nextjs/*"
      }
    },

The debugger attaches perfectly fine. However, once attaching to one of the breakpoints, and being WITHIN a dynamic route, this error crops up repeatedly.

Exception has occurred: PageNotFoundError: Cannot find module for page: /chat/mQyUtnWCiXkS1pxm23Spp

This only happens on dynamic page routes, not regular page routes.

The source of the error is within this code

    if (!pagePath && pagesDir) {
        pagePath = await (0, _findpagefile.findPageFile)(pagesDir, normalizedPagePath, extensions, false);
    }
    if (pagePath !== null && pagesDir) {
        const pageUrl = (0, _ensureleadingslash.ensureLeadingSlash)((0, _removepagepathtail.removePagePathTail)((0, _normalizepathsep.normalizePathSep)(pagePath), {
            extensions
        }));
        return {
            filename: (0, _path.join)(pagesDir, pagePath),
            bundlePath: _path.posix.join("pages", (0, _normalizepagepath.normalizePagePath)(pageUrl)),
            page: _path.posix.normalize(pageUrl)
        };
    }
    if (page === "/_error") {
        return {
            filename: require.resolve("next/dist/pages/_error"),
            bundlePath: page,
            page: (0, _normalizepathsep.normalizePathSep)(page)
        };
    } else {
        throw new _utils1.PageNotFoundError(normalizedPagePath);

within next/dist/server/dev/on-demand-entry-handler.js

Here's the stack trace

 at findPagePathData (/app/nextjs/node_modules/next/dist/server/dev/on-demand-entry-handler.js:328:15)
    at async Object.ensurePage (/app/nextjs/node_modules/next/dist/server/dev/hot-reloader-turbopack.js:600:42)
    at async ensure (/app/nextjs/node_modules/next/dist/server/lib/router-utils/setup-dev-bundler.js:162:13)
    at async Object.getItem (/app/nextjs/node_modules/next/dist/server/lib/router-utils/filesystem.js:498:45)
    at async handleRoute (/app/nextjs/node_modules/next/dist/server/lib/router-utils/resolve-routes.js:266:36)
    at async resolveRoutes (/app/nextjs/node_modules/next/dist/server/lib/router-utils/resolve-routes.js:525:28)
    at async handleRequest (/app/nextjs/node_modules/next/dist/server/lib/router-server.js:211:96)
    at async requestHandlerImpl (/app/nextjs/node_modules/next/dist/server/lib/router-server.js:377:13)
    at async Server.requestListener (/app/nextjs/node_modules/next/dist/server/lib/start-server.js:141:13)

As you can see, it seems to be an issue with the turbopack hot reloader colliding with the debugger itself, and not being able to find the dynamic route.

I believe that this issue only occurs when the process is being debugged, however I could be wrong on this and it could be occuring anyway every time the page is hot reloaded.

Here is how the dynamic route is set up

import React from "react";
import { notFound } from "next/navigation";
import { FindAllChats } from "@/features/chat/chat-services/chat-service";
import { FindChatThreadByID } from "@/features/chat/chat-services/chat-thread-service";
import { ChatUI } from "@/features/chat/chat-ui/chat-ui";

export default async function Home({ params }: { params: { id: string } }) {
  const items = await FindAllChats(params.id);
  const threads = await FindChatThreadByID(params.id);

  if (threads.length === 0) {
    notFound();
  }

  const chatThread = threads[0];

  if (params.id !== chatThread.id) {
    return notFound();
  }

  return <ChatUI messages={items} chatThread={chatThread} />;
}

and the path is done like this nextjs/app/chat/[id]/page.tsx

The error basically makes us unable to use the vscode debugger in development mode with turbopack, specifically with dynamic routes.

@timneutkens
Copy link
Member

Thanks for the additional details, that clarifies a lot more. It seems you are using Docker but the dockerfile is not provided. Can you share the setup as I still can't be reproduced with the provided steps unfortunately.

Could you also clarify if you're actively on a breakpoint when you make changes to the file and then save or if it's something else?

@avianion
Copy link
Author

Thanks for your response @timneutkens . I am not saving the file at all. I am literally moving through the breakpoints as normal with the Vscode debugger.

Sometimes the error will appear before even hitting a breakpoint and sometimes after. The error will continuously occur then in a kind of loop until it triggers an issue with the jest worker, which basically nukes the Nextjs server and requires a restart. So basically, one error causes another and then when visiting any page, the app does not work on a development environment

Server Error

Error: Jest worker encountered 2 child process exceptions, exceeding retry limit
This error happened while generating the page. Any console logs will be displayed in the terminal window.
Call Stack
Next.js
ChildProcessWorker.initialize
file:/app/nextjs/node_modules/next/dist/compiled/jest-worker/index.js (1:11580)
ChildProcessWorker._onExit
file:/app/nextjs/node_modules/next/dist/compiled/jest-worker/index.js (1:12545)
ChildProcess.emit
node:events (518:28)
ChildProcess.emit
node:domain (488:12)

Here's the dockerfile

FROM node:20-alpine AS base

# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed.
RUN apk add --no-cache libc6-compat

# Set the working directory
WORKDIR /app/nextjs

# Rebuild the source code and install dependencies in a single stage
FROM base AS builder
WORKDIR /app/nextjs

# Copy package.json and package-lock.json
COPY package.json ./
COPY package-lock.json ./

# Install the dependencies
RUN npm install --force

# Copy the rest of the app files
COPY . .

# Dev image, copy all the files and run next
FROM base AS runner
WORKDIR /app/nextjs

# Copy node_modules from the builder stage
# COPY --from=builder /app/nextjs/node_modules ./node_modules
# Copy the rest of the app files from the builder stage
COPY --from=builder /app/nextjs/ .

# Set NODE_ENV to development
ENV NODE_ENV development

# Create user and group for security reasons
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
# Change ownership of the /app/nextjs directory to the nextjs user
# RUN chown -R nextjs:nodejs /app/nextjs

# USER nextjs

ENV PORT 3000
ENV HOSTNAME localhost


EXPOSE 3000

and the docker-compose.yaml

  nextjs:
    develop:
      watch:
        - action: sync
          path: ./nextjs
          target: /app/nextjs/

    build:
      context: ./nextjs
      dockerfile: ../compose/local/nextjs/Dockerfile
    image: avian_local_nextjs
    container_name: avian_local_nextjs
    env_file:
      - ./.envs/.local/.nextjs
    ports:
      - "3000:3000"
      - "9230:9230"
      - "9229:9229"
    # volumes:
    #   - ./nextjs/.next/:/app/nextjs/.next/:z
    command: npm run dev
    restart: always
    environment:
      - VIRTUAL_HOST=chat.lvh.me
      - VIRTUAL_PORT=3000

timneutkens added a commit that referenced this issue Apr 26, 2024
## What?

Ensures paths that have spaces in them in `NODE_OPTIONS` are handled. An
example of that is VS Code's debugger which adds:

```
--require "/Applications/Visual Studio Code.app/Contents/Resources/app/extensions/ms-vscode.js-debug/src/bootloader.js"
```

Currently the output is cut off and causes: `invalid value for
NODE_OPTIONS (unterminated string)`.

Related issue: #63740

<!-- 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 #

-->


Closes NEXT-3226

---------

Co-authored-by: Wyatt Johnson <accounts+github@wyattjoh.ca>
Co-authored-by: Ethan Arrowood <ethan@arrowood.dev>
@timneutkens
Copy link
Member

After landing #65046 on canary I was able to verify that it now correctly highlights the underlying error in the setup:

avian_local_nextjs  | Error: Cannot find module '/Applications/Visual Studio Code.app/Contents/Resources/app/extensions/ms-vscode.js-debug/src/bootloader.js'
avian_local_nextjs  | Require stack:
avian_local_nextjs  | - internal/preload
avian_local_nextjs  |     at Module._resolveFilename (node:internal/modules/cjs/loader:1143:15)
avian_local_nextjs  |     at Module._load (node:internal/modules/cjs/loader:984:27)
avian_local_nextjs  |     at internalRequire (node:internal/modules/cjs/loader:174:19)
avian_local_nextjs  |     at Module._preloadModules (node:internal/modules/cjs/loader:1574:5)
avian_local_nextjs  |     at loadPreloadModules (node:internal/process/pre_execution:723:5)
avian_local_nextjs  |     at setupUserModules (node:internal/process/pre_execution:203:5)
avian_local_nextjs  |     at prepareExecution (node:internal/process/pre_execution:159:5)
avian_local_nextjs  |     at prepareMainThreadExecution (node:internal/process/pre_execution:54:10)
avian_local_nextjs  |     at node:internal/main/run_main_module:11:19 {
avian_local_nextjs  |   code: 'MODULE_NOT_FOUND',
avian_local_nextjs  |   requireStack: [ 'internal/preload' ]
avian_local_nextjs  | }
avian_local_nextjs  | 

This happens regardless of using Turbopack or webpack. I couldn't find much information about this but the VS Code JS debugger adds --require "/Applications/Visual Studio Code.app/Contents/Resources/app/extensions/ms-vscode.js-debug/src/bootloader.js" to the NODE_OPTIONS but obviously this runs in Docker so it can't access my machine's Applications folder.

@avianion Could you try installing next@canary and running it to double check that is the same error that is causing the worker to crash?

@timneutkens
Copy link
Member

timneutkens commented Apr 26, 2024

Adding "autoAttachChildProcesses": false, to launch.json makes it work with webpack and Turbopack, also the sourceMapPathOverrides are still required. Will open a PR on the reproduction repository to show the changes:

"configurations": [
    {
      "name": "Docker Nextjs Debug",
      "type": "node",
      "request": "attach",
      // "address": "127.0.0.1",
      "localRoot": "${workspaceFolder}",
      "remoteRoot": "/app",
      "sourceMaps": true,
      "cwd": "${workspaceFolder}",
      "port": 9230,
      "autoAttachChildProcesses": false,
      "sourceMapPathOverrides": {
        "meteor://💻app/*": "${workspaceFolder}/*",
        "webpack:///./~/*": "${workspaceFolder}/node_modules/*",
        "webpack://?:*/*": "${workspaceFolder}/*",
        "/turbopack/[project]/*": "${workspaceFolder}/nextjs/*",
        "turbopack://[project]/*": "${workspaceFolder}/nextjs/*"
      }
    }
  ]

@avianion
Copy link
Author

I can confirm the crashing issue is fixed.

However, unfortuantely, I cannot get my debugger to bind anymore

Could not read source map for file:///app/nextjs/.next/server/chunks/ssr/[root%20of%20the%20server]__ef3759..js: ENOENT: no such file or directory, open 'c:\Users\dexim\Desktop\avian\nextjs.next\server\chunks\ssr[root of the server]__ef3759..js.map'

My source maps aren't loading, even with the exact config as above.

Which is bizzare.

@avianion
Copy link
Author

avianion commented Apr 27, 2024

image

Here's a screenshot of using the test repo and receiving the error where the source maps are not binding correctly.

Could not read source map for file:///app/nextjs/.next/server/chunks/ssr/node_modules_892a5a._.js: ENOENT: no such file or directory, open 'c:\Users\dexim\Desktop\nextjs-turbo-broken-dynamic-page-hot-reload-and-vscode-debugger-main\nextjs\.next\server\chunks\ssr\node_modules_892a5a._.js.map'
Could not read source map for file:///app/nextjs/.next/server/chunks/ssr/_0aa3de._.js: ENOENT: no such file or directory, open 'c:\Users\dexim\Desktop\nextjs-turbo-broken-dynamic-page-hot-reload-and-vscode-debugger-main\nextjs\.next\server\chunks\ssr\_0aa3de._.js.map'
Could not read source map for file:///app/nextjs/.next/server/chunks/ssr/node_modules_d26df3._.js: ENOENT: no such file or directory, open 'c:\Users\dexim\Desktop\nextjs-turbo-broken-dynamic-page-hot-reload-and-vscode-debugger-main\nextjs\.next\server\chunks\ssr\node_modules_d26df3._.js.map'
Could not read source map for file:///app/nextjs/.next/server/chunks/ssr/node_modules_d5ad6d._.js: ENOENT: no such file or directory, open 'c:\Users\dexim\Desktop\nextjs-turbo-broken-dynamic-page-hot-reload-and-vscode-debugger-main\nextjs\.next\server\chunks\ssr\node_modules_d5ad6d._.js.map'
Could not read source map for file:///app/nextjs/.next/server/chunks/ssr/_98535b._.js: ENOENT: no such file or directory, open 'c:\Users\dexim\Desktop\nextjs-turbo-broken-dynamic-page-hot-reload-and-vscode-debugger-main\nextjs\.next\server\chunks\ssr\_98535b._.js.map'

That's the error I'm getting. My launch.json is the same as yours.

For the record, I'm using Windows 11 - not sure if that makes a difference.

@timneutkens
Copy link
Member

Thanks for checking! Did some more digging and figured out why it was working for me but not for you, the volume wasn't being mounted: avianion/nextjs-turbo-broken-dynamic-page-hot-reload-and-vscode-debugger#4

With that change it does correctly stop at the breakpoints.

Could you verify that and let me know if it works? Thanks!

@timneutkens
Copy link
Member

@avianion checking in here, is this good to be closed?

@avianion
Copy link
Author

avianion commented May 1, 2024

Hi Tim. Give me a few hours to check on this and I will get back to you

@avianion
Copy link
Author

avianion commented May 1, 2024

npm ERR! code ERESOLVE
npm ERR! ERESOLVE unable to resolve dependency tree
npm ERR!
npm ERR! While resolving: avian-next-chat-app@0.1.0
npm ERR! Found: next@14.3.0-canary.34
npm ERR! node_modules/next
npm ERR! next@"14.3.0-canary.34" from the root project
npm ERR!
npm ERR! Could not resolve dependency:
npm ERR! peer next@"^10.0.8 || ^11.0 || ^12.0 || ^13.0 || ^14.0" from @sentry/nextjs@7.112.2
npm ERR! node_modules/@sentry/nextjs
npm ERR! @sentry/nextjs@"7.112.2" from the root project

optional bonus question (unrelated) how can I use a canary nextjs version with sentry nextjs package? it breaks every time i use a canary package.

@avianion
Copy link
Author

avianion commented May 1, 2024

so @timneutkens your fix worked, which is great. However the fix breaks my hot reload.

If you noticed in the original code, I was using the docker-compose watch in order to have the hot reload work. It was working fine before. Now I commented it out. So now I have the choice of hot reload working (or manually reloading the entire app) or using the debugger.

Hope that makes sense.

nextjs:
# develop:
# watch:
# - action: sync
# path: ./nextjs
# target: /app/nextjs/
# ignored_paths:
# - ./nextjs/.next/
# # Add any other directories you want to exclude from watching
build:
context: ./nextjs
dockerfile: ../compose/local/nextjs/Dockerfile
image: avian_local_nextjs
container_name: avian_local_nextjs
env_file:
- ./.envs/.local/.nextjs
ports:
- "3000:3000"
- "9230:9230"
- "9229:9229"
volumes:
- ./nextjs/.next/:/app/nextjs/.next/:z
command: npm run dev
restart: always
environment:
- VIRTUAL_HOST=chat.lvh.me
- VIRTUAL_PORT=3000
- "NODE_OPTIONS=--inspect=0.0.0.0:9229"

@avianion
Copy link
Author

avianion commented May 2, 2024

@timneutkens @sokra Thanks so much for the help. using a volume mount with docker-compose watch fixed the hot reload issue.

So I guess everything is working now. Great job. Closing this.

@avianion avianion closed this as completed May 2, 2024
@timneutkens
Copy link
Member

Thanks for checking! Glad it's resolved now 🙏

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Issue was opened via the bug report template. linear: turbopack Confirmed issue that is tracked by the Turbopack team. Turbopack Related to Turbopack with Next.js.
Projects
None yet
Development

No branches or pull requests

4 participants