【问题标题】:Rollup bundling peer dependencies / Multiple instances of MUI make the ThemeProvider not work汇总捆绑对等依赖项 / MUI 的多个实例使 ThemeProvider 不起作用
【发布时间】:2022-01-14 12:23:29
【问题描述】:

我正在处理两个不同的存储库,libapps

  • lib 有一些使用 MUI 制作的 React 组件,我想在 apps 中使用它们,这些组件是使用 Rollup 构建的。

  • apps 是带有 Next.js 应用程序的 Lerna monorepo,该应用程序将 lib 作为依赖项导入以使用其组件,可以自定义将它们包装在具有自定义主题的 <ThemeProvider> 中。

但是,这不起作用,因为有重复的 MUI / ThemeProvider 实例,我可以通过将其添加到 lib 的入口点来验证:

if (process.browser) {
  (window as any)._React = React;
  (window as any)._ThemeProvider = ThemeProvider;
}

然后这个变成apps':

if (process.browser) {
  const {
    _React,
    _ThemeProvider,
  } = window as any;

  console.log(_React ? (_React === React ? "✅ Unique React" : "❌ Duplicate React") : "-");
  console.log(_ThemeProvider ? (_ThemeProvider === ThemeProvider ? "✅ Unique ThemeProvider" : "❌ Duplicate ThemeProvider") : "-");
}

哪些打印:

✅ Unique React
❌ Duplicate ThemeProvider

libapp 中的组件用法如下所示:

<ThemeProvider theme={ MY_CUSTOM_THEME }>
  <MyComponent{ ...myComponentProps } />
</ThemeProvider>

MyComponentMY_CUSTOM_THEME 都是从 lib 导入的,而 ThemeProvider 是从 @mui/material/styles 导入的,就像在 lib 中一样。

但是,所有 MUI 组件都将以默认主题显示。

以下是两个 repos 的一些相关构建文件:

lib &gt; package.json:

{
  "name": "@myscope/lib",
  "version": "1.0.0-alpha",
  "description": "",
  "main": "dist/cjs/src/index.js",
  "module": "dist/esm/src/index.js",
  "types": "dist/index.d.ts",
  "files": [
    "dist"
  ],
  "private": true,
  "scripts": {
    "build": "rollup -c",
  },
  "dependencies": {
    "@apollo/client": "^3.4.5",
    "@apollo/link-context": "^2.0.0-beta.3",
    "@hookform/resolvers": "^2.8.5",
    "@mui/icons-material": "^5.0.4",
    "@swyg/corre": "^1.0.1",
    "apollo-upload-client": "^16.0.0",
    "atob": "^2.1.2",
    "axios": "^0.24.0",
    "btoa": "^1.2.1",
    "country-codes-list": "^1.6.8",
    "country-region-data": "^1.6.0",
    "next": "^11.0.1",
    "next-images": "^1.8.2",
    "openpgp": "^5.0.0",
    "react-hook-form": "^7.22.0",
    "react-payment-inputs": "^1.1.8",
    "react-use-country-region": "^1.0.0",
    "styled-components": "^5.3.0",
    "use-callback-ref": "^1.2.5",
    "uuidv4": "^6.2.12",
    "yup": "^0.32.11"
  },
  "peerDependencies": {
    "@mui/material": "^5.0.4",
    "react-dom": "^17.0.2",
    "react": "^17.0.2"
  },
  "devDependencies": {
    "@auth0/auth0-react": "^1.6.0",
    "@babel/preset-react": "^7.16.7",
    "@emotion/react": "^11.5.0",
    "@emotion/styled": "^11.3.0",
    "@graphql-codegen/cli": "^1.21.5",
    "@graphql-codegen/introspection": "^1.18.2",
    "@graphql-codegen/typescript-operations": "^1.18.0",
    "@graphql-codegen/typescript-react-apollo": "^2.2.5",
    "@graphql-codegen/typescript": "^1.22.1",
    "@mui/material": "^5.2.8",
    "@rollup/plugin-babel": "^5.3.0",
    "@rollup/plugin-commonjs": "^21.0.1",
    "@rollup/plugin-node-resolve": "^13.1.2",
    "@rollup/plugin-typescript": "^8.3.0",
    "@testing-library/dom": "^8.1.0",
    "@testing-library/jest-dom": "^5.14.1",
    "@testing-library/react": "^12.0.0",
    "@testing-library/user-event": "^13.2.1",
    "@types/jest": "^26.0.24",
    "@types/react-dom": "^17.0.11",
    "@types/react": "^17.0.16",
    "@types/styled-components": "^5.1.12",
    "@typescript-eslint/eslint-plugin": "^4.29.0",
    "@typescript-eslint/parser": "^4.29.0",
    "babel-jest": "^27.0.6",
    "babel-plugin-styled-components": "^2.0.2",
    "eslint-config-next": "^11.0.1",
    "eslint-config-prettier": "^8.3.0",
    "eslint-plugin-react-hooks": "^4.2.0",
    "eslint-plugin-unused-imports": "^1.1.2",
    "eslint": "^7.32.0",
    "graphql": "^16.2.0",
    "jest": "^27.0.6",
    "prettier": "^2.3.2",
    "rollup-plugin-dts": "^4.1.0",
    "rollup-plugin-node-externals": "^3.1.2",
    "rollup-plugin-peer-deps-external": "^2.2.4",
    "rollup-plugin-typescript2": "^0.31.1",
    "rollup": "^2.63.0",
    "ts-jest": "^27.0.4",
    "typescript": "^4.3.5"
  }
}

请注意@mui/material 出现在peerDependenciesdevDependencies 中,但不出现在reactrect-dom 中,它们仅列为peerDependencies。这是因为有 @types/react@types/react-dom,但 MUI 没有类似的东西,所以如果找不到正确的类型,Rollup 构建就会失败。

lib &gt; rollup.config.js:

import commonjs from '@rollup/plugin-commonjs';
import dts from 'rollup-plugin-dts'
import resolve from "@rollup/plugin-node-resolve";
import typescript from 'rollup-plugin-typescript2'
import babel from '@rollup/plugin-babel'

import pkg from "./package.json";

// Extensions handled by babel:
const EXTENSIONS = [".ts", ".tsx"];

// Exclude dev and peer dependencies:
const EXTERNAL = [
  ...Object.keys(pkg.devDependencies),
  ...Object.keys(pkg.peerDependencies),
];

export default [{
    input: 'src/index.ts',

    output: [{
        dir: "dist/esm",
        sourcemap: true,
        format: "esm",
        preserveModules: true,
        globals: {
          react: "React",
        },
    }, {
        dir: "dist/cjs",
        sourcemap: true,
        format: "cjs",
        preserveModules: true,
        globals: {
          react: "React",
        },
    }],

    external: EXTERNAL,
    
    plugins: [
       resolve(),

        commonjs({
            exclude: "node_modules",
            ignoreGlobal: true,
        }),

        typescript({
          useTsconfigDeclarationDir: true,
          tsconfig: "rollup.tsconfig.json",
        }),
    ],

}, {
    input: './dist/types/src/index.d.ts',
    output: [{ file: './dist/index.d.ts', format: "esm" }],
    external: EXTERNAL,
    plugins: [dts()],
}];

apps &gt; lerna.json:

{
  "packages": ["apps/**/*", "packages/**/*"],
  "version": "0.0.1",
  "npmClient": "yarn",
  "useWorkspaces": true
}

apps &gt; package.json:

...
"dependencies": {
    "@myscope/lib": "file:../lib"
},
...

请注意,这是一个 file: 导入,只是为了更轻松地开发和测试更改。

我也尝试将resolutions 添加到apps &gt; package.jsonapps &gt; app &gt; package.json,但也没有运气......:

"resolutions": {
  "@mui/material": "5.2.8"
}

【问题讨论】:

    标签: npm material-ui next.js rollup lerna


    【解决方案1】:

    这可能不是最好的解决方案,但我通过从lib 导出ThemeProvider 解决了这个问题:

    export { ThemeProvider as MyComponentThemeProvider } from "@mui/material/styles";
    

    现在,当在app 中使用这个时:

    <MyComponentThemeProvider theme={ MY_CUSTOM_THEME }>
      <MyComponent{ ...myComponentProps } />
    </MyComponentThemeProvider>
    

    一切都按预期进行:

    ✅ Unique React
    ✅ Unique ThemeProvider
    

    另外,看看https://github.com/facebook/react/issues/19541

    【讨论】:

      猜你喜欢
      • 2021-10-25
      • 2021-10-22
      • 1970-01-01
      • 2018-04-18
      • 1970-01-01
      • 2017-12-02
      • 2020-08-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多