I have two different repos I'm working on, lib
and apps
.
lib
has some React components made with MUI that I want to consume inapps
, and that's built with Rollup.apps
is a Lerna monorepo with a Next.js app that importslib
as a dependency to consume its components, which can be customized wrapping them in a<ThemeProvider>
with a custom theme.
However, that doesn't work because there are duplicated instances of MUI / ThemeProvider
, which I was able to verify by adding this to lib
's entry point:
if (process.browser) {
(window as any)._React = React;
(window as any)._ThemeProvider = ThemeProvider;
}
And then this into 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") : "-");
}
Which prints:
✅ Unique React
❌ Duplicate ThemeProvider
lib
's component usage in app
looks like this:
<ThemeProvider theme={ MY_CUSTOM_THEME }>
<MyComponent{ ...myComponentProps } />
</ThemeProvider>
Where both MyComponent
and MY_CUSTOM_THEME
are imported from lib
, while ThemeProvider
is imported from @mui/material/styles
, just like it is in lib
.
However, all MUI components will be displayed with the default theme.
Here are some of the relevant build files for both repos:
lib > 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"
}
}
Note that @mui/material
appears both in peerDependencies
and devDependencies
, but not react
or rect-dom
, which are only listed as peerDependencies
. That's because there's @types/react
and @types/react-dom
, but nothing similar for MUI, so the Rollup build would fail if it can't find the right types.
lib > 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 > lerna.json
:
{
"packages": ["apps/**/*", "packages/**/*"],
"version": "0.0.1",
"npmClient": "yarn",
"useWorkspaces": true
}
apps > package.json
:
...
"dependencies": {
"@myscope/lib": "file:../lib"
},
...
Note this is a file:
import just to make it easier to develop and test changes.
I've also tried adding resolutions
to both apps > package.json
and apps > app > package.json
, but no luck with that either...:
"resolutions": {
"@mui/material": "5.2.8"
}
rollup.config.js
you can see there'sexternal: EXTERNAL
which should have the same effect. – Shawandaimport external from 'rollup-plugin-peer-deps-external';
and use it in the plugins section:// eslint-disable-next-line @typescript-eslint/no-unsafe-call
external(),
I have mine listed as the first plugin. There may be a reason for that. Also, I haven't found a way around the TypeScript warning, so thats why I disabled it. Hope that helps. Not sure if you're still having an issue or not. Just happened to see your post while trying to find an answer to the TS warning – Weidman