问题描述
是否可以将 Material UI 设为 peerDependency 而将其类型保留为 DevDependency?
我正在使用 React + Typescript 构建一个组件库,这些组件基于 Material UI 库,使用 Rollup 作为模块捆绑器。
这是我的 IInputProps
类型扩展 Material UI TextFieldProps
类型的示例。
import { TextFieldProps } from "@material-ui/core";
export type IInputProps = TextFieldProps & {...}
我的目标是将 Material UI 包设置为 peerDependency,因此它将使用安装在目标项目上的 material-ui 包。我将 Material UI 作为 peerDependency 插入,并使用 rollup
插件设置了 peerDepsExternal
。当我尝试构建包时,它抛出以下错误:
Cannot find module '@material-ui/core' or its corresponding type declarations.
原因与此答案有关 (What's the relationship of @material-ui/core and @types/material-ui?)。 Material-UI 包包含自己的类型定义 (*.d.ts files
),因此当我将其设置为 peerDependency 时,类型/接口丢失。为了解决这个问题,我按照这个解决方案 (https://github.com/ezolenko/rollup-plugin-typescript2/issues/198) 在 src/@types/material-ui/index.d.ts 文件中声明了每个模块,但它引发了另一个问题:我不能使用 material-ui 类型/interfaces 了。
在我的 @material-ui/core
文件中声明了 src/@types/material-ui/index.d.ts
后,代码在下面指出了这个错误。
Cannot use namespace 'TextFieldProps' as a type.ts(2709)
Exported type alias 'IInputProps' has or is using private name 'TextFieldProps'.ts(4081)
现在,我只能看到这两种解决方案:
- 将整个材料 ui 包保存在我的库中,并丢失包大小:
Library with Material UI packages as peerDependency
npm notice package size: 101.0 kB
npm notice unpacked size: 493.6 kB
Library with Material UI packages
npm notice package size: 1.2 MB
npm notice unpacked size: 6.0 MB
- 将 Material UI 用作 peerDependency,但会丢失 Material UI 类型/接口和 lint(通过向我的类型/接口添加一个属性来接受任何属性 - TypeScript interface that allows other properties)。
[x:string]:any
所以,我想知道是否有任何方法可以将 Material UI 设为 peerDependency,但将其类型保留为 devDependency,这样我就可以将它与 Material UI 捆绑为 peerDependency 并使用其类型在我的包裹上?
我的配置如下:
src/@types/material-ui/index.d.ts
declare module "@material-ui/core";
rollup.config.js
import peerDepsExternal from "rollup-plugin-peer-deps-external";
import resolve from "@rollup/plugin-node-resolve";
import commonjs from "@rollup/plugin-commonjs";
import image from "@rollup/plugin-image";
import typescript from "rollup-plugin-typescript2";
const packageJson = require("./package.json");
export default {
input: "src/index.ts", output: [
{
file: packageJson.main, format: "cjs", sourcemap: true
}, {
file: packageJson.module, format: "esm", sourcemap: true
}
], plugins: [
peerDepsExternal(), resolve(), commonjs(), image(), typescript({ useTsconfigDeclarationDir: true })
]
};
tsconfig.json
{
"compilerOptions": {
"rootDir": "src", "declaration": true, "declarationDir": "build", "module": "esnext", "target": "es5", "lib": ["es6","dom","es2016","es2017"], "sourceMap": true, "jsx": "react", "moduleResolution": "node", "allowSyntheticDefaultImports": true, "esModuleInterop": true, "typeRoots": ["./src/@types"]
}, "include": ["src/**/*"], "exclude": [
"node_modules", "build", "storybook-static", "src/**/*.stories.tsx", "src/**/*.test.tsx"
]
}
package.json
...
"main": "build/index.js", "module": "build/index.esm.js",..., "peerDependencies": {
"@material-ui/core": "^4.11.4", "react": "^16.8.0", "react-dom": "^16.8.0", },...
解决方法
如果您希望使用“外部”@material-ui/core
(即不是汇总的一部分),您应该这样指定。
Rollup 实际上在对等依赖项上有 documentation,它确实指定使用 externals
,例如 lodash
:
// rollup.config.js
import resolve from '@rollup/plugin-node-resolve';
export default {
input: 'src/main.js',output: {
file: 'bundle.js',format: 'cjs'
},plugins: [resolve({
// pass custom options to the resolve plugin
customResolveOptions: {
moduleDirectory: 'node_modules'
}
})],// indicate which modules should be treated as external
external: ['lodash']
};
,
我通过将所有 peerDependencies 也 设置为我的 devDependencies 解决了这个问题。
所以,我的包 json 设置如下:
.as-console-wrapper { min-height: 100%!important; top: 0; }
然后我可以摆脱一些配置:
- 我删除了我的“src/@types/material-ui/index.d.ts”
- 我从 tsconfig.json 中删除了 '"typeRoots": ["./src/@types"]'
所有其他配置保持不变。
参考:https://github.com/HarveyD/react-component-library/issues/40