vercel / next.js

The React Framework
https://nextjs.org
MIT License
126.87k stars 26.97k forks source link

Export to SPA with App Router and useContext #52448

Closed hamidmayeli closed 1 year ago

hamidmayeli commented 1 year ago

Verify canary release

Provide environment information

Operating System:
      Platform: win32
      Arch: x64
      Version: Windows 10 Pro
    Binaries:
      Node: 20.3.1
      npm: N/A
      Yarn: N/A
      pnpm: N/A
    Relevant Packages:
      next: 13.4.10-canary.0
      eslint-config-next: 13.4.9
      react: 18.2.0
      react-dom: 18.2.0
      typescript: 5.1.6
    Next.js Config:
      output: export

Which area(s) of Next.js are affected? (leave empty if unsure)

Static HTML Export (output: "export")

Link to the code that reproduces this issue or a replay of the bug

https://github.com/hamidmayeli/nextjs-spa-issue

To Reproduce

I have created a new project using `create-next-app@13.4.9` with default settings. ```bash create-next-app@13.4.9 Ok to proceed? (y) √ What is your project named? ... nextjs-issue √ Would you like to use TypeScript? ... No / Yes √ Would you like to use ESLint? ... No / Yes √ Would you like to use Tailwind CSS? ... No / Yes √ Would you like to use `src/` directory? ... No / Yes √ Would you like to use App Router? (recommended) ... No / Yes √ Would you like to customize the default import alias? ... No / Yes Creating a new Next.js app in C:\PD\nextjs-issue. ```
Then I have set the `output` to `export` ```ts /** @type {import("next").NextConfig} */ const nextConfig = { output: "export", }; module.exports = nextConfig; ```

After that I have created a component outside the app folder to separate the context logic from the layout.

The AppContext ```ts import { createContext, useState, useMemo, useCallback } from "react"; interface ICurrentUser { token?: string } export const AppContext = createContext({} as { currentUser?: ICurrentUser, login: (user: ICurrentUser) => void, }); const userStorageKey = "key"; export default function AppContextProvider({ children, }: { children: React.ReactNode }) { const [currentUser, setCurrentUser] = useState(JSON.parse(localStorage.getItem(userStorageKey) ?? "{}") as ICurrentUser); const login = useCallback((user: ICurrentUser) => { localStorage.setItem(userStorageKey, JSON.stringify(user)); setCurrentUser(user); }, []); const contextValue = useMemo(() => ({ currentUser, login, }), [currentUser, login]); return ( {children} ); } ```

Then I use this the app context in layout wrapping the body.

The layout ```tsx "use client"; import AppContextProvider from '@/components/appContext' import './globals.css' // import type { Metadata } from 'next' // import { Inter } from 'next/font/google' // const inter = Inter({ subsets: ['latin'] }) // export const metadata: Metadata = { // title: 'Create Next App', // description: 'Generated by create next app', // } export default function RootLayout({ children, }: { children: React.ReactNode }) { return ( {children} ) } ```

Describe the Bug

When I try to build the project, all pages (with this example Home) are causing issue. Because compiler tries to pre-render this page while in the AppContext I am accessing localStorage.

Expected Behavior

I expect to see the pages are turned into JS files and have an exported output.

Which browser are you using? (if relevant)

No response

How are you deploying your application? (if relevant)

npm run build

Fredkiss3 commented 1 year ago

client components are still prerendered on the server so your app context will render on the server and since localStorage do not exist on the server you will have an error. If you want to opt-out of prerendering, you can use next/dynamic with SSR (prerendering) disabled.

Something like this :

"use client";

import dynamic from 'next/dynamic'
import './globals.css'
// import type { Metadata } from 'next'
// import { Inter } from 'next/font/google'

// const inter = Inter({ subsets: ['latin'] })

// export const metadata: Metadata = {
//   title: 'Create Next App',
//   description: 'Generated by create next app',
// }
const AppContextProvider = dynamic(() => import('@/components/appContext'), { ssr: false })

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en">
      <AppContextProvider>
        <body>{children}</body>
      </AppContextProvider>
    </html>
  )
}

more info in the docs : https://nextjs.org/docs/app/building-your-application/optimizing/lazy-loading#skipping-ssr

hamidmayeli commented 1 year ago

Thank you @Fredkiss3, I have applied the suggestion and I can confirm that it builds. But when I run it for dev (npm run dev) I am facing with the following logs in the browser and it shows nothing in the page.

navigation.js:136  Uncaught Error: invariant expected app router to be mounted
    at useRouter (webpack-internal:///(:3000/app-client)/./node_modules/next/dist/client/components/navigation.js:118:15)
    at HotReload (webpack-internal:///(:3000/app-client)/./node_modules/next/dist/client/components/react-dev-overlay/hot-reloader-client.js:396:46)
    at renderWithHooks (webpack-internal:///(:3000/app-client)/./node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js:10697:18)
    at mountIndeterminateComponent (webpack-internal:///(:3000/app-client)/./node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js:15735:13)
    at beginWork$1 (webpack-internal:///(:3000/app-client)/./node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js:17310:16)
    at HTMLUnknownElement.callCallback (webpack-internal:///(:3000/app-client)/./node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js:19443:14)
    at Object.invokeGuardedCallbackImpl (webpack-internal:///(:3000/app-client)/./node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js:19492:16)
    at invokeGuardedCallback (webpack-internal:///(:3000/app-client)/./node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js:19567:29)
    at beginWork (webpack-internal:///(:3000/app-client)/./node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js:25711:7)
    at performUnitOfWork (webpack-internal:///(:3000/app-client)/./node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js:24540:12)
    at workLoopSync (webpack-internal:///(:3000/app-client)/./node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js:24256:5)
    at renderRootSync (webpack-internal:///(:3000/app-client)/./node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js:24211:7)
    at performConcurrentWorkOnRoot (webpack-internal:///(:3000/app-client)/./node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js:23339:74)
    at workLoop (webpack-internal:///(:3000/app-client)/./node_modules/next/dist/compiled/scheduler/cjs/scheduler.development.js:261:34)
    at flushWork (webpack-internal:///(:3000/app-client)/./node_modules/next/dist/compiled/scheduler/cjs/scheduler.development.js:230:14)
    at MessagePort.performWorkUntilDeadline (webpack-internal:///(:3000/app-client)/./node_modules/next/dist/compiled/scheduler/cjs/scheduler.development.js:537:21)
useRouter @ navigation.js:136
HotReload @ hot-reloader-client.js:413
renderWithHooks @ react-dom.development.js:10697
mountIndeterminateComponent @ react-dom.development.js:15735
beginWork$1 @ react-dom.development.js:17310
callCallback @ react-dom.development.js:19443
invokeGuardedCallbackImpl @ react-dom.development.js:19492
invokeGuardedCallback @ react-dom.development.js:19567
beginWork @ react-dom.development.js:25711
performUnitOfWork @ react-dom.development.js:24540
workLoopSync @ react-dom.development.js:24256
renderRootSync @ react-dom.development.js:24211
performConcurrentWorkOnRoot @ react-dom.development.js:23339
workLoop @ scheduler.development.js:261
flushWork @ scheduler.development.js:230
performWorkUntilDeadline @ scheduler.development.js:537
navigation.js:136  Uncaught Error: invariant expected app router to be mounted
    at useRouter (webpack-internal:///(:3000/app-client)/./node_modules/next/dist/client/components/navigation.js:118:15)
    at HotReload (webpack-internal:///(:3000/app-client)/./node_modules/next/dist/client/components/react-dev-overlay/hot-reloader-client.js:396:46)
    at renderWithHooks (webpack-internal:///(:3000/app-client)/./node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js:10697:18)
    at mountIndeterminateComponent (webpack-internal:///(:3000/app-client)/./node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js:15735:13)
    at beginWork$1 (webpack-internal:///(:3000/app-client)/./node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js:17310:16)
    at HTMLUnknownElement.callCallback (webpack-internal:///(:3000/app-client)/./node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js:19443:14)
    at Object.invokeGuardedCallbackImpl (webpack-internal:///(:3000/app-client)/./node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js:19492:16)
    at invokeGuardedCallback (webpack-internal:///(:3000/app-client)/./node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js:19567:29)
    at beginWork (webpack-internal:///(:3000/app-client)/./node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js:25711:7)
    at performUnitOfWork (webpack-internal:///(:3000/app-client)/./node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js:24540:12)
    at workLoopSync (webpack-internal:///(:3000/app-client)/./node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js:24256:5)
    at renderRootSync (webpack-internal:///(:3000/app-client)/./node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js:24211:7)
    at recoverFromConcurrentError (webpack-internal:///(:3000/app-client)/./node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js:23446:20)
    at performConcurrentWorkOnRoot (webpack-internal:///(:3000/app-client)/./node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js:23352:22)
    at workLoop (webpack-internal:///(:3000/app-client)/./node_modules/next/dist/compiled/scheduler/cjs/scheduler.development.js:261:34)
    at flushWork (webpack-internal:///(:3000/app-client)/./node_modules/next/dist/compiled/scheduler/cjs/scheduler.development.js:230:14)
    at MessagePort.performWorkUntilDeadline (webpack-internal:///(:3000/app-client)/./node_modules/next/dist/compiled/scheduler/cjs/scheduler.development.js:537:21)
useRouter @ navigation.js:136
HotReload @ hot-reloader-client.js:413
renderWithHooks @ react-dom.development.js:10697
mountIndeterminateComponent @ react-dom.development.js:15735
beginWork$1 @ react-dom.development.js:17310
callCallback @ react-dom.development.js:19443
invokeGuardedCallbackImpl @ react-dom.development.js:19492
invokeGuardedCallback @ react-dom.development.js:19567
beginWork @ react-dom.development.js:25711
performUnitOfWork @ react-dom.development.js:24540
workLoopSync @ react-dom.development.js:24256
renderRootSync @ react-dom.development.js:24211
recoverFromConcurrentError @ react-dom.development.js:23446
performConcurrentWorkOnRoot @ react-dom.development.js:23352
workLoop @ scheduler.development.js:261
flushWork @ scheduler.development.js:230
performWorkUntilDeadline @ scheduler.development.js:537
app-index.js:31  The above error occurred in the <HotReload> component:

    at HotReload (webpack-internal:///(app-client)/./node_modules/next/dist/client/components/react-dev-overlay/hot-reloader-client.js:318:11)

Consider adding an error boundary to your tree to customize error handling behavior.
Visit https://reactjs.org/link/error-boundaries to learn more about error boundaries.
window.console.error @ app-index.js:31
logCapturedError @ react-dom.development.js:14124
update.callback @ react-dom.development.js:14150
callCallback @ react-dom.development.js:7892
commitCallbacks @ react-dom.development.js:7939
commitLayoutEffectOnFiber @ react-dom.development.js:20339
commitLayoutEffects @ react-dom.development.js:21794
commitRootImpl @ react-dom.development.js:25007
commitRoot @ react-dom.development.js:24860
commitRootWhenReady @ react-dom.development.js:23598
finishConcurrentRender @ react-dom.development.js:23563
performConcurrentWorkOnRoot @ react-dom.development.js:23411
workLoop @ scheduler.development.js:261
flushWork @ scheduler.development.js:230
performWorkUntilDeadline @ scheduler.development.js:537
react-dom.development.js:25106  Uncaught Error: invariant expected app router to be mounted
    at useRouter (webpack-internal:///(:3000/app-client)/./node_modules/next/dist/client/components/navigation.js:118:15)
    at HotReload (webpack-internal:///(:3000/app-client)/./node_modules/next/dist/client/components/react-dev-overlay/hot-reloader-client.js:396:46)
    at renderWithHooks (webpack-internal:///(:3000/app-client)/./node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js:10697:18)
    at mountIndeterminateComponent (webpack-internal:///(:3000/app-client)/./node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js:15735:13)
    at beginWork$1 (webpack-internal:///(:3000/app-client)/./node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js:17310:16)
    at beginWork (webpack-internal:///(:3000/app-client)/./node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js:25689:14)
    at performUnitOfWork (webpack-internal:///(:3000/app-client)/./node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js:24540:12)
    at workLoopSync (webpack-internal:///(:3000/app-client)/./node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js:24256:5)
    at renderRootSync (webpack-internal:///(:3000/app-client)/./node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js:24211:7)
    at recoverFromConcurrentError (webpack-internal:///(:3000/app-client)/./node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js:23446:20)
    at performConcurrentWorkOnRoot (webpack-internal:///(:3000/app-client)/./node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js:23352:22)
    at workLoop (webpack-internal:///(:3000/app-client)/./node_modules/next/dist/compiled/scheduler/cjs/scheduler.development.js:261:34)
    at flushWork (webpack-internal:///(:3000/app-client)/./node_modules/next/dist/compiled/scheduler/cjs/scheduler.development.js:230:14)
    at MessagePort.performWorkUntilDeadline (webpack-internal:///(:3000/app-client)/./node_modules/next/dist/compiled/scheduler/cjs/scheduler.development.js:537:21)

You can find the code in the new branch of the same repo.


Interestingly, it has a different behavior in my actual project. It could be related to packages or something similar.

You can see the logs here. ```console Import trace for requested module: ./node_modules/next/dist/server/future/helpers/interception-routes.js ./node_modules/next/dist/client/components/router-reducer/compute-changed-path.js ./node_modules/next/dist/client/components/router-reducer/create-initial-router-state.js ./node_modules/next/dist/client/components/app-router.js - info Linting and checking validity of types - info Collecting page data - info Creating an optimized production build ...TypeError: Cannot read properties of null (reading 'useContext') at exports.useContext (C:\pd\Nazarsanj\frontend\node_modules\react\cjs\react.production.min.js:24:118) at Head (C:\pd\Nazarsanj\frontend\.next\server\pages\_error.js:284:44) at Wc (C:\PD\Nazarsanj\frontend\node_modules\react-dom\cjs\react-dom-server.browser.production.min.js:68:44) at Zc (C:\PD\Nazarsanj\frontend\node_modules\react-dom\cjs\react-dom-server.browser.production.min.js:70:253) at Z (C:\PD\Nazarsanj\frontend\node_modules\react-dom\cjs\react-dom-server.browser.production.min.js:76:89) at $c (C:\PD\Nazarsanj\frontend\node_modules\react-dom\cjs\react-dom-server.browser.production.min.js:78:98) at bd (C:\PD\Nazarsanj\frontend\node_modules\react-dom\cjs\react-dom-server.browser.production.min.js:77:404) at Z (C:\PD\Nazarsanj\frontend\node_modules\react-dom\cjs\react-dom-server.browser.production.min.js:76:217) at $c (C:\PD\Nazarsanj\frontend\node_modules\react-dom\cjs\react-dom-server.browser.production.min.js:78:98) at Zc (C:\PD\Nazarsanj\frontend\node_modules\react-dom\cjs\react-dom-server.browser.production.min.js:71:145) Error occurred prerendering page "/404". Read more: https://nextjs.org/docs/messages/prerender-error TypeError: Cannot read properties of null (reading 'useContext') at exports.useContext (C:\pd\Nazarsanj\frontend\node_modules\react\cjs\react.production.min.js:24:118) at Head (C:\pd\Nazarsanj\frontend\.next\server\pages\_error.js:284:44) at Wc (C:\PD\Nazarsanj\frontend\node_modules\react-dom\cjs\react-dom-server.browser.production.min.js:68:44) at Zc (C:\PD\Nazarsanj\frontend\node_modules\react-dom\cjs\react-dom-server.browser.production.min.js:70:253) at Z (C:\PD\Nazarsanj\frontend\node_modules\react-dom\cjs\react-dom-server.browser.production.min.js:76:89) at $c (C:\PD\Nazarsanj\frontend\node_modules\react-dom\cjs\react-dom-server.browser.production.min.js:78:98) at bd (C:\PD\Nazarsanj\frontend\node_modules\react-dom\cjs\react-dom-server.browser.production.min.js:77:404) at Z (C:\PD\Nazarsanj\frontend\node_modules\react-dom\cjs\react-dom-server.browser.production.min.js:76:217) at $c (C:\PD\Nazarsanj\frontend\node_modules\react-dom\cjs\react-dom-server.browser.production.min.js:78:98) at Zc (C:\PD\Nazarsanj\frontend\node_modules\react-dom\cjs\react-dom-server.browser.production.min.js:71:145) - info Creating an optimized production build .TypeError: Cannot read properties of null (reading 'useContext') at exports.useContext (C:\pd\Nazarsanj\frontend\node_modules\react\cjs\react.production.min.js:24:118) at Head (C:\pd\Nazarsanj\frontend\.next\server\pages\_error.js:284:44) at Wc (C:\PD\Nazarsanj\frontend\node_modules\react-dom\cjs\react-dom-server.browser.production.min.js:68:44) at Zc (C:\PD\Nazarsanj\frontend\node_modules\react-dom\cjs\react-dom-server.browser.production.min.js:70:253) at Z (C:\PD\Nazarsanj\frontend\node_modules\react-dom\cjs\react-dom-server.browser.production.min.js:76:89) at $c (C:\PD\Nazarsanj\frontend\node_modules\react-dom\cjs\react-dom-server.browser.production.min.js:78:98) at bd (C:\PD\Nazarsanj\frontend\node_modules\react-dom\cjs\react-dom-server.browser.production.min.js:77:404) at Z (C:\PD\Nazarsanj\frontend\node_modules\react-dom\cjs\react-dom-server.browser.production.min.js:76:217) at $c (C:\PD\Nazarsanj\frontend\node_modules\react-dom\cjs\react-dom-server.browser.production.min.js:78:98) at Zc (C:\PD\Nazarsanj\frontend\node_modules\react-dom\cjs\react-dom-server.browser.production.min.js:71:145) Error occurred prerendering page "/500". Read more: https://nextjs.org/docs/messages/prerender-error TypeError: Cannot read properties of null (reading 'useContext') at exports.useContext (C:\pd\Nazarsanj\frontend\node_modules\react\cjs\react.production.min.js:24:118) at Head (C:\pd\Nazarsanj\frontend\.next\server\pages\_error.js:284:44) at Wc (C:\PD\Nazarsanj\frontend\node_modules\react-dom\cjs\react-dom-server.browser.production.min.js:68:44) at Zc (C:\PD\Nazarsanj\frontend\node_modules\react-dom\cjs\react-dom-server.browser.production.min.js:70:253) at Z (C:\PD\Nazarsanj\frontend\node_modules\react-dom\cjs\react-dom-server.browser.production.min.js:76:89) at $c (C:\PD\Nazarsanj\frontend\node_modules\react-dom\cjs\react-dom-server.browser.production.min.js:78:98) at bd (C:\PD\Nazarsanj\frontend\node_modules\react-dom\cjs\react-dom-server.browser.production.min.js:77:404) at Z (C:\PD\Nazarsanj\frontend\node_modules\react-dom\cjs\react-dom-server.browser.production.min.js:76:217) at $c (C:\PD\Nazarsanj\frontend\node_modules\react-dom\cjs\react-dom-server.browser.production.min.js:78:98) at Zc (C:\PD\Nazarsanj\frontend\node_modules\react-dom\cjs\react-dom-server.browser.production.min.js:71:145) - info Creating an optimized production build ...TypeError: Cannot read properties of null (reading 'useContext') at exports.useContext (C:\pd\Nazarsanj\frontend\node_modules\next\dist\compiled\react\cjs\react.production.min.js:28:118) at usePathname (C:\pd\Nazarsanj\frontend\.next\server\chunks\118.js:1529:34) at ErrorBoundary (C:\pd\Nazarsanj\frontend\.next\server\chunks\118.js:849:50) at Je (C:\PD\Nazarsanj\frontend\node_modules\next\dist\compiled\react-dom\cjs\react-dom-server.edge.production.min.js:121:272) at Z (C:\PD\Nazarsanj\frontend\node_modules\next\dist\compiled\react-dom\cjs\react-dom-server.edge.production.min.js:128:91) at Je (C:\PD\Nazarsanj\frontend\node_modules\next\dist\compiled\react-dom\cjs\react-dom-server.edge.production.min.js:122:9) at Je (C:\PD\Nazarsanj\frontend\node_modules\next\dist\compiled\react-dom\cjs\react-dom-server.edge.production.min.js:127:11) at Z (C:\PD\Nazarsanj\frontend\node_modules\next\dist\compiled\react-dom\cjs\react-dom-server.edge.production.min.js:128:91) at Ke (C:\PD\Nazarsanj\frontend\node_modules\next\dist\compiled\react-dom\cjs\react-dom-server.edge.production.min.js:131:155) at Me (C:\PD\Nazarsanj\frontend\node_modules\next\dist\compiled\react-dom\cjs\react-dom-server.edge.production.min.js:130:289) Error occurred prerendering page "/login". Read more: https://nextjs.org/docs/messages/prerender-error TypeError: Cannot read properties of null (reading 'useContext') at exports.useContext (C:\pd\Nazarsanj\frontend\node_modules\next\dist\compiled\react\cjs\react.production.min.js:28:118) at usePathname (C:\pd\Nazarsanj\frontend\.next\server\chunks\118.js:1529:34) at ErrorBoundary (C:\pd\Nazarsanj\frontend\.next\server\chunks\118.js:849:50) at Je (C:\PD\Nazarsanj\frontend\node_modules\next\dist\compiled\react-dom\cjs\react-dom-server.edge.production.min.js:121:272) at Z (C:\PD\Nazarsanj\frontend\node_modules\next\dist\compiled\react-dom\cjs\react-dom-server.edge.production.min.js:128:91) at Je (C:\PD\Nazarsanj\frontend\node_modules\next\dist\compiled\react-dom\cjs\react-dom-server.edge.production.min.js:122:9) at Je (C:\PD\Nazarsanj\frontend\node_modules\next\dist\compiled\react-dom\cjs\react-dom-server.edge.production.min.js:127:11) at Z (C:\PD\Nazarsanj\frontend\node_modules\next\dist\compiled\react-dom\cjs\react-dom-server.edge.production.min.js:128:91) at Ke (C:\PD\Nazarsanj\frontend\node_modules\next\dist\compiled\react-dom\cjs\react-dom-server.edge.production.min.js:131:155) at Me (C:\PD\Nazarsanj\frontend\node_modules\next\dist\compiled\react-dom\cjs\react-dom-server.edge.production.min.js:130:289) TypeError: Cannot read properties of null (reading 'useContext') at exports.useContext (C:\pd\Nazarsanj\frontend\node_modules\next\dist\compiled\react\cjs\react.production.min.js:28:118) at usePathname (C:\pd\Nazarsanj\frontend\.next\server\chunks\118.js:1529:34) at ErrorBoundary (C:\pd\Nazarsanj\frontend\.next\server\chunks\118.js:849:50) at Je (C:\PD\Nazarsanj\frontend\node_modules\next\dist\compiled\react-dom\cjs\react-dom-server.edge.production.min.js:121:272) at Z (C:\PD\Nazarsanj\frontend\node_modules\next\dist\compiled\react-dom\cjs\react-dom-server.edge.production.min.js:128:91) at Je (C:\PD\Nazarsanj\frontend\node_modules\next\dist\compiled\react-dom\cjs\react-dom-server.edge.production.min.js:122:9) at Je (C:\PD\Nazarsanj\frontend\node_modules\next\dist\compiled\react-dom\cjs\react-dom-server.edge.production.min.js:127:11) at Z (C:\PD\Nazarsanj\frontend\node_modules\next\dist\compiled\react-dom\cjs\react-dom-server.edge.production.min.js:128:91) at Ke (C:\PD\Nazarsanj\frontend\node_modules\next\dist\compiled\react-dom\cjs\react-dom-server.edge.production.min.js:131:155) at Me (C:\PD\Nazarsanj\frontend\node_modules\next\dist\compiled\react-dom\cjs\react-dom-server.edge.production.min.js:130:289) Error occurred prerendering page "/business". Read more: https://nextjs.org/docs/messages/prerender-error TypeError: Cannot read properties of null (reading 'useContext') at exports.useContext (C:\pd\Nazarsanj\frontend\node_modules\next\dist\compiled\react\cjs\react.production.min.js:28:118) at usePathname (C:\pd\Nazarsanj\frontend\.next\server\chunks\118.js:1529:34) at ErrorBoundary (C:\pd\Nazarsanj\frontend\.next\server\chunks\118.js:849:50) at Je (C:\PD\Nazarsanj\frontend\node_modules\next\dist\compiled\react-dom\cjs\react-dom-server.edge.production.min.js:121:272) at Z (C:\PD\Nazarsanj\frontend\node_modules\next\dist\compiled\react-dom\cjs\react-dom-server.edge.production.min.js:128:91) at Je (C:\PD\Nazarsanj\frontend\node_modules\next\dist\compiled\react-dom\cjs\react-dom-server.edge.production.min.js:122:9) at Je (C:\PD\Nazarsanj\frontend\node_modules\next\dist\compiled\react-dom\cjs\react-dom-server.edge.production.min.js:127:11) at Z (C:\PD\Nazarsanj\frontend\node_modules\next\dist\compiled\react-dom\cjs\react-dom-server.edge.production.min.js:128:91) at Ke (C:\PD\Nazarsanj\frontend\node_modules\next\dist\compiled\react-dom\cjs\react-dom-server.edge.production.min.js:131:155) at Me (C:\PD\Nazarsanj\frontend\node_modules\next\dist\compiled\react-dom\cjs\react-dom-server.edge.production.min.js:130:289) TypeError: Cannot read properties of null (reading 'useContext') at exports.useContext (C:\pd\Nazarsanj\frontend\node_modules\next\dist\compiled\react\cjs\react.production.min.js:28:118) at usePathname (C:\pd\Nazarsanj\frontend\.next\server\chunks\118.js:1529:34) at ErrorBoundary (C:\pd\Nazarsanj\frontend\.next\server\chunks\118.js:849:50) at Je (C:\PD\Nazarsanj\frontend\node_modules\next\dist\compiled\react-dom\cjs\react-dom-server.edge.production.min.js:121:272) at Z (C:\PD\Nazarsanj\frontend\node_modules\next\dist\compiled\react-dom\cjs\react-dom-server.edge.production.min.js:128:91) at Je (C:\PD\Nazarsanj\frontend\node_modules\next\dist\compiled\react-dom\cjs\react-dom-server.edge.production.min.js:122:9) at Je (C:\PD\Nazarsanj\frontend\node_modules\next\dist\compiled\react-dom\cjs\react-dom-server.edge.production.min.js:127:11) at Z (C:\PD\Nazarsanj\frontend\node_modules\next\dist\compiled\react-dom\cjs\react-dom-server.edge.production.min.js:128:91) at Ke (C:\PD\Nazarsanj\frontend\node_modules\next\dist\compiled\react-dom\cjs\react-dom-server.edge.production.min.js:131:155) at Me (C:\PD\Nazarsanj\frontend\node_modules\next\dist\compiled\react-dom\cjs\react-dom-server.edge.production.min.js:130:289) - info Creating an optimized production build . Error occurred prerendering page "/". Read more: https://nextjs.org/docs/messages/prerender-error TypeError: Cannot read properties of null (reading 'useContext') at exports.useContext (C:\pd\Nazarsanj\frontend\node_modules\next\dist\compiled\react\cjs\react.production.min.js:28:118) at usePathname (C:\pd\Nazarsanj\frontend\.next\server\chunks\118.js:1529:34) at ErrorBoundary (C:\pd\Nazarsanj\frontend\.next\server\chunks\118.js:849:50) at Je (C:\PD\Nazarsanj\frontend\node_modules\next\dist\compiled\react-dom\cjs\react-dom-server.edge.production.min.js:121:272) at Z (C:\PD\Nazarsanj\frontend\node_modules\next\dist\compiled\react-dom\cjs\react-dom-server.edge.production.min.js:128:91) at Je (C:\PD\Nazarsanj\frontend\node_modules\next\dist\compiled\react-dom\cjs\react-dom-server.edge.production.min.js:122:9) at Je (C:\PD\Nazarsanj\frontend\node_modules\next\dist\compiled\react-dom\cjs\react-dom-server.edge.production.min.js:127:11) at Z (C:\PD\Nazarsanj\frontend\node_modules\next\dist\compiled\react-dom\cjs\react-dom-server.edge.production.min.js:128:91) at Ke (C:\PD\Nazarsanj\frontend\node_modules\next\dist\compiled\react-dom\cjs\react-dom-server.edge.production.min.js:131:155) at Me (C:\PD\Nazarsanj\frontend\node_modules\next\dist\compiled\react-dom\cjs\react-dom-server.edge.production.min.js:130:289) - info Generating static pages (6/6) > Export encountered errors on following paths: /_error: /404 /_error: /500 /business/page: /business /login/page: /login /page: / - info Creating an optimized production build . ```
Fredkiss3 commented 1 year ago

the problem is that you put the context outside of the <body> tag, you fix it by just putting it inside :

  <body>
        <AppContextProvider>{children}</AppContextProvider>
  </body>

This is normal as no markup can be outside of your <body> tag right ?

hamidmayeli commented 1 year ago

Cool, that fixed it.

Fredkiss3 commented 1 year ago

You may stumble onto multiple related bugs if you use next app router for your SPA, especially with SSR (prerendering). you may want to learn how to make your app work with SSR or you'd have to use the next/dynamic hack everywhere if you don't want the server.

Maybe you have chosen next for good reasons, but if you wanted a pure SPA without the need (and pains) of SSR, i would advise to start your project with vite, there is not an official guide to do so, but you can find multiple tutorials online.

Or simply start with :

npx create-vite@latest my-react-app --template react-ts

Or even don't start using Next App Directory but pages directory, if you want to stay with next and not deal with server components yet.

hamidmayeli commented 1 year ago

Thanks for your advice, @Fredkiss3. I'd probably go for the Pages then.

  1. But would it be SPA out of the box?
  2. If yes, does it create separated files for different pages?
  3. Is there any document for migration from app to pages or I just simply need to rename the folder? (Update: with a quick search around this I realize it's not just a rename but easy task as I only have a couple pages so far.)
Fredkiss3 commented 1 year ago
  1. No, but you don't have to deal with server components (if you don't understand them), you would still have to deal with components prerendered on the server, that's why i said to maybe go for vite for a purely SPA app (no SSR shenanigans).
  2. It creates a different HTML page for each page, but while navigating on the client, it just does a SPA navigation (same as with app dir)
  3. Pages dir and app dir work differently, so you may follow the tutorial on migration of pages to app but in reverse : https://nextjs.org/docs/app/building-your-application/upgrading/app-router-migration#migrating-from-pages-to-app . And learn how pages work : https://nextjs.org/docs/pages/building-your-application/routing/pages-and-layouts
hamidmayeli commented 1 year ago

The reason, I end up using NextJs, is because CRA is not supported anymore. But, I really like the idea of having smaller files to load what user needs. Although it's possible using Lazy/Suspense. On the other hand, vite seems to have limited community support. So, I'll give the pages a try before giving up on NextJs.

hamidmayeli commented 1 year ago

As my last question, how does PWA works with NextJs Page, NextJs App and Vite?

Fredkiss3 commented 1 year ago

you'd have to search for how to implement PWA support in Next and even in vite, i think you may even find some packages that could work, mostly with pages dir (for Next) since pages dir have not been out for long enough.

And vite is widely supported by the community, if judging simply by the fact that many framework are built on top of it : vue, solid, svelte, lit, astro and many more, you'll find a bunch of tutorials and examples for many many functionnalities you may need when building your app.

It is just the react core team who don't aknowledge it, or what they want is to recommend a framework with all batteries included (mostly routing & data-fetching) but not stricly suited for all and every kind of app, especially pure SPAs without SSR since you'd have to do many workarounds to avoid SSR. On the other hand, if you need some SSR for statically generated pages like landing pages or blog pages then Next becomes a good bet. You just have to have that take that tradeoff into account.

Fredkiss3 commented 1 year ago

this may be of great help for errors related to hydration, localStorage and SSR : https://nextjs.org/docs/messages/react-hydration-error

hamidmayeli commented 1 year ago

For the future reader, I end up using this template with Vite. It's a complete set of PWA, typescript, tailwind CSS, cypress (for e2e, component and code coverage), routing,fake API server. Quick SPA

github-actions[bot] commented 1 year ago

This closed issue has been automatically locked because it had no new activity for a month. If you are running into a similar issue, please create a new issue with the steps to reproduce. Thank you.