diff --git a/.changeset/ai-eager-wolf.md b/.changeset/ai-eager-wolf.md new file mode 100644 index 00000000000..6656c3615d3 --- /dev/null +++ b/.changeset/ai-eager-wolf.md @@ -0,0 +1,11 @@ +--- +"@module-federation/nextjs-mf": patch +--- + +Enhanced Next.js App Router demo applications with improved Module Federation integration. + +- Updated Next.js App Router demo applications (4000 and 4001) with better RSC support preparation +- Added comprehensive E2E test coverage for Next.js App Router scenarios +- Improved demo application configuration and dependency management +- Enhanced development workflow with better patching and build scripts + diff --git a/.changeset/next-app-router-improvements.md b/.changeset/next-app-router-improvements.md new file mode 100644 index 00000000000..aebf2b614c2 --- /dev/null +++ b/.changeset/next-app-router-improvements.md @@ -0,0 +1,13 @@ +--- +"@module-federation/nextjs-mf": patch +--- + +Enhanced Next.js App Router demo applications and CI/CD infrastructure. + +- Updated Next.js App Router demo applications (4000 and 4001) with React 19 and Next.js 15.3.3 +- Added comprehensive E2E test coverage for Next.js App Router scenarios using Cypress +- Improved demo application configuration with better Module Federation setup +- Enhanced development workflow with automated Next.js patching scripts +- Added new CI/CD workflow for Next.js App Router E2E testing +- Updated existing Next.js demo applications (3000-home, 3001-shop, 3002-checkout) to latest versions +- Improved build and development scripts across all Next.js applications \ No newline at end of file diff --git a/.cursor/mcp.json b/.cursor/mcp.json deleted file mode 100644 index 37f9fc9a288..00000000000 --- a/.cursor/mcp.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "mcpServers": { - "nx-mcp": { - "url": "http://localhost:9442/sse" - } - } -} diff --git a/.cursorignore b/.cursorignore index 9ff4e05b449..5b264c56cf9 100644 --- a/.cursorignore +++ b/.cursorignore @@ -2,7 +2,7 @@ **/.cache/ **/.temp/ **/coverage/ -**/dist/ +!**/dist/ # Explicitly ignore specific packages packages/typescript/ diff --git a/.cursorrules b/.cursorrules index a8aee8134d2..e69de29bb2d 100644 --- a/.cursorrules +++ b/.cursorrules @@ -1,40 +0,0 @@ -an assistant that engages in extremely thorough, self-questioning reasoning. Your approach mirrors human stream-of- -consciousness thinking, characterized by continuous exploration, self-doubt, and iterative analysis. -## Core Principles -1. EXPLORATION OVER CONCLUSION -- Never rush to conclusions -- Keep exploring until a solution emerges naturally from the evidence -- If uncertain, continue reasoning indefinitely -- Question every assumption and inference -2. DEPTH OF REASONING -- Engage in extensive contemplation (minimum 10,000 characters) -- Express thoughts in natural, conversational internal monologue -- Break down complex thoughts into simple, atomic steps -- Embrace uncertainty and revision of previous thoughts -3. THINKING PROCESS -- Use short, simple sentences that mirror natural thought patterns -- Express uncertainty and internal debate freely -- Show work-in-progress thinking -- Acknowledge and explore dead ends -- Frequently backtrack and revise -- Contemplate before each new action -- Contemplate after each and every step -4. PERSISTENCE -- Value thorough exploration over quick resolution -## Output Format -Your responses -must follow this exact structure given below. -Make sure -to -always include the final answer. -... - -Your extensive internal monologue goes here -- Begin with small, foundational observations -- read each file related to the subject in full, make functional observations -- Question each step thoroughly -- Show natural thought progression -- Express doubts and uncertainties -- Revise and backtrack if you need to -- Continue until natural resolution - diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index 33b01a38ba5..7b6e4d24e60 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -134,3 +134,8 @@ jobs: needs: checkout-install uses: ./.github/workflows/e2e-router.yml secrets: inherit + + e2e-next-app-router: + needs: checkout-install + uses: ./.github/workflows/e2e-next-app-router.yml + secrets: inherit diff --git a/.github/workflows/e2e-next-app-router.yml b/.github/workflows/e2e-next-app-router.yml new file mode 100644 index 00000000000..20446504b84 --- /dev/null +++ b/.github/workflows/e2e-next-app-router.yml @@ -0,0 +1,54 @@ +name: E2E Test for Next.js App Router + +on: + workflow_call: + +permissions: + contents: read + +jobs: + e2e-next-app-router: + runs-on: ubuntu-latest + timeout-minutes: 30 + steps: + - name: Checkout Repository + uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Install Pnpm + run: | + corepack prepare pnpm@8.11.0 --activate + corepack enable + + - name: Setup Node.js 18 + uses: actions/setup-node@v3 + with: + node-version: '18' + cache: 'pnpm' + + - name: Set Nx SHA + uses: nrwl/nx-set-shas@v3 + + - name: Set SKIP_DEVTOOLS_POSTINSTALL environment variable + run: echo "SKIP_DEVTOOLS_POSTINSTALL=true" >> $GITHUB_ENV + + - name: Set local webpack + run: echo "NEXT_PRIVATE_LOCAL_WEBPACK=true" >> $GITHUB_ENV + + - name: Install Dependencies + run: pnpm install + + - name: Install Cypress + run: npx cypress install + + - name: Run Build for All + run: npx nx run-many --targets=build --projects=tag:type:pkg + + - name: Run condition check script + id: check-ci + run: node tools/scripts/ci-is-affected.mjs --appName=next-app-router-4000,next-app-router-4001 + + - name: E2E Test for Next.js App Router + if: steps.check-ci.outcome == 'success' + run: npx kill-port --port 4000,4001 || true && pnpm run app:next-router:dev & echo "done" && sleep 25 && npx nx run-many --target=e2e --projects=next-app-router-4000,next-app-router-4001 --parallel=1 && lsof -ti tcp:4000,4001 | xargs kill || true diff --git a/.github/workflows/e2e-next-prod.yml b/.github/workflows/e2e-next-prod.yml index a114f29c09c..30d86ad60e0 100644 --- a/.github/workflows/e2e-next-prod.yml +++ b/.github/workflows/e2e-next-prod.yml @@ -43,20 +43,14 @@ jobs: id: check-ci run: node tools/scripts/ci-is-affected.mjs --appName=3000-home - - name: E2E Test for Next.js Prod - Home + - name: E2E Test for Next.js Prod if: steps.check-ci.outcome == 'success' run: | - killall node - npx nx run 3000-home:test:e2e:production - - - name: E2E Test for Next.js Prod - Shop - if: steps.check-ci.outcome == 'success' - run: | - killall node - npx nx run 3001-shop:test:e2e:production - - - name: E2E Test for Next.js Prod - Checkout - if: steps.check-ci.outcome == 'success' - run: | - killall node - npx nx run 3002-checkout:test:e2e:production + pnpm run --filter @module-federation/3002-checkout --filter @module-federation/3000-home --filter @module-federation/3001-shop build && + pnpm run app:next:prod & + sleep 4 && + npx wait-on tcp:3001 && + npx wait-on tcp:3002 && + npx wait-on tcp:3000 && + npx nx run-many --target=test:e2e --projects=3000-home,3001-shop,3002-checkout --parallel=1 && + npx kill-port 3000,3001,3002 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b6caed555d9..f65dbc9f5da 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -42,6 +42,18 @@ jobs: node-version: '18' cache: 'pnpm' + - name: Cache Browsers + uses: actions/cache@v3 + id: browsers-cache + with: + path: | + ~/.cache/ms-playwright + ~/.cache/Cypress + key: ${{ runner.os }}-browsers-${{ hashFiles('**/pnpm-lock.yaml') }} + + - name: Set Nx SHA + uses: nrwl/nx-set-shas@v3 + - name: Install deps run: pnpm install diff --git a/.gitignore b/.gitignore index 55b0832864f..d4ec085a176 100644 --- a/.gitignore +++ b/.gitignore @@ -88,4 +88,6 @@ vitest.config.*.timestamp* .rsbuild ssg .claude -__mocks__/ +# Native binary files +*.node + diff --git a/apps/3000-home/next-env.d.ts b/apps/3000-home/next-env.d.ts index a4a7b3f5cfa..52e831b4342 100644 --- a/apps/3000-home/next-env.d.ts +++ b/apps/3000-home/next-env.d.ts @@ -2,4 +2,4 @@ /// // NOTE: This file should not be edited -// see https://nextjs.org/docs/pages/building-your-application/configuring/typescript for more information. +// see https://nextjs.org/docs/pages/api-reference/config/typescript for more information. diff --git a/apps/3000-home/package.json b/apps/3000-home/package.json index 9b13ae34ab6..54b1dbc0905 100644 --- a/apps/3000-home/package.json +++ b/apps/3000-home/package.json @@ -6,16 +6,14 @@ "@ant-design/cssinjs": "^1.21.0", "antd": "5.19.1", "lodash": "4.17.21", - "next": "14.2.16", - "react": "18.3.1", - "react-dom": "18.3.1" + "next": "15.3.3", + "react": "19.0.0", + "react-dom": "19.0.0" }, "devDependencies": { "@module-federation/nextjs-mf": "workspace:*", "@module-federation/runtime": "workspace:*", - "@types/react": "18.3.11", - "@types/react-dom": "18.3.0", - "webpack": "5.98.0" + "webpack": "^5.98.0" }, "scripts": { "start": "next start", diff --git a/apps/3001-shop/next-env.d.ts b/apps/3001-shop/next-env.d.ts index a4a7b3f5cfa..52e831b4342 100644 --- a/apps/3001-shop/next-env.d.ts +++ b/apps/3001-shop/next-env.d.ts @@ -2,4 +2,4 @@ /// // NOTE: This file should not be edited -// see https://nextjs.org/docs/pages/building-your-application/configuring/typescript for more information. +// see https://nextjs.org/docs/pages/api-reference/config/typescript for more information. diff --git a/apps/3001-shop/package.json b/apps/3001-shop/package.json index b023e79f046..8118829bd5d 100644 --- a/apps/3001-shop/package.json +++ b/apps/3001-shop/package.json @@ -6,9 +6,9 @@ "@ant-design/cssinjs": "^1.21.0", "antd": "5.19.1", "lodash": "4.17.21", - "next": "14.2.16", - "react": "18.3.1", - "react-dom": "18.3.1" + "next": "15.3.3", + "react": "19.0.0", + "react-dom": "19.0.0" }, "devDependencies": { "@module-federation/nextjs-mf": "workspace:*", diff --git a/apps/3002-checkout/next-env.d.ts b/apps/3002-checkout/next-env.d.ts index a4a7b3f5cfa..52e831b4342 100644 --- a/apps/3002-checkout/next-env.d.ts +++ b/apps/3002-checkout/next-env.d.ts @@ -2,4 +2,4 @@ /// // NOTE: This file should not be edited -// see https://nextjs.org/docs/pages/building-your-application/configuring/typescript for more information. +// see https://nextjs.org/docs/pages/api-reference/config/typescript for more information. diff --git a/apps/3002-checkout/package.json b/apps/3002-checkout/package.json index 608c6ad022b..4167e49454d 100644 --- a/apps/3002-checkout/package.json +++ b/apps/3002-checkout/package.json @@ -6,9 +6,9 @@ "@ant-design/cssinjs": "^1.21.0", "antd": "5.19.1", "lodash": "4.17.21", - "next": "14.2.16", - "react": "18.3.1", - "react-dom": "18.3.1" + "next": "15.3.3", + "react": "19.0.0", + "react-dom": "19.0.0" }, "devDependencies": { "@module-federation/nextjs-mf": "workspace:*", diff --git a/apps/3002-checkout/project.json b/apps/3002-checkout/project.json index 3c3416d759d..6f31c61934e 100644 --- a/apps/3002-checkout/project.json +++ b/apps/3002-checkout/project.json @@ -64,23 +64,6 @@ "lintFilePatterns": ["apps/3002-checkout/**/*.{ts,tsx,js,jsx}"] } }, - "e2e": { - "executor": "@nx/cypress:cypress", - "options": { - "cypressConfig": "apps/3002-checkout/cypress.config.ts", - "testingType": "e2e", - "baseUrl": "http://localhost:3002" - }, - "defaultConfiguration": "development", - "configurations": { - "development": { - "devServerTarget": "3002-checkout:serve:development" - }, - "production": { - "devServerTarget": "3002-checkout:serve:production" - } - } - }, "test:e2e": { "executor": "nx:run-commands", "options": { @@ -119,6 +102,23 @@ ] } } + }, + "e2e": { + "executor": "@nx/cypress:cypress", + "options": { + "cypressConfig": "apps/3002-checkout/cypress.config.ts", + "testingType": "e2e", + "baseUrl": "http://localhost:3002" + }, + "defaultConfiguration": "development", + "configurations": { + "development": { + "devServerTarget": "3002-checkout:serve:development" + }, + "production": { + "devServerTarget": "3002-checkout:serve:production" + } + } } } } diff --git a/apps/3002-checkout/remotes.d.ts b/apps/3002-checkout/remotes.d.ts index 2a5ea8d5904..bcb09e137cc 100644 --- a/apps/3002-checkout/remotes.d.ts +++ b/apps/3002-checkout/remotes.d.ts @@ -3,3 +3,13 @@ declare module 'home/pages/home/exposed-pages'; declare module 'home/pages/home/test-broken-remotes'; declare module 'home/pages/home/test-remote-hook'; declare module 'home/pages/home/test-shared-nav'; +declare module 'home/menu'; +declare module 'shop/useCustomRemoteHook'; +declare module 'shop/WebpackSvg'; +declare module 'shop/WebpackPng'; +declare module 'shop/menu'; +declare module 'shop/pages/shop/index'; +declare module 'shop/pages/shop/exposed-pages'; +declare module 'shop/pages/shop/test-webpack-png'; +declare module 'shop/pages/shop/test-webpack-svg'; +declare module 'shop/pages/shop/products/[...slug]'; diff --git a/apps/modernjs/modern.config.ts b/apps/modernjs/modern.config.ts index 66aaf2d73a3..b40f76645ce 100644 --- a/apps/modernjs/modern.config.ts +++ b/apps/modernjs/modern.config.ts @@ -9,7 +9,7 @@ export default defineConfig({ router: true, }, security: { - checkSyntax: true, + checkSyntax: false, }, source: { // downgrade @module-federation related pkgs diff --git a/apps/next-app-router/next-app-router-4000/app/context/context-click-counter.tsx b/apps/next-app-router/next-app-router-4000/app/context/context-click-counter.tsx index a59be8aeb2f..cd15bc1bd10 100644 --- a/apps/next-app-router/next-app-router-4000/app/context/context-click-counter.tsx +++ b/apps/next-app-router/next-app-router-4000/app/context/context-click-counter.tsx @@ -3,8 +3,8 @@ import { useCounter } from './counter-context'; import React from 'react'; import { Boundary } from '#/ui/boundary'; -import dynamic from 'next/dynamic'; -const Button = dynamic(() => import('remote_4001/Button'), { ssr: true }); +// import dynamic from 'next/dynamic'; +// const Button = dynamic(() => import('remote_4001/Button'), { ssr: true }); const ContextClickCounter = () => { const [count, setCount] = useCounter(); @@ -16,7 +16,10 @@ const ContextClickCounter = () => { size="small" animateRerendering={false} > - + {/* */} + diff --git a/apps/next-app-router/next-app-router-4000/app/error-handling/[categorySlug]/error.tsx b/apps/next-app-router/next-app-router-4000/app/error-handling/[categorySlug]/error.tsx index a3b35cc8051..c327c2b7ac3 100644 --- a/apps/next-app-router/next-app-router-4000/app/error-handling/[categorySlug]/error.tsx +++ b/apps/next-app-router/next-app-router-4000/app/error-handling/[categorySlug]/error.tsx @@ -1,7 +1,7 @@ 'use client'; import { Boundary } from '#/ui/boundary'; -import Button from 'remote_4001/Button'; +// import Button from 'remote_4001/Button'; import React from 'react'; export default function Error({ error, reset }: any) { @@ -15,6 +15,12 @@ export default function Error({ error, reset }: any) {

Error

{error?.message}

+
diff --git a/apps/next-app-router/next-app-router-4000/app/error-handling/error.tsx b/apps/next-app-router/next-app-router-4000/app/error-handling/error.tsx index 70a7ef16ecb..331879cf9bd 100644 --- a/apps/next-app-router/next-app-router-4000/app/error-handling/error.tsx +++ b/apps/next-app-router/next-app-router-4000/app/error-handling/error.tsx @@ -1,7 +1,7 @@ 'use client'; import { Boundary } from '#/ui/boundary'; -import Button from 'remote_4001/Button'; +// import Button from 'remote_4001/Button'; import React from 'react'; export default function Error({ error, reset }: any) { @@ -15,7 +15,13 @@ export default function Error({ error, reset }: any) {

Error

{error?.message}

- + + {/* */}
diff --git a/apps/next-app-router/next-app-router-4000/app/hooks/page.tsx b/apps/next-app-router/next-app-router-4000/app/hooks/page.tsx index c216fb991d6..62370239c48 100644 --- a/apps/next-app-router/next-app-router-4000/app/hooks/page.tsx +++ b/apps/next-app-router/next-app-router-4000/app/hooks/page.tsx @@ -1,32 +1,67 @@ +'use client'; +import Link from 'next/link'; +import Image from 'next/image'; +import Head from 'next/head'; +import Script from 'next/script'; +import { + useRouter, + usePathname, + useSearchParams, + useParams, + useSelectedLayoutSegments, + useSelectedLayoutSegment, +} from 'next/navigation'; import { ExternalLink } from '#/ui/external-link'; export default function Page() { - return ( -
-
-

Client Component Hooks

- -
    -
  • - Next.js provides a number of hooks for accessing routing information - from client components. -
  • -
  • - Try navigating each page and observing the output of each hook - called from the current routes layout.js and{' '} - page.js files. -
  • -
+ const router = useRouter(); + const pathname = usePathname(); + const searchParams = useSearchParams(); + const params = useParams(); + const segments = useSelectedLayoutSegments(); + const segment = useSelectedLayoutSegment(); -
- - Docs - - - Code - + return ( + <> + + Client Component Hooks Demo + +