是否可以将 Material UI 作为 peerDependency 但将其类型保留为 DevDependency?

Is it possible to have Material UI as peerDependency but keep its types as DevDependency?

是否可以将 Material UI 作为 peerDependency 但将其类型保留为 DevDependency?

我正在使用 React + Typescript 构建ui组件库,组件基于 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 插入,并使用 peerDepsExternal 插件设置 rollup。当我试图 build 包时,它抛出以下错误:

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 package contains its own type definitions (*.d.ts files), so when I set it as peerDependency, the types/interfaces are missing. To solve this problem, I followed this solution (https://github.com/ezolenko/rollup-plugin-typescript2/issues/198)有关,它在 src/@types/material-ui/index.d.ts 文件中声明了每个模块,但它引发了另一个问题:我不能使用 material-ui types/interfaces 了。

在我的 src/@types/material-ui/index.d.ts 文件中声明了 @material-ui/core,代码指出了下面的错误。

Cannot use namespace 'TextFieldProps' as a type.ts(2709)

Exported type alias 'IInputProps' has or is using private name 'TextFieldProps'.ts(4081)

现在,我只能看到这两个解决方案:

  1. 将整个 material 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
  1. 使用 Material UI 作为 peerDependency,但失去 Material UI types/interfaces 和 lint(通过添加 属性 到我的types/interfaces 接受任何道具 - ).
[x:string]:any

所以,我想知道是否有 任何方法可以将 Material UI 作为 peerDependency 但将其类型保持为 devDependencies,所以我可以将它与 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 also 设置为我的 devDependencies 解决了这个问题。

所以,我的包 json 设置如下:

"peerDependencies": {
    "@material-ui/core": "^4.11.4",
    "react": "^16.8.0",
    "react-dom": "^16.8.0",
},
"devDependencies": {
    "@material-ui/core": "^4.11.4",
    "react": "^16.8.0",
    "react-dom": "^16.8.0",
...

然后我可以摆脱一些配置:

  1. 我删除了我的'src/@types/material-ui/index.d.ts'
  2. 我从 tsconfig.json
  3. 中删除了 '"typeRoots": ["./src/@types"]'

其他配置不变

参考:https://github.com/HarveyD/react-component-library/issues/40