Repository: material-ui
Issue: [ESM] Publish packages in ESM module format
Labels: breaking change,enhancement,scope: code-infra

### Why

- Run untranspiled on server environments (e.g. Next.js `experimental.esmxternals`). Could help with [https://github.com/mui-org/material-ui/issues/29742#issuecomment-982597676](https://github.com/mui-org/material-ui/issues/29742#issuecomment-982597676) to give `babel-plugin-styled-components` a source that is easier to statically analyze.
- Snowpack has trouble serving our library: https://github.com/mui-org/material-ui/issues/28628
It looks like it’s trying to convert back the commonjs version into ESM and getting confused (this is a non-deterministic process, best effort). It seems to resolve the package specifier to the commonjs module instead of ESM
- Next.js [supports ESM](https://nextjs.org/blog/next-11-1#es-modules-support) by default in v12
- Issues [with vite module ordering](https://github.com/vitejs/vite/issues/12423) which seem to get resolved when packages have exports defined
- Issues around mixed cjs/esm imports when using icons-material both in Next.js and vite https://github.com/mui/material-ui/issues/35233

### How

- [x] Early attempt: https://github.com/mui-org/material-ui/pull/30510
- [ ] Figure out what happened with these PRs and verify whether the problem is still relevant:
  - https://github.com/mui-org/material-ui/pull/26310 
  - https://github.com/mui-org/material-ui/pull/26656
- [ ] In our build output, make sure ESM files get the extension `.mjs`. We can probably start with this and maybe even release on a minor
- [ ] `package.json`: dual ESM/commonjs: https://nodejs.org/api/packages.html#dual-commonjses-module-packages
    - Add exports field, let's leave out the `"type": "module"` until v7?
    - We should do this one one  major (v6)
- [ ] Internal imports will need file extensions https://github.com/jaydenseric/babel-plugin-transform-require-extensions. We can probably also consider releasing this on a  minor version
- [ ] How do we deal with `process.env.NODE_ENV` (e.g. https://github.com/mui-org/material-ui/blob/1230b1a571942f1abf2fec81812b757ceb0e5d0b/packages/mui-system/src/spacing.js#L104)? It will break when run as a module in the browser.
     Perhaps:
    
    ```jsx
    // This way it won't break uncompiled, but webpack can still 
    // replace `process.env.NODE_ENV`
    import process from './process'
    
    // ...
          if (process.env.NODE_ENV !== 'production') {
            if (typeof abs !== 'number') {
              console.error(
                `MUI: Expected ${propName} argument to be a number or a string, got ${abs}.`,
              );
            }
          }
    // ...
    
    // ./process.js
    // Gracefully handle being run in the browser
    export default typeof process === 'undefined' ? { env: {} } : process;
    ```
    
- [ ] This doesn't work with react <=17: **[Bug: Cannot import 'react/jsx-runtime' from esm node/webpack 5 facebook/react#20235](https://github.com/facebook/react/issues/20235)**, We may be stuck on this until package exports are backported to react 17 (or when we can bump our `react` peer dependency >=18).