dai-shi / waku

⛩️ The minimal React framework
https://waku.gg
MIT License
4.46k stars 118 forks source link

Mantine Component Library / dev mode / Error when evaluating SSR module #421

Open aheissenberger opened 7 months ago

aheissenberger commented 7 months ago

How can I use Mantine with WAKU without getting this Error: (waku dev --with-ssr or waku dev - no problem with waku build --with-ssr)

repo to replicate the error: https://github.com/aheissenberger/waku-mantine-broken

22:27:44 [vite] Error when evaluating SSR module /node_modules/.pnpm/use-callback-ref@1.3.1_@types+react@18.2.48_react@18.3.0-canary-b30030471-20240117/node_modules/use-callback-ref/dist/es2015/useRef.js: failed to import "react"
|- SyntaxError: [vite] Named export 'useState' not found. The requested module 'react' is a CommonJS module, which may not support all module.exports as named exports.
CommonJS modules can always be imported via the default export, for example using:

import pkg from 'react';
const {useState} = pkg;

    at analyzeImportedModDifference (file:///waku-mantine/node_modules/.pnpm/vite@5.0.12/node_modules/vite/dist/node/chunks/dep-9A4-l-43.js:50953:19)
    at nodeImport (file:///waku-mantine/node_modules/.pnpm/vite@5.0.12/node_modules/vite/dist/node/chunks/dep-9A4-l-43.js:50904:9)
    at async ssrImport (file:///waku-mantine/node_modules/.pnpm/vite@5.0.12/node_modules/vite/dist/node/chunks/dep-9A4-l-43.js:50799:24)
    at async eval (/waku-mantine/node_modules/.pnpm/use-callback-ref@1.3.1_@types+react@18.2.48_react@18.3.0-canary-b30030471-20240117/node_modules/use-callback-ref/dist/es2015/useRef.js:3:44)
    at async instantiateModule (file:///waku-mantine/node_modules/.pnpm/vite@5.0.12/node_modules/vite/dist/node/chunks/dep-9A4-l-43.js:50861:9)

Cannot render RSC Error: SyntaxError: [vite] Named export 'useState' not found. The requested module 'react' is a CommonJS module, which may not support all module.exports as named exports.
CommonJS modules can always be imported via the default export, for example using:

import pkg from 'react';
const {useState} = pkg;

    at file:///waku-mantine/node_modules/.pnpm/file+..+..+DEV+waku+packages+waku+waku-0.19.1.tgz_react-dom@18.3.0-canary-b30030471-20240117__jadhby4bmjtn267th77iortg3m/node_modules/waku/dist/lib/handlers/dev-worker-api.js:148:60
    at Worker.<anonymous> (file:///waku-mantine/node_modules/.pnpm/file+..+..+DEV+waku+packages+waku+waku-0.19.1.tgz_react-dom@18.3.0-canary-b30030471-20240117__jadhby4bmjtn267th77iortg3m/node_modules/waku/dist/lib/handlers/dev-worker-api.js:33:52)
    at Worker.emit (node:events:531:35)
    at MessagePort.<anonymous> (node:internal/worker:263:53)
    at [nodejs.internal.kHybridDispatch] (node:internal/event_target:822:20)
    at exports.emitMessage (node:internal/per_context/messageport:23:28)

Versions: Mantine: 7.4.2 - works with NextJS App Router and has 'use client' in all components - https://mantine.dev/guides/next/ WAKU: 0.19.1

root-layout.tsx

import '@mantine/core/styles.css';
import { ColorSchemeScript, createTheme, MantineProvider } from '@mantine/core';
import type { ReactNode } from 'react';

import { Header } from '../components/header.js';
import { Footer } from '../components/footer.js';

const theme = createTheme({
  /** Put your mantine theme override here */
});

type RootLayoutProps = { children: ReactNode };

export const RootLayout = async ({ children }: RootLayoutProps) => {
  const data = await getData();

  return (

    <div id="__waku" >
      <meta property="description" content={data.description} />
      <link rel="icon" type="image/png" href={data.icon} />
      <ColorSchemeScript />
      <MantineProvider theme={theme}>
        <Header />
        <main >
          {children}
        </main>
        <Footer />
      </MantineProvider>
    </div>

  );
};

const getData = async () => {
  const data = {
    description: 'An internet website!',
    icon: '/images/favicon.png',
  };

  return data;
};
dai-shi commented 6 months ago

Hmm, hope @Aslemammad has an idea.

aheissenberger commented 2 months ago

Updated Status with WAKU 0.21.0-beta.0 Commit 8ffc4f546b6ad52638cc930f6ba192823b0ca66d

Errors with waku dev:


Cannot process SSR Error: @mantine/core: MantineProvider was not found in component tree, make sure you have it in your app
    at useMantineTheme (file:///waku/node_modules/.pnpm/@mantine+core@7.11.0_@mantine+hooks@7.11.0_react@19.0.0-rc.0__@types+react@18.3.3_react-dom@1_5dwn4r2gopvgtvjfs7ivsjxr3q/node_modules/@mantine/core/esm/core/MantineProvider/MantineThemeProvider/MantineThemeProvider.mjs:12:11)
    at useProps (file:///waku/node_modules/.pnpm/@mantine+core@7.11.0_@mantine+hooks@7.11.0_react@19.0.0-rc.0__@types+react@18.3.3_react-dom@1_5dwn4r2gopvgtvjfs7ivsjxr3q/node_modules/@mantine/core/esm/core/MantineProvider/use-props/use-props.mjs:9:17)
    at @mantine/core/Autocomplete (file:///waku/node_modules/.pnpm/@mantine+core@7.11.0_@mantine+hooks@7.11.0_react@19.0.0-rc.0__@types+react@18.3.3_react-dom@1_5dwn4r2gopvgtvjfs7ivsjxr3q/node_modules/@mantine/core/esm/components/Autocomplete/Autocomplete.mjs:40:17)
    at renderWithHooks (/waku/node_modules/.pnpm/react-dom@19.0.0-rc.0_react@19.0.0-rc.0/node_modules/react-dom/cjs/react-dom-server.edge.development.js:9602:16)
    at renderForwardRef (/waku/node_modules/.pnpm/react-dom@19.0.0-rc.0_react@19.0.0-rc.0/node_modules/react-dom/cjs/react-dom-server.edge.development.js:9834:18)
    at renderElement (/waku/node_modules/.pnpm/react-dom@19.0.0-rc.0_react@19.0.0-rc.0/node_modules/react-dom/cjs/react-dom-server.edge.development.js:9990:11)
    at renderNodeDestructive (/waku/node_modules/.pnpm/react-dom@19.0.0-rc.0_react@19.0.0-rc.0/node_modules/react-dom/cjs/react-dom-server.edge.development.js:10246:13)
    at finishFunctionComponent (/waku/node_modules/.pnpm/react-dom@19.0.0-rc.0_react@19.0.0-rc.0/node_modules/react-dom/cjs/react-dom-server.edge.development.js:9767:5)
    at renderFunctionComponent (/waku/node_modules/.pnpm/react-dom@19.0.0-rc.0_react@19.0.0-rc.0/node_modules/react-dom/cjs/react-dom-server.edge.development.js:9715:3)
    at renderElement (/waku/node_modules/.pnpm/react-dom@19.0.0-rc.0_react@19.0.0-rc.0/node_modules/react-dom/cjs/react-dom-server.edge.development.js:9918:7)
    at renderLazyComponent (/waku/node_modules/.pnpm/react-dom@19.0.0-rc.0_react@19.0.0-rc.0/node_modules/react-dom/cjs/react-dom-server.edge.development.js:9895:3)
    at renderElement (/waku/node_modules/.pnpm/react-dom@19.0.0-rc.0_react@19.0.0-rc.0/node_modules/react-dom/cjs/react-dom-server.edge.development.js:10023:11)
    at renderNodeDestructive (/waku/node_modules/.pnpm/react-dom@19.0.0-rc.0_react@19.0.0-rc.0/node_modules/react-dom/cjs/react-dom-server.edge.development.js:10246:13)
    at renderNode (/waku/node_modules/.pnpm/react-dom@19.0.0-rc.0_react@19.0.0-rc.0/node_modules/react-dom/cjs/react-dom-server.edge.development.js:10640:14)
    at renderChildrenArray (/waku/node_modules/.pnpm/react-dom@19.0.0-rc.0_react@19.0.0-rc.0/node_modules/react-dom/cjs/react-dom-server.edge.development.js:10519:5)
    at renderNodeDestructive (/waku/node_modules/.pnpm/react-dom@19.0.0-rc.0_react@19.0.0-rc.0/node_modules/react-dom/cjs/react-dom-server.edge.development.js:10273:7)
    at renderNode (/waku/node_modules/.pnpm/react-dom@19.0.0-rc.0_react@19.0.0-rc.0/node_modules/react-dom/cjs/react-dom-server.edge.development.js:10640:14)
    at renderChildrenArray (/waku/node_modules/.pnpm/react-dom@19.0.0-rc.0_react@19.0.0-rc.0/node_modules/react-dom/cjs/react-dom-server.edge.development.js:10519:5)
    at renderNodeDestructive (/waku/node_modules/.pnpm/react-dom@19.0.0-rc.0_react@19.0.0-rc.0/node_modules/react-dom/cjs/react-dom-server.edge.development.js:10273:7)
    at renderContextProvider (/waku/node_modules/.pnpm/react-dom@19.0.0-rc.0_react@19.0.0-rc.0/node_modules/react-dom/cjs/react-dom-server.edge.development.js:9877:3)
    at renderElement (/waku/node_modules/.pnpm/react-dom@19.0.0-rc.0_react@19.0.0-rc.0/node_modules/react-dom/cjs/react-dom-server.edge.development.js:10006:13)
    at renderNodeDestructive (/waku/node_modules/.pnpm/react-dom@19.0.0-rc.0_react@19.0.0-rc.0/node_modules/react-dom/cjs/react-dom-server.edge.development.js:10246:13)
    at finishFunctionComponent (/waku/node_modules/.pnpm/react-dom@19.0.0-rc.0_react@19.0.0-rc.0/node_modules/react-dom/cjs/react-dom-server.edge.development.js:9767:5)
    at renderFunctionComponent (/waku/node_modules/.pnpm/react-dom@19.0.0-rc.0_react@19.0.0-rc.0/node_modules/react-dom/cjs/react-dom-server.edge.development.js:9715:3)
    at renderElement (/waku/node_modules/.pnpm/react-dom@19.0.0-rc.0_react@19.0.0-rc.0/node_modules/react-dom/cjs/react-dom-server.edge.development.js:9918:7)
    at renderNodeDestructive (/waku/node_modules/.pnpm/react-dom@19.0.0-rc.0_react@19.0.0-rc.0/node_modules/react-dom/cjs/react-dom-server.edge.development.js:10246:13)
    at renderContextProvider (/waku/node_modules/.pnpm/react-dom@19.0.0-rc.0_react@19.0.0-rc.0/node_modules/react-dom/cjs/react-dom-server.edge.development.js:9877:3)
    at renderElement (/waku/node_modules/.pnpm/react-dom@19.0.0-rc.0_react@19.0.0-rc.0/node_modules/react-dom/cjs/react-dom-server.edge.development.js:10006:13)
    at renderNodeDestructive (/waku/node_modules/.pnpm/react-dom@19.0.0-rc.0_react@19.0.0-rc.0/node_modules/react-dom/cjs/react-dom-server.edge.development.js:10246:13)
    at finishFunctionComponent (/waku/node_modules/.pnpm/react-dom@19.0.0-rc.0_react@19.0.0-rc.0/node_modules/react-dom/cjs/react-dom-server.edge.development.js:9767:5)
    at renderFunctionComponent (/waku/node_modules/.pnpm/react-dom@19.0.0-rc.0_react@19.0.0-rc.0/node_modules/react-dom/cjs/react-dom-server.edge.development.js:9715:3)
    at renderElement (/waku/node_modules/.pnpm/react-dom@19.0.0-rc.0_react@19.0.0-rc.0/node_modules/react-dom/cjs/react-dom-server.edge.development.js:9918:7)
    at renderLazyComponent (/waku/node_modules/.pnpm/react-dom@19.0.0-rc.0_react@19.0.0-rc.0/node_modules/react-dom/cjs/react-dom-server.edge.development.js:9895:3)
    at renderElement (/waku/node_modules/.pnpm/react-dom@19.0.0-rc.0_react@19.0.0-rc.0/node_modules/react-dom/cjs/react-dom-server.edge.development.js:10023:11)
    at renderNodeDestructive (/waku/node_modules/.pnpm/react-dom@19.0.0-rc.0_react@19.0.0-rc.0/node_modules/react-dom/cjs/react-dom-server.edge.development.js:10246:13)
    at retryRenderTask (/waku/node_modules/.pnpm/react-dom@19.0.0-rc.0_react@19.0.0-rc.0/node_modules/react-dom/cjs/react-dom-server.edge.development.js:11072:5)
    at retryTask (/waku/node_modules/.pnpm/react-dom@19.0.0-rc.0_react@19.0.0-rc.0/node_modules/react-dom/cjs/react-dom-server.edge.development.js:11044:5)
    at performWork (/waku/node_modules/.pnpm/react-dom@19.0.0-rc.0_react@19.0.0-rc.0/node_modules/react-dom/cjs/react-dom-server.edge.development.js:11230:7)
    at Timeout._onTimeout (/waku/node_modules/.pnpm/react-dom@19.0.0-rc.0_react@19.0.0-rc.0/node_modules/react-dom/cjs/react-dom-server.edge.development.js:9081:14)
    at listOnTimeout (node:internal/timers:573:17)
    at process.processTimers (node:internal/timers:514:7)

with this in vite.config.ts:

export default {
  ssr: {
    optimizeDeps: {
      include: ['@mantine/core'],
    },
  },
};

the error changes to:

10:40:29 AM [vite] Error when evaluating SSR module /src/pages/_layout.tsx: failed to import "/node_modules/.vite/waku-dev-server-rsc/deps_ssr/@mantine_core.js?v=ea31c413"
|- TypeError: (0 , import_react74.createContext) is not a function
    at eval (/waku/examples/xx_mantine/node_modules/.vite/waku-dev-server-rsc/deps_ssr/@mantine_core.js?v=ea31c413:2258:55)
    at async instantiateModule (file:///waku/node_modules/.pnpm/vite@5.2.12_@types+node@20.12.13_sugarss@4.0.1_postcss@8.4.39__terser@5.31.0/node_modules/vite/dist/node/chunks/dep-BKbDVx1T.js:56231:9)

Cannot process SSR TypeError: (0 , import_react74.createContext) is not a function
    at eval (/waku/examples/xx_mantine/node_modules/.vite/waku-dev-server-rsc/deps_ssr/@mantine_core.js?v=ea31c413:2258:55)
    at async instantiateModule (file:///waku/node_modules/.pnpm/vite@5.2.12_@types+node@20.12.13_sugarss@4.0.1_postcss@8.4.39__terser@5.31.0/node_modules/vite/dist/node/chunks/dep-BKbDVx1T.js:56231:9)
Cannot process SSR TypeError: (0 , import_react74.createContext) is not a function
    at eval (/waku/examples/xx_mantine/node_modules/.vite/waku-dev-server-rsc/deps_ssr/@mantine_core.js?v=ea31c413:2258:55)
    at async instantiateModule (file:///waku/node_modules/.pnpm/vite@5.2.12_@types+node@20.12.13_sugarss@4.0.1_postcss@8.4.39__terser@5.31.0/node_modules/vite/dist/node/chunks/dep-BKbDVx1T.js:56231:9)
node:internal/process/promises:391
    triggerUncaughtException(err, true /* fromPromise */);
    ^

TypeError: (0 , import_react74.createContext) is not a function
    at eval (/waku/examples/xx_mantine/node_modules/.vite/waku-dev-server-rsc/deps_ssr/@mantine_core.js?v=ea31c413:2258:55)
    at async instantiateModule (file:///waku/node_modules/.pnpm/vite@5.2.12_@types+node@20.12.13_sugarss@4.0.1_postcss@8.4.39__terser@5.31.0/node_modules/vite/dist/node/chunks/dep-BKbDVx1T.js:56231:9)
dai-shi commented 2 months ago

Can you add 'react' too?

-       include: ['@mantine/core'],
+       include: ['@mantine/core', 'react'],
jkhaui commented 2 months ago

Confirming that I also get the error TypeError: (0 , import_react74.createContext) is not a function after upgrading from "0.21.0-alpha.2" to "0.21.0-beta.0". Also, adding react to optimizeDeps doesn't fix it. Hmm let me see if I can help out. Going to try get this working in dev, mantine is a library I also really "need"

jkhaui commented 2 months ago

I'll probably need some time to read through this thread and try and understand how the dev server differs to the production build, etc.

But for now the only thing that seems to make a difference is to not include mantine in optimizeDeps.include. (Some other things I tried were to add react to resolve.dedupe and adding mantine to ssr.noExternal. Neither had any effect)

aheissenberger commented 2 months ago

The Problem with the SSR Error MantineProvider was not found in component tree only exists if an imported custom component is using a Mantine Component. Directly imported components from Mantine (e.g. Button) in the same file wrapped by a <MantineProvider> do not create this error! It looks like in WAKU SSR Dev Mode the component can only access the context of the provider if the provider is placed in the same file or the context from _layout.tsx is not accessible in the custom component.

I was able to work around the SSR Error MantineProvider was not found in component tree by wrapping the used mantine component in the imported custom component with MantineProvider but this is not a solution as multiple theme context blow up the code with multiple injections of stylings but should help to find the problem:

// src/component/Combox.tsx
'use client';

import * as React from 'react';
import { Autocomplete, MantineProvider } from '@mantine/core';
import {theme} from '../theme';
export default function ComboBox() {
  return (
    <MantineProvider  theme={theme}> {/* this is only a work around */}
    <Autocomplete
      label="Your favorite library"
      placeholder="Pick value or enter anything"
      data={['React', 'Angular', 'Vue', 'Svelte']}
    />
    </MantineProvider>
  );
}
// src/pages/_layout.tsx
import '@mantine/core/styles.css';

import type { ReactNode } from 'react';
import { Autocomplete, MantineProvider } from '@mantine/core';
import {theme} from '../theme';
import { Button } from '@mantine/core';
import ComboBox from '../components/Combox.tsx';

type RootLayoutProps = { children: ReactNode };

export default async function RootLayout({ children }: RootLayoutProps) {
  return (
    <MantineProvider  theme={theme}>
    <Button
        variant='contained'
      >
        DEMO
      </Button>
      <ComboBox />
      {/* <Autocomplete
      label="Your favorite library"
      placeholder="Pick value or enter anything"
      data={['React', 'Angular', 'Vue', 'Svelte']}
    /> */}
    </MantineProvider>

  );
}

export const getConfig = async () => {
  return {
    render: 'static',
  };
};
jkhaui commented 2 months ago

The Problem with the SSR Error MantineProvider was not found in component tree only exists if an imported custom component is using a Mantine Component. Directly imported components from Mantine (e.g. Button) in the same file wrapped by a <MantineProvider> do not create this error!

Oh this is a great find. Again, confirming that I experience the same behaviour (was previously using the mantine provider from an imported providers component, but the issue goes away if I use the Mantine provider directly from @mantine/core in the root layout).

Question: why do we need @mantine/core in optimizeDeps? Seems like it works the same way in dev regardless of whether it's included there

jkhaui commented 2 months ago

Maybe this is the problem, when you add @mantine/core to optimizeDeps.include, looks like it creates this cjs build of the module which subsequently tries to call createContext from the react-server import. But the function createContext doesn't exist at all in react-server. Shouldn't it be importing from react?

But again, why do we need to add mantine to optimizeDeps? Don't the latest versions of Waku mostly fix the compatibility issues without needing to use optimizeDeps?

image

For reference, I have Mantine working with an Astro project (which uses Vite internally) and React v18.3.1. This is what the equivalent code looks like under node_modules/.vite/deps/...

image

jkhaui commented 2 months ago

@aheissenberger I believe I've found the cause of the issue in a dev environment and am waiting for a response from Mantine's maintainer, see here

You can use a local build of Mantine with the suggestions I've put in that post, and also ensure you don't put @mantine/core under optimizeDeps. It should all work in your dev environment after doing this

jkhaui commented 2 months ago

SOLVED IT! FINALLY.

Just when this entire thing seemed impossible to understand and I was about to give up... Here's the required config, I will post an explanation of my findings later:

  1. To overcome the legacy peer deps issue when running npm i, add this to your package.json (note that I've only tried this with npm so far, not pnpm):
  "overrides": {
    "react": "$react",
    "react-dom": {
      ".": "$react-dom",
      "react": "$react"
    },
    "react-server-dom-webpack": {
      ".": "$react-server-dom-webpack",
      "react": "$react",
      "react-dom": "$react-dom"
    },
    "@floating-ui/react": {
      "react": "$react",
      "react-dom": "$react-dom",
      "@floating-ui/react-dom": {
        "react": "$react",
        "react-dom": "$react-dom",
        "@floating-ui/dom": {
          "react": "$react",
          "react-dom": "$react-dom"
        }
      }
    },
    "waku": {
      ".": "$waku",
      "react": "$react",
      "react-dom": "$react-dom",
      "react-server-dom-webpack": "$react-server-dom-webpack",
      "@vitejs/plugin-react": {
        "react": "$react",
        "react-dom": "$react-dom",
        "react-refresh": {
          "react": "$react",
          "react-dom": "$react-dom"
        }
      }
    },
    "@mantine/core": {
      ".": "$@mantine/core",
      "react": "$react",
      "react-dom": "$react-dom",
      "react-number-format": {
        "react": "$react",
        "react-dom": "$react-dom"
      },
      "react-textarea-autosize": {
        "react": "$react",
        "react-dom": "$react-dom",
        "use-compose-ref": {
          "react": "$react",
          "react-dom": "$react-dom"
        },
        "use-latest": {
          "react": "$react",
          "react-dom": "$react-dom",
          "use-isomorphic-layout-effect": {
            "react": "$react",
            "react-dom": "$react-dom"
          }
        }
      },
      "react-remove-scroll": {
        "react": "$react",
        "react-dom": "$react-dom",
        "react-remove-scroll-bar": {
          "react": "$react",
          "react-dom": "$react-dom"
        },
        "react-style-singleton": {
          "react": "$react",
          "react-dom": "$react-dom"
        },
        "use-callback-ref": {
          "react": "$react",
          "react-dom": "$react-dom"
        },
        "use-sidecar": {
          "react": "$react",
          "react-dom": "$react-dom"
        }
      },
      "@mantine-tests/core": {
        "react": "$react",
        "react-dom": "$react-dom"
      },
      "@floating-ui/react": {
        "react": "$react",
        "react-dom": "$react-dom",
        "@floating-ui/react-dom": {
          "react": "$react",
          "react-dom": "$react-dom",
          "@floating-ui/dom": {
            "react": "$react",
            "react-dom": "$react-dom"
          }
        }
      }
    },
    "@mantine/hooks": {
      ".": "$@mantine/hooks",
      "react": "$react"
    }
  }

Also note that you don't have to put this on your package.json. You can instead add the --legacy-peer-deps flag when running npm i. I personally find it slightly less hacky to add the overrides.

  1. Create a vite.config.ts file with the following:
import { defineConfig } from "vite";

export default defineConfig({
    optimizeDeps: {
        exclude: ["@mantine/core", "@mantine/hooks"]
    },
    ssr: {
        noExternal: ["@mantine/core", "@mantine/hooks"]
    }
});

Mantine should work fine in dev mode now

dai-shi commented 2 months ago

So, it's basically this is the trick? I think noExternal is already applied.

    optimizeDeps: {
        exclude: ["@mantine/core", "@mantine/hooks"]
    },
jkhaui commented 2 months ago

So, it's basically this is the trick? I think noExternal is already applied.


    optimizeDeps: {

        exclude: ["@mantine/core", "@mantine/hooks"]

    },

I'll check again tomorrow (not on my computer), but I don't think ssr.noExternal is automatically applied.

First I added mantine to ssr.noExternal and it fixed the issue of <MantineProvider/> (imported via a custom provider component used in the root layout) throwing an error during SSR.

But still the app would then immediately crash clientside (from the same error) during hydration. It looks like optimizeDeps exclude fixed this

So yeah, it's strange - looks like ssr noExternal tells vite "fix this package on the server" & optimizeDeps exclude tells vite "fix this on the client"

jkhaui commented 2 months ago

Follow up:

I'm happy I managed to fix this for my own use-case but I think it's far more important we use this opportunity to nail down what the root cause is. We all know from first-hand experience that debugging issues with Vite's bundling of 3rd-party deps can be a nightmare. So let's try and understand once and for all how each of Vite's configuration options affects the bundling process, rather than blindly tweaking things until it works


Before & After Comparison

"Broken" setup

vite.config.ts

import { defineConfig } from "vite";

export default defineConfig({
    // optimizeDeps: {
    //     exclude: ["@mantine/core", "@mantine/hooks"]
    // },
    ssr: {
        noExternal: ["@mantine/core", "@mantine/hooks"]
    }
});

Contents of node_modules > .vite > waku-dev-server inspected from browser sources:

Screenshot 2024-07-08 104434

Working setup

vite.config.ts

import { defineConfig } from "vite";

export default defineConfig({
    optimizeDeps: {
        exclude: ["@mantine/core", "@mantine/hooks"]
    },
    ssr: {
        noExternal: ["@mantine/core", "@mantine/hooks"]
    }
});

Contents of node_modules > .vite > waku-dev-server inspected from browser sources:

Screenshot 2024-07-08 104238

Observations & open questions

  1. Appears that Vite has a separate bundling mechanism for SSR and another for modules sent to the browser.

This is observed by adding @mantine/core to ssr.noExternal, which fixes the missing context provider error on the server and allows the initial SSRd HTML to render in the browser. However, during hydration in the browser, the client crashes as it re-executes the same logic but it's not using the corrected module graph used on the server.

The answer to this is adding @mantine/core to optimizeDeps.exclude, which seems to instruct Vite to also leave Mantine and its dependencies in their raw unbundled ESM format on the client.

  1. We've already suspected that the "missing context provider" triggered by Mantine is caused by multiple versions of react and/or @mantine/core in the module graph. The before & after screenshots confirm this.

  2. Why is the default behaviour of Waku/Vite in this scenario to include @mantine/core twice in the module graph? This can clearly be seen in the "before" screenshot where @mantine is both in Vite's optimised deps under waku-dev-server as well as the root node_modules. This double-inclusion is the root cause and we need to figure out: is this a Waku-specific problem? Vite-specific? Is it related to React v19 rc being used? Is there a problem with Mantine itself?

dai-shi commented 2 months ago

@Aslemammad Can you help here?

@jkhaui btw, there's ssr.optimizeDeps.exclude instead of optimizeDeps.exclude. It's not documented though.

aheissenberger commented 1 month ago

@jkhaui great work finding a working setup - but did you find a solution to bundle the matine packages? I get roughly 149 http requests (assets) and they are grouped into 4 waves download after each other :-( Look like tree shaking is not applied and all components of Mantine UI are included in each request

aheissenberger commented 1 month ago

still breaks with @mantine/dates even when added to vite.config.ts

dai-shi commented 1 month ago

Hmm. Can you update the repro with the latest waku@next?

jkhaui commented 1 month ago

@jkhaui great work finding a working setup - but did you find a solution to bundle the matine packages?

I get roughly 149 http requests (assets) and they are grouped into 4 waves download after each other :-(

Look like tree shaking is not applied and all components of Mantine UI are included in each request

Sorry I didn't see this (started a new job so have limited time to experiment with waku atm ☹️)

Hmm yeah you're right. I never investigated deeper as I didn't experience any noticeable perf issues, but this explains why there's like 150 tiny RSC chunks in the build output!

Hopefully I can help look into this soon. I've been comparing Waku's build pipeline with Astro + react 19. I find it odd that there doesn't appear to be significant difference between how either framework uses vite in the build process. However, Waku has a lot more trouble bundling certain libs.

My guess is that the need for a separate environment to bundle RSCs might be the reason

aheissenberger commented 4 weeks ago

Hmm. Can you update the repro with the latest waku@next?

I always test with the lastest commits in waku@next - this was tested with commit d0fae28

dai-shi commented 4 weeks ago

Okay. I mean if I can test your repo. https://github.com/aheissenberger/waku-mantine-broken isn't updated.

aheissenberger commented 4 weeks ago

You can find a test in the examples/xx_mantine in the branch "mantine-test" of my forked repo of WAKU: https://github.com/aheissenberger/waku/tree/mantine-test

dai-shi commented 3 weeks ago

Thanks. You are not using the latest version. It has to be the same waku version in package json or use the workspace protocol.

Here's the fix:

diff --git a/examples/xx_mantine/package.json b/examples/xx_mantine/package.json
index 8f01461d..24033eff 100644
--- a/examples/xx_mantine/package.json
+++ b/examples/xx_mantine/package.json
@@ -16,10 +16,10 @@
     "@mantine/dates": "^7.12.1",
     "@mantine/hooks": "^7.12.1",
     "dayjs": "^1.11.12",
-    "react": "19.0.0-rc.0",
-    "react-dom": "19.0.0-rc.0",
-    "react-server-dom-webpack": "19.0.0-rc.0",
-    "waku": "0.21.0-beta.0"
+    "react": "19.0.0-rc-68dbd84b-20240812",
+    "react-dom": "19.0.0-rc-68dbd84b-20240812",
+    "react-server-dom-webpack": "19.0.0-rc-68dbd84b-20240812",
+    "waku": "0.21.0-beta.5"
   },
   "devDependencies": {
     "@types/react": "18.3.3",
diff --git a/examples/xx_mantine/src/pages/_layout.tsx b/examples/xx_mantine/src/pages/_layout.tsx
index a3bb4224..a5686f6f 100644
--- a/examples/xx_mantine/src/pages/_layout.tsx
+++ b/examples/xx_mantine/src/pages/_layout.tsx
@@ -3,7 +3,7 @@ import '@mantine/core/styles.css';

 import type { ReactNode } from 'react';
 import { MantineProvider } from '@mantine/core';
-import {theme} from '../theme';
+import { theme } from '../theme';

 type RootLayoutProps = { children: ReactNode };

@@ -11,10 +11,14 @@ export default async function RootLayout({ children }: RootLayoutProps) {
   const data = await getData();

   return (
-    <MantineProvider  theme={theme} withNormalizeCSS>
-    {children}
-    </MantineProvider>
-    
+    <html>
+      <head></head>
+      <body>
+        <MantineProvider theme={theme} withNormalizeCSS>
+          {children}
+        </MantineProvider>
+      </body>
+    </html>
   );
 }
aheissenberger commented 3 weeks ago

@dai-shi sorry for using an older version, but this did not fix the error I get with waku dev when using the <MyDate /> date component examples/xx_mantine/src/pages/index.tsx of Mantine:

10:32:54 AM [vite] Error when evaluating SSR module /@fs/Users/ah/SVN-Checkouts/DEV/waku/node_modules/.pnpm/@mantine+dates@7.12.1_@mantine+core@7.12.1_@mantine+hooks@7.12.1_react@19.0.0-rc-68dbd84b-202_44x75gxv2oqotuitlhasvn5g6e/node_modules/@mantine/dates/esm/utils/get-timezone-offset.mjs:
|- TypeError: Cannot read properties of undefined (reading 'extend')
    at eval (/Users/ah/SVN-Checkouts/DEV/waku/node_modules/.pnpm/@mantine+dates@7.12.1_@mantine+core@7.12.1_@mantine+hooks@7.12.1_react@19.0.0-rc-68dbd84b-202_44x75gxv2oqotuitlhasvn5g6e/node_modules/@mantine/dates/esm/utils/get-timezone-offset.mjs:11:31)
    at async instantiateModule (file:///Users/ah/SVN-Checkouts/DEV/waku/node_modules/.pnpm/vite@5.4.0_@types+node@22.4.0_sugarss@4.0.1_postcss@8.4.41__terser@5.31.6/node_modules/vite/dist/node/chunks/dep-NjL7WTE1.js:52844:5)

10:32:54 AM [vite] Error when evaluating SSR module /@fs/Users/ah/SVN-Checkouts/DEV/waku/node_modules/.pnpm/@mantine+dates@7.12.1_@mantine+core@7.12.1_@mantine+hooks@7.12.1_react@19.0.0-rc-68dbd84b-202_44x75gxv2oqotuitlhasvn5g6e/node_modules/@mantine/dates/esm/utils/shift-timezone.mjs:
|- TypeError: Cannot read properties of undefined (reading 'extend')
    at eval (/Users/ah/SVN-Checkouts/DEV/waku/node_modules/.pnpm/@mantine+dates@7.12.1_@mantine+core@7.12.1_@mantine+hooks@7.12.1_react@19.0.0-rc-68dbd84b-202_44x75gxv2oqotuitlhasvn5g6e/node_modules/@mantine/dates/esm/utils/get-timezone-offset.mjs:11:31)
    at async instantiateModule (file:///Users/ah/SVN-Checkouts/DEV/waku/node_modules/.pnpm/vite@5.4.0_@types+node@22.4.0_sugarss@4.0.1_postcss@8.4.41__terser@5.31.6/node_modules/vite/dist/node/chunks/dep-NjL7WTE1.js:52844:5)

10:32:54 AM [vite] Error when evaluating SSR module /@fs/Users/ah/SVN-Checkouts/DEV/waku/node_modules/.pnpm/@mantine+dates@7.12.1_@mantine+core@7.12.1_@mantine+hooks@7.12.1_react@19.0.0-rc-68dbd84b-202_44x75gxv2oqotuitlhasvn5g6e/node_modules/@mantine/dates/esm/utils/get-default-clamped-date.mjs:
|- TypeError: Cannot read properties of undefined (reading 'extend')
    at eval (/Users/ah/SVN-Checkouts/DEV/waku/node_modules/.pnpm/@mantine+dates@7.12.1_@mantine+core@7.12.1_@mantine+hooks@7.12.1_react@19.0.0-rc-68dbd84b-202_44x75gxv2oqotuitlhasvn5g6e/node_modules/@mantine/dates/esm/utils/get-timezone-offset.mjs:11:31)
    at async instantiateModule (file:///Users/ah/SVN-Checkouts/DEV/waku/node_modules/.pnpm/vite@5.4.0_@types+node@22.4.0_sugarss@4.0.1_postcss@8.4.41__terser@5.31.6/node_modules/vite/dist/node/chunks/dep-NjL7WTE1.js:52844:5)

10:32:54 AM [vite] Error when evaluating SSR module /@fs/Users/ah/SVN-Checkouts/DEV/waku/node_modules/.pnpm/@mantine+dates@7.12.1_@mantine+core@7.12.1_@mantine+hooks@7.12.1_react@19.0.0-rc-68dbd84b-202_44x75gxv2oqotuitlhasvn5g6e/node_modules/@mantine/dates/esm/index.mjs:
|- TypeError: Cannot read properties of undefined (reading 'extend')
    at eval (/Users/ah/SVN-Checkouts/DEV/waku/node_modules/.pnpm/@mantine+dates@7.12.1_@mantine+core@7.12.1_@mantine+hooks@7.12.1_react@19.0.0-rc-68dbd84b-202_44x75gxv2oqotuitlhasvn5g6e/node_modules/@mantine/dates/esm/utils/get-timezone-offset.mjs:11:31)
    at async instantiateModule (file:///Users/ah/SVN-Checkouts/DEV/waku/node_modules/.pnpm/vite@5.4.0_@types+node@22.4.0_sugarss@4.0.1_postcss@8.4.41__terser@5.31.6/node_modules/vite/dist/node/chunks/dep-NjL7WTE1.js:52844:5)

10:32:54 AM [vite] Error when evaluating SSR module /src/components/MyDate.tsx:
|- TypeError: Cannot read properties of undefined (reading 'extend')
    at eval (/Users/ah/SVN-Checkouts/DEV/waku/node_modules/.pnpm/@mantine+dates@7.12.1_@mantine+core@7.12.1_@mantine+hooks@7.12.1_react@19.0.0-rc-68dbd84b-202_44x75gxv2oqotuitlhasvn5g6e/node_modules/@mantine/dates/esm/utils/get-timezone-offset.mjs:11:31)
    at async instantiateModule (file:///Users/ah/SVN-Checkouts/DEV/waku/node_modules/.pnpm/vite@5.4.0_@types+node@22.4.0_sugarss@4.0.1_postcss@8.4.41__terser@5.31.6/node_modules/vite/dist/node/chunks/dep-NjL7WTE1.js:52844:5)
aheissenberger commented 3 weeks ago

Treeshaking is not working and all files from Mantine Library are loaded in the browser on each page (143 requests): pnpm build && pnpm start

SCR-20240817-jtjo
dai-shi commented 3 weeks ago

As for dev error, please try this:

diff --git a/examples/xx_mantine/vite.config.ts b/examples/xx_mantine/vite.confi
g.ts
index 39325f79..a94ea43a 100644
--- a/examples/xx_mantine/vite.config.ts
+++ b/examples/xx_mantine/vite.config.ts
@@ -1,8 +1,9 @@
 export default {
   optimizeDeps: {
-    exclude: ["@mantine/core", "@mantine/hooks","@mantine/dates","dayjs"]
+    include: ["dayjs", "dayjs/plugin/*"],
+    exclude: ["@mantine/core", "@mantine/hooks","@mantine/dates"]
   },
   ssr: {
-    noExternal: ["@mantine/core", "@mantine/hooks","@mantine/dates","dayjs"],
+    noExternal: ["@mantine/core", "@mantine/hooks","@mantine/dates"],
   }
 };
dai-shi commented 3 weeks ago

I'm not sure about treeshaking not working in PRD. Can anyone help? cc @jkhaui

aheissenberger commented 3 weeks ago

@dai-shi I update the configuration and tested all other Mantine Libraries and documented the setup or problems in the README.md of my repo

The Mantine Main Libraries including Dates, Forms and most of the Extentions are working with release 0.21.0-beta.5.

There are Problems with:

aheissenberger commented 3 weeks ago

@dai-shi it works with 0.21.0-beta.5 release but DEV Mode breaks again with Error: @mantine/core: MantineProvider with one of the latest commits d5b19bbeab0ed747a1fed5e32c126b55963dd74d

dai-shi commented 3 weeks ago

That's weird. This seems to improve it.

diff --git a/examples/xx_mantine/vite.config.ts b/examples/xx_mantine/vite.config.ts
index 7440ddf4..8cd43cfa 100644
--- a/examples/xx_mantine/vite.config.ts
+++ b/examples/xx_mantine/vite.config.ts
@@ -10,10 +10,4 @@ export default {
       "@mantine/notifications > prop-types",
     ]
   },
-  ssr: {
-    noExternal: ["@mantine/core", "@mantine/hooks", "@mantine/dates", "@mantine/charts",
-      "@mantine/code-highlight", "@mantine/notifications", "@mantine/spotlight",
-      "@mantine/carousel",
-      "@mantine/dropzone", "@mantine/nprogress", "@mantine/modals", "@mantine/tiptap"],
-  }
 };

What are the remaining problems? (Apart from "tree-shaking not working". Hm, it might be because of prefetching, not related with tree-shaking.)

jkhaui commented 3 weeks ago

@aheissenberger I just thought to try something which is adding the following to waku.config.ts:

export default {
  preserveModuleDirs: ['pages']
}

This change alone dropped no. of network requests in my minimal app from 144 -> 132. Maybe you can investigate this to see if it also treeshakes more unused code (I don't have much spare time atm)

It had always been on my mind to try this, but initially I thought it didn't work because I got a broken app setting preserveModuleDirs: []. Only just then I realised that only pages dir needs to be kept as is to preserve relative paths with the fs router, otherwise I believe everything else should be left to the bundler to do its thing

aheissenberger commented 3 weeks ago

Updated Example which supports the current WAKU release is here: https://github.com/aheissenberger/waku/tree/mantine-test/examples/xx_mantine

preserveModuleDirs in waku.config.ts did not change anything related to the number of requests.