Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

[material-ui] Compatibility issues with Remix #44993

Open
davidbielik opened this issue Jan 12, 2025 · 12 comments
Open

[material-ui] Compatibility issues with Remix #44993

davidbielik opened this issue Jan 12, 2025 · 12 comments
Assignees
Labels
bug 🐛 Something doesn't work package: material-ui Specific to @mui/material

Comments

@davidbielik
Copy link

davidbielik commented Jan 12, 2025

Steps to reproduce

Steps:

  1. Install remix defaults npx create-remix@latest remix-mui-bug
  2. Install mui defaults npm install @mui/material @emotion/react @emotion/styled
  3. Import and add any MUI component, like a <Button>

Current behavior

Hydration errors (and also for some reason the button converts from variant="contained" to variant="text" upon hydration?)

 Warning: Prop `charSet` did not match. Server: "null" Client: "utf-8" Error Component Stack
    at meta (<anonymous>)
    at head (<anonymous>)
    at html (<anonymous>)
    at Layout (root.tsx:25:26)


Uncaught Error: Hydration failed because the initial UI does not match what was rendered on the server.
    at throwOnHydrationMismatch (react-dom.development.js:12507:9)
    at tryToClaimNextHydratableInstance (react-dom.development.js:12535:7)
    at updateHostComponent (react-dom.development.js:19931:5)
    at beginWork (react-dom.development.js:21657:14)
    at HTMLUnknownElement.callCallback2 (react-dom.development.js:4164:14)
    at Object.invokeGuardedCallbackDev (react-dom.development.js:4213:16)
    at invokeGuardedCallback (react-dom.development.js:4277:31)
    at beginWork$1 (react-dom.development.js:27490:7)
    at performUnitOfWork (react-dom.development.js:26596:12)
    at workLoopConcurrent (react-dom.development.js:26582:5)
image

Expected behavior

I should be able to npm install mui and not have hydration errors

Context

I followed the advice here: #39765 by adding this provider but still seeing the error

Your environment

npx @mui/envinfo
  System:
    OS: macOS 14.4.1
  Binaries:
    Node: 20.11.1 - ~/.asdf/installs/nodejs/20.11.1/bin/node
    npm: 10.2.4 - ~/.asdf/plugins/nodejs/shims/npm
    pnpm: 8.15.5 - ~/.asdf/installs/nodejs/20.11.1/bin/pnpm
  Browsers:
    Chrome: 131.0.6778.265
    Edge: Not Found
    Safari: 17.4.1
  npmPackages:
    @emotion/react: ^11.14.0 => 11.14.0 
    @emotion/styled: ^11.14.0 => 11.14.0 
    @mui/core-downloads-tracker:  6.3.1 
    @mui/material: ^6.3.1 => 6.3.1 
    @mui/private-theming:  6.3.1 
    @mui/styled-engine:  6.3.1 
    @mui/system:  6.3.1 
    @mui/types:  7.2.21 
    @mui/utils:  6.3.1 
    @types/react: ^18.2.20 => 18.3.18 
    react: ^18.2.0 => 18.3.1 
    react-dom: ^18.2.0 => 18.3.1 
    typescript: ^5.1.6 => 5.7.3

Search keywords: remix Warning: Prop charSet did not match. Server: "null" Client: "utf-8" Error Component Stack

@davidbielik davidbielik added the status: waiting for maintainer These issues haven't been looked at yet by a maintainer label Jan 12, 2025
@davidbielik
Copy link
Author

Updates:

swapping react dependencies to canary versions remove that hydration issue and solve the contained/text issue, but shows a different error:

-"react": "^18.2.0",
-"react-dom": "^18.2.0"
+"react": "18.3.0-canary-01ab35a9a-20240228",
+"react-dom": "18.3.0-canary-01ab35a9a-20240228",
New hydration error
hook.js:608 Warning: Prop `dangerouslySetInnerHTML` did not match. Server: ".css-1x9p500-MuiButton-root{font-family:\"Roboto\",\"Helvetica\",\"Arial\",sans-serif;font-weight:500;font-size:0.875rem;line-height:1.75;letter-spacing:0.02857em;text-transform:uppercase;min-width:64px;padding:6px 16px;border:0;border-radius:4px;-webkit-transition:background-color 250ms cubic-bezier(0.4, 0, 0.2, 1) 0ms,box-shadow 250ms cubic-bezier(0.4, 0, 0.2, 1) 0ms,border-color 250ms cubic-bezier(0.4, 0, 0.2, 1) 0ms,color 250ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;transition:background-color 250ms cubic-bezier(0.4, 0, 0.2, 1) 0ms,box-shadow 250ms cubic-bezier(0.4, 0, 0.2, 1) 0ms,border-color 250ms cubic-bezier(0.4, 0, 0.2, 1) 0ms,color 250ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;color:var(--variant-containedColor);background-color:var(--variant-containedBg);box-shadow:0px 3px 1px -2px rgba(0,0,0,0.2),0px 2px 2px 0px rgba(0,0,0,0.14),0px 1px 5px 0px rgba(0,0,0,0.12);--variant-textColor:#1976d2;--variant-outlinedColor:#1976d2;--variant-outlinedBorder:rgba(25, 118, 210, 0.5);--variant-containedColor:#fff;--variant-containedBg:#1976d2;}.css-1x9p500-MuiButton-root:hover{-webkit-text-decoration:none;text-decoration:none;}.css-1x9p500-MuiButton-root.Mui-disabled{color:rgba(0, 0, 0, 0.26);}.css-1x9p500-MuiButton-root:hover{box-shadow:0px 2px 4px -1px rgba(0,0,0,0.2),0px 4px 5px 0px rgba(0,0,0,0.14),0px 1px 10px 0px rgba(0,0,0,0.12);}@media (hover: none){.css-1x9p500-MuiButton-root:hover{box-shadow:0px 3px 1px -2px rgba(0,0,0,0.2),0px 2px 2px 0px rgba(0,0,0,0.14),0px 1px 5px 0px rgba(0,0,0,0.12);}}.css-1x9p500-MuiButton-root:active{box-shadow:0px 5px 5px -3px rgba(0,0,0,0.2),0px 8px 10px 1px rgba(0,0,0,0.14),0px 3px 14px 2px rgba(0,0,0,0.12);}.css-1x9p500-MuiButton-root.Mui-focusVisible{box-shadow:0px 3px 5px -1px rgba(0,0,0,0.2),0px 6px 10px 0px rgba(0,0,0,0.14),0px 1px 18px 0px rgba(0,0,0,0.12);}.css-1x9p500-MuiButton-root.Mui-disabled{color:rgba(0, 0, 0, 0.26);box-shadow:none;background-color:rgba(0, 0, 0, 0.12);}@media (hover: hover){.css-1x9p500-MuiButton-root:hover{--variant-containedBg:#1565c0;--variant-textBg:rgba(25, 118, 210, 0.04);--variant-outlinedBorder:#1976d2;--variant-outlinedBg:rgba(25, 118, 210, 0.04);}}" Client: "\n/* /app/tailwind.css */\n*, ::before, ::after {\n  --tw-border-spacing-x: 0;\n  --tw-border-spacing-y: 0;\n  --tw-translate-x: 0;\n  --tw-translate-y: 0;\n  --tw-rotate: 0;\n  --tw-skew-x: 0;\n  --tw-skew-y: 0;\n  --tw-scale-x: 1;\n  --tw-scale-y: 1;\n  --tw-pan-x:  ;\n  --tw-pan-y:  ;\n  --tw-pinch-zoom:  ;\n  --tw-scroll-snap-strictness: proximity;\n  --tw-gradient-from-position:  ;\n  --tw-gradient-via-position:  ;\n  --tw-gradient-to-position:  ;\n  --tw-ordinal:  ;\n  --tw-slashed-zero:  ;\n  --tw-numeric-figure:  ;\n  --tw-numeric-spacing:  ;\n  --tw-numeric-fraction:  ;\n  --tw-ring-inset:  ;\n  --tw-ring-offset-width: 0px;\n  --tw-ring-offset-color: #fff;\n  --tw-ring-color: rgb(59 130 246 / 0.5);\n  --tw-ring-offset-shadow: 0 0 #0000;\n  --tw-ring-shadow: 0 0 #0000;\n  --tw-shadow: 0 0 #0000;\n  --tw-shadow-colored: 0 0 #0000;\n  --tw-blur:  ;\n  --tw-brightness:  ;\n  --tw-contrast:  ;\n  --tw-grayscale:  ;\n  --tw-hue-rotate:  ;\n  --tw-invert:  ;\n  --tw-saturate:  ;\n  --tw-sepia:  ;\n  --tw-drop-shadow:  ;\n  --tw-backdrop-blur:  ;\n  --tw-backdrop-brightness:  ;\n  --tw-backdrop-contrast:  ;\n  --tw-backdrop-grayscale:  ;\n  --tw-backdrop-hue-rotate:  ;\n  --tw-backdrop-invert:  ;\n  --tw-backdrop-opacity:  ;\n  --tw-backdrop-saturate:  ;\n  --tw-backdrop-sepia:  ;\n  --tw-contain-size:  ;\n  --tw-contain-layout:  ;\n  --tw-contain-paint:  ;\n  --tw-contain-style:  ;\n}\n\n::backdrop {\n  --tw-border-spacing-x: 0;\n  --tw-border-spacing-y: 0;\n  --tw-translate-x: 0;\n  --tw-translate-y: 0;\n  --tw-rotate: 0;\n  --tw-skew-x: 0;\n  --tw-skew-y: 0;\n  --tw-scale-x: 1;\n  --tw-scale-y: 1;\n  --tw-pan-x:  ;\n  --tw-pan-y:  ;\n  --tw-pinch-zoom:  ;\n  --tw-scroll-snap-strictness: proximity;\n  --tw-gradient-from-position:  ;\n  --tw-gradient-via-position:  ;\n  --tw-gradient-to-position:  ;\n  --tw-ordinal:  ;\n  --tw-slashed-zero:  ;\n  --tw-numeric-figure:  ;\n  --tw-numeric-spacing:  ;\n  --tw-numeric-fraction:  ;\n  --tw-ring-inset:  ;\n  --tw-ring-offset-width: 0px;\n  --tw-ring-offset-color: #fff;\n  --tw-ring-color: rgb(59 130 246 / 0.5);\n  --tw-ring-offset-shadow: 0 0 #0000;\n  --tw-ring-shadow: 0 0 #0000;\n  --tw-shadow: 0 0 #0000;\n  --tw-shadow-colored: 0 0 #0000;\n  --tw-blur:  ;\n  --tw-brightness:  ;\n  --tw-contrast:  ;\n  --tw-grayscale:  ;\n  --tw-hue-rotate:  ;\n  --tw-invert:  ;\n  --tw-saturate:  ;\n  --tw-sepia:  ;\n  --tw-drop-shadow:  ;\n  --tw-backdrop-blur:  ;\n  --tw-backdrop-brightness:  ;\n  --tw-backdrop-contrast:  ;\n  --tw-backdrop-grayscale:  ;\n  --tw-backdrop-hue-rotate:  ;\n  --tw-backdrop-invert:  ;\n  --tw-backdrop-opacity:  ;\n  --tw-backdrop-saturate:  ;\n  --tw-backdrop-sepia:  ;\n  --tw-contain-size:  ;\n  --tw-contain-layout:  ;\n  --tw-contain-paint:  ;\n  --tw-contain-style:  Error Component Stack
    at style (<anonymous>)
    at head (<anonymous>)
    at html (<anonymous>)
    at Layout (root.tsx:25:26)

@zannager zannager added the package: material-ui Specific to @mui/material label Jan 13, 2025
@mnajdova mnajdova assigned siriwatknp and unassigned DiegoAndai Jan 14, 2025
@davidbielik
Copy link
Author

After more testing, the only way to have it barely functional was to add

// vite.config.ts
ssr: {
  noExternal: [
        /^@mui/
  ]
}

But this results in extreme slowness ~35 seconds to render a page.

Is the answer that MUI doesn't work with Vite/Remix and we should wait until "true ESM Support"?

@DiegoAndai DiegoAndai assigned DiegoAndai and unassigned siriwatknp Jan 15, 2025
@DiegoAndai
Copy link
Member

DiegoAndai commented Jan 15, 2025

Hey @davidbielik, thanks for reaching out.

May I ask you to test this resolution on your package.json:

"resolutions": {
    "@mui/material": "https://pkg.csb.dev/mui/material-ui/commit/8a28484f/@mui/material",
    "@mui/material-pigment-css": "https://pkg.csb.dev/mui/material-ui/commit/8a28484f/@mui/material-pigment-css",
    "@mui/private-theming": "https://pkg.csb.dev/mui/material-ui/commit/8a28484f/@mui/private-theming",
    "@mui/styled-engine": "https://pkg.csb.dev/mui/material-ui/commit/8a28484f/@mui/styled-engine",
    "@mui/styles": "https://pkg.csb.dev/mui/material-ui/commit/8a28484f/@mui/styles",
    "@mui/system": "https://pkg.csb.dev/mui/material-ui/commit/8a28484f/@mui/system",
    "@mui/types": "https://pkg.csb.dev/mui/material-ui/commit/8a28484f/@mui/types",
    "@mui/utils": "https://pkg.csb.dev/mui/material-ui/commit/8a28484f/@mui/utils",
  },

And removing the noExternal rule?

This is to test if #43264 would fix it.

@DiegoAndai DiegoAndai added status: waiting for author Issue with insufficient information and removed status: waiting for maintainer These issues haven't been looked at yet by a maintainer labels Jan 15, 2025
@DiegoAndai DiegoAndai changed the title MUI not compatible with Remix [material-ui] Not compatible with Remix Jan 15, 2025
@DiegoAndai DiegoAndai changed the title [material-ui] Not compatible with Remix [material-ui] Compatibility issues with Remix Jan 15, 2025
@davidbielik
Copy link
Author

davidbielik commented Jan 15, 2025

Hi @DiegoAndai thanks - here's the result.

10:59:49 AM [vite] (ssr) Error when evaluating SSR module virtual:remix/server-build:
|- remix/node_modules/@mui/icons-material/esm/index.js:1
export { default as Abc } from "./Abc.js";
^^^^^^

SyntaxError: Unexpected token 'export'
    at internalCompileFunction (node:internal/vm:77:18)
    at wrapSafe (node:internal/modules/cjs/loader:1288:20)
    at Module._compile (node:internal/modules/cjs/loader:1340:27)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1435:10)
    at Module.load (node:internal/modules/cjs/loader:1207:32)
    at Function.Module._load (node:internal/modules/cjs/loader:1023:12)
    at cjsLoader (node:internal/modules/esm/translators:356:17)
    at ModuleWrap.<anonymous> (node:internal/modules/esm/translators:305:7)
    at ModuleJob.run (node:internal/modules/esm/module_job:218:25)
    at ModuleLoader.import (node:internal/modules/esm/loader:329:24)

10:59:49 AM [vite] Internal server error: Unexpected token 'export'
      at internalCompileFunction (node:internal/vm:77:18)
      at wrapSafe (node:internal/modules/cjs/loader:1288:20)
      at Module._compile (node:internal/modules/cjs/loader:1340:27)
      at Object.Module._extensions..js (node:internal/modules/cjs/loader:1435:10)
      at Module.load (node:internal/modules/cjs/loader:1207:32)
      at Function.Module._load (node:internal/modules/cjs/loader:1023:12)
      at cjsLoader (node:internal/modules/esm/translators:356:17)
      at ModuleWrap.<anonymous> (node:internal/modules/esm/translators:305:7)
      at ModuleJob.run (node:internal/modules/esm/module_job:218:25)
      at ModuleLoader.import (node:internal/modules/esm/loader:329:24)
import { vitePlugin as remix } from '@remix-run/dev';
import react from '@vitejs/plugin-react-swc';
import { defineConfig } from 'vite';
import tsconfigPaths from 'vite-tsconfig-paths';

declare module '@remix-run/node' {
  interface Future {
    v3_singleFetch: true;
  }
}

export default defineConfig({
  plugins: [
    react({}),
    remix({
      future: {
        v3_fetcherPersist: true,
        v3_relativeSplatPath: true,
        v3_throwAbortReason: true,
        v3_singleFetch: true,
        v3_lazyRouteDiscovery: true,
      },
    }),
    tsconfigPaths(),
  ],
  ssr: {
    noExternal: [],
  },
  optimizeDeps: {
    include: [],
  },
});

@github-actions github-actions bot added status: waiting for maintainer These issues haven't been looked at yet by a maintainer and removed status: waiting for author Issue with insufficient information labels Jan 15, 2025
@DiegoAndai
Copy link
Member

And what do you get when adding:

// vite.config.ts
ssr: {
  noExternal: [
        /^@mui\/icons-material/
  ]
}

@DiegoAndai DiegoAndai added status: waiting for author Issue with insufficient information and removed status: waiting for maintainer These issues haven't been looked at yet by a maintainer labels Jan 15, 2025
@davidbielik
Copy link
Author

That works, though just adding mui increases load time from < 50m up to ~10 seconds, even in a production build.

The only thing I've added was MUI

@github-actions github-actions bot added status: waiting for maintainer These issues haven't been looked at yet by a maintainer and removed status: waiting for author Issue with insufficient information labels Jan 15, 2025
@DiegoAndai
Copy link
Member

DiegoAndai commented Jan 15, 2025

Ok, so it seems this would be fixed by #43264. Thanks for the quick response.

May I ask you to do a final test with:

"resolutions": {
    "@mui/material": "https://pkg.csb.dev/mui/material-ui/commit/2422d845/@mui/material",
    "@mui/material-pigment-css": "https://pkg.csb.dev/mui/material-ui/commit/2422d845/@mui/material-pigment-css",
    "@mui/private-theming": "https://pkg.csb.dev/mui/material-ui/commit/2422d845/@mui/private-theming",
    "@mui/styled-engine": "https://pkg.csb.dev/mui/material-ui/commit/2422d845/@mui/styled-engine",
    "@mui/styles": "https://pkg.csb.dev/mui/material-ui/commit/2422d845/@mui/styles",
    "@mui/system": "https://pkg.csb.dev/mui/material-ui/commit/2422d845/@mui/system",
    "@mui/types": "https://pkg.csb.dev/mui/material-ui/commit/2422d845/@mui/types",
    "@mui/utils": "https://pkg.csb.dev/mui/material-ui/commit/2422d845/@mui/utils",
  },

And no noExternal? Does that reduce the load time?

@DiegoAndai DiegoAndai added status: waiting for author Issue with insufficient information and removed status: waiting for maintainer These issues haven't been looked at yet by a maintainer labels Jan 15, 2025
@davidbielik
Copy link
Author

empty noExternal:

[vite] Error when evaluating SSR module virtual:remix/server-build: failed to import "@mui/icons-material"
|- /Users/david.bielik/Downloads/remix-mui-bug/node_modules/@mui/icons-material/esm/index.js:1
export { default as Abc } from "./Abc.js";

 ssr: {
    noExternal: [/^@mui\/icons-material/],
  },

Still ~4 seconds + hydration error

A tree hydrated but some attributes of the server rendered HTML didn't match the client properties. This won't be patched up. This can happen if a SSR-ed Client Component used:

@github-actions github-actions bot added status: waiting for maintainer These issues haven't been looked at yet by a maintainer and removed status: waiting for author Issue with insufficient information labels Jan 15, 2025
@DiegoAndai DiegoAndai added bug 🐛 Something doesn't work and removed status: waiting for maintainer These issues haven't been looked at yet by a maintainer labels Jan 16, 2025
@DiegoAndai
Copy link
Member

I created a repro: https://github.com/DiegoAndai/material-ui-issue-44993-repro

There's definitely something not working, I'll continue investigating

@DiegoAndai
Copy link
Member

Hey @davidbielik, I got my repro working with these changes: DiegoAndai/material-ui-issue-44993-repro@2287c6b (This is only a test, that @mui/material build is not production ready)

May I ask you if you might've also been missing the react plugin in your vite config?

@stabback
Copy link

stabback commented Feb 9, 2025

Hey @DiegoAndai I'm also attempting to figure out why I've got a number of warnings going on with Remix and MUI. This thread appears to be top of (at least my) Google search for Warning: PropcharSet did not match. Server: "null" Client: "utf-8" Error.

May I ask you if you might've also been missing the react plugin in your vite config?

The Remix plugin should be handling the stuff the React plugin would normally handle. Having both plugins leads to some duplication.

If you pull down your repro and run pnpm dev, you'll notice that you've got a new error in the console:

Uncaught SyntaxError: Identifier 'RefreshRuntime' has already been declared (at root.tsx:2:1)

HMR appears non functional when both plugins are used at once.

@stabback
Copy link

stabback commented Feb 10, 2025

So I poked around with this a bit more, and have a solution that doesn't have any console warnings or errors, but does have some cavaets.

You can find it here: https://github.com/stabback/material-ui-issue-44993-repro (just check the commits authored by me since the fork)

Notably:

  1. I upgraded to React 19. There's some chatter about Remix / MUI hydration not working great in 18.2.0 (and 18.3.0, which just adds migration helpers).
  2. After upgrading to 19, there were new hydration errors, but they were around Tailwind. I removed it as I don't use tailwind (and I don't know why one would with MUI). After removing, they of course went away.

I've also tested to make sure theming still works (in case the tailwind issue was indicative of a wider styling concern) and can confirm that MUI useTheme and sx props are still working.

Also worth noting - MUI 6.4.3 blows up with this. I need to use the versions from the commit @DiegoAndai was previously using. It'd be great to better understand when that work will be made public.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug 🐛 Something doesn't work package: material-ui Specific to @mui/material
Projects
None yet
Development

No branches or pull requests

5 participants