-
Notifications
You must be signed in to change notification settings - Fork 4
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
Migrate from Next.js Pages Router to App Router #255
Conversation
…-migration # Conflicts: # app/.eslintrc.js # app/.storybook/preview.tsx # app/next.config.js # app/package-lock.json # app/package.json # app/src/components/Header.tsx # app/src/components/Layout.tsx # app/src/pages/_app.tsx # app/src/pages/health.tsx # app/src/pages/index.tsx # app/src/types/i18n.d.ts # app/tests/app/page.test.tsx # app/tests/components/Header.test.tsx # app/tests/components/Layout.test.tsx # app/tests/jest-i18n.ts
# Conflicts: # app/.storybook/I18nStoryWrapper.tsx # app/.storybook/preview.tsx # app/README.md # app/next.config.js # app/src/app/[locale]/page.tsx # app/src/i18n/config.ts # app/src/i18n/getMessagesWithFallbacks.ts # app/src/pages/_app.tsx # app/tests/react-utils.tsx # docs/internationalization.md
app/next-env.d.ts
Outdated
@@ -1,5 +1,6 @@ | |||
/// <reference types="next" /> | |||
/// <reference types="next/image-types/global" /> | |||
/// <reference types="next/navigation-types/compat/navigation" /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ℹ️ Automatically added by Next.js when using App Router
{ | ||
"name": "next" | ||
} | ||
] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ℹ️ Automatically added by Next.js when using App Router
…-migration # Conflicts: # app/package-lock.json # app/package.json # app/src/app/[locale]/page.tsx # app/tests/app/page.test.tsx
⛔ I'm going to move this back into a Draft state. I encountered a blocker that is making me reconsider whether it's still too soon to migrate to React Server Components (AKA App Router). ContextThe main benefit of using App Router is to use React Server Components (RSC), which are a new feature. First, it may be helpful to provide context on the RSC and Next.js release timeline so far, and my thinking for when it felt appropriate to finally perform a migration:
Blockers and concernsWith server actions now stable, and an entire year for teams to kick the tires of server components, it appeared like things were in a better place for the Nava template to finally migrate to the App Router architecture. For the most part, I think that's still true, but one thing this migration PR has surfaced is that not all tooling in the React ecosystem has made the jump.
Given the above, I'm leaning towards continuing to hold off on migrating to the App Router. I think the following need to happen before we reconsider:
My personal preference would be to continue to have the ability to test within Jest since these tests are often faster and don't require running the entire application. |
…-migration # Conflicts: # app/README.md # app/src/app/[locale]/page.tsx # app/src/components/Layout.tsx # app/src/pages/health.tsx
Hey @sawyerh! Thanks for writing this up 😄 Your timeline seems accurate. I wanted to share some other thoughts.
Redwood and Remix are also moving in the RSC direction. Here's Redwoods notes. There's other more experimental frameworks like Waku being released.
We hope to continue to improve our testing docs and examples here for unit, integration, and E2E test. We also have this RFC open around testing.
I wanted to mention that, while this isn't the most ideal state, it's also (IMO) still an improvement over the Pages Router. For example, you getting streaming SSR by default, which is very powerful. I made a video about this here.
All of the existing caching work is stable and functional. We just want to improve the DX further. There will be smooth migrations from the existing DX today and possibly some simplified ways of authoring code around caching when ready. We will share more details and plans are figured out. But that doesn't mean it's unstable today! Hope this helps 🙏 |
@leerob Really appreciate you jumping in here to add more context, thank you. After posting this last night and sharing with colleagues, I think we've identified a way to move forwards with a migration to App Router and decouple "controller" and "view" logic and unit test async server components with mocked external services, similar to how we were testing |
@leerob @delbaoliveira Feel free to ignore me here, but wanted to follow-up on my previous comment. Seems like the original pattern we were thinking is currently prevented by the Next.js TypeScript plugin. Added a comment to this existing Next.js issue with more context. |
@@ -0,0 +1,3 @@ | |||
export default function Page() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is the /health/ page an aspect of next.js that's built in to handle some particular functionality? I couldn't find it looking in the docs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My understanding is it's required by the infra template in order to know if the container is healthy, otherwise it spins up a new ECS task.
locale: string; | ||
} | ||
|
||
export async function generateMetadata({ params }: { params: RouteParams }) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe overkill, but do you think worth linking to this section of the docs? https://nextjs.org/docs/app/api-reference/functions/generate-metadata
I imagine we don't want to reference for everything, but was wondering if for things that are new for server components (which many folks may be less familiar with at first) it could help 🤷♀️
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good question. I have a follow-up ticket where I want to add more docs so will fold code comments into that scope since I think it relates. #262
@@ -1,3 +1,5 @@ | |||
"use client"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to use client here b/ c the truss stuff?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This component uses useState
for hiding/showing the mobile menu
|
||
describe("Index", () => { | ||
describe("Index - Controller", () => { | ||
it("retrieves feature flags", async () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✨
render(<View isFooEnabled />); | ||
expect(screen.getByText(enabledFlagTextMatcher)).toBeInTheDocument(); | ||
|
||
cleanup(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was wondering how to do this before and couldn't find the cleanup function! Nice to see this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might it make sense to rename the top-level folder from app
to something else? It's a bit confusing (especially if someone might be new to the repo or to the concepts of the App Router) to have multiple folders w/ that pseudo-magic app
name?
@jcq I had a similar question in the spec's Open Questions, and there's some discussion there. I was going to leave it as is for now since the infra template expects |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking good — all things about which I had questions can be addressed later in follow-up discussions!
Ticket
Resolves #66
Changes
This is purely an architecture migration and nothing functionally should have changed.
Pages Router → App Router:
pages/_app.tsx
→app/[locale]/layout.tsx
pages/index.tsx
→app/[locale]/page.tsx
pages/health.tsx
→app/[locale]/health/page.tsx
pages/api/hello.ts
→app/api/hello/route.tsx
Internationalized routing and locale detection:
App Router doesn't include built-in support for internationalized routing and locale detection like Pages Router.
src/middleware.ts
) to detect and store the user's preferred language, and routing them to/es-US/*
when their preferred language is Spanishi18n/server.ts
to contain server-side configuration for thenext-intl
plugin. This makes locale strings available to all server componentsContext for reviewers
view.tsx
exists instead of that component being colocated in thepage.tsx
file. More context on this Next.js issue.Testing