我开发了一个自定义 React 组件库,可以在私有 npm 上使用。我的所有组件都是 Typescript React 类组件,在许多组件中我使用接口来声明哪些 props 是可选的或必需的。示例:
export interface ICardLinkProps {
Title: string;
Description: string;
ActionText: string;
DestinationUrl?: string;
ImageUrl?: string;
Icon?: string;
Theme: Theme;
}
export class CardLink extends React.Component<ICardLinkProps> {
/// component Code.
}
所有组件都按预期工作,但是当我的同事安装解包时,智能感知不会显示所需的道具。示例:
相比之下,如果我使用 Material-UI 中的组件,智能感知会显示所有必需和可选的道具。
有人知道为什么我的组件没有获得智能感知吗?我正在使用 rollup 导出构建包,这是我的配置:
import typescript from "rollup-plugin-typescript2";
import commonjs from "rollup-plugin-commonjs";
import external from "rollup-plugin-peer-deps-external";
import resolve from "rollup-plugin-node-resolve";
import url from "rollup-plugin-url";
import PeerDepsExternalPlugin from "rollup-plugin-peer-deps-external";
import pkg from "./package.json";
export default {
input: "src/index.ts",
output: [
{
file: pkg.main,
format: "cjs",
exports: "named",
sourcemap: true
},
{
file: pkg.module,
format: "es",
exports: "named",
sourcemap: true
}
],
plugins: [
url({
include: ['**/*.ttf', '**/*.png'],
limit: Infinity
}),
PeerDepsExternalPlugin(),
external(),
resolve(),
typescript({
rollupCommonJSResolveHack: true,
exclude: "**/__tests__/**",
clean: true
}),
commonjs({
include: ["node_modules/**"],
namedExports: {
"node_modules/react/react.js": [
"Children",
"Component",
"PropTypes",
"createElement"
],
"node_modules/react-dom/index.js": ["render"],
'node_modules/react-is/index.js': [
'isElement',
'isValidElementType',
'ForwardRef',
'Memo',
'isFragment'
],
'node_modules/prop-types/index.js': [
'elementType'
]
}
})
]
};
这是我的 tsconfig.json
{
"compilerOptions": {
"outDir": "dist",
"module": "esnext",
"target": "es5",
"lib": [
"es6",
"dom",
"es2016",
"es2017"
],
"sourceMap": true,
"allowJs": false,
"jsx": "react",
"declaration": true,
"moduleResolution": "node",
"forceConsistentCasingInFileNames": true,
"noImplicitReturns": true,
"noImplicitThis": true,
"noImplicitAny": true,
"strictNullChecks": true,
"suppressImplicitAnyIndexErrors": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"typeRoots": [
"src/types"
]
},
"include": [
"src"
],
"exclude": [
"node_modules",
"dist",
"src/**/*.stories.tsx",
"src/**/*.test.tsx"
]
}
这是运行 rollup -c 后的 dist 文件夹:
这是CardLink.d.ts的内容
import React from "react";
import { ICardLinkProps } from "./ICardLinkProps";
/**
* CardLink Component
* @extends {Component<ICardLinkProps,ICardLinkState>}
*/
export declare const CardLink: React.ComponentType<Pick<Pick<ICardLinkProps, "theme" | "classes"> & Partial<Pick<ICardLinkProps, "Title" | "Description" | "ActionText" | "DestinationUrl" | "ImageUrl" | "Icon" | "Secondary">> & Partial<Pick<{
Title: string;
Description: string;
ActionText: string;
DestinationUrl: string;
ImageUrl: string;
Icon: string;
Secondary: boolean;
}, never>>, "Title" | "Description" | "ActionText" | "DestinationUrl" | "ImageUrl" | "Icon" | "Secondary"> & import("@material-ui/core").StyledComponentProps<"centeredIcon" | "icon" | "bellowMargin" | "paper" | "paperSecondary" | "iconSecondary" | "container" | "actionsArea">>;
提前致谢。
问题没有显示最重要的事情:
dist
)这两项将告诉您组件包的名称以及如何将路径导出为节点模块。特别是 package.json 中的
name
和 exports
字段。
我假设组件包使用桶文件从某个索引文件中导出它们,因为构建使用了捆绑器。另一种方法是简单地使用 TS 进行编译,并让使用包处理捆绑包。
对于具有从图像中给出的输出的捆绑组件包,您可以定义类型,以便可以在模块解析期间找到它们。
package.json
"name": "components",
"main": "dist/index.js",
"module": "dist/index.es.js",
"types": "dist/index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.es.js",
"require": "./dist/index.js",
"default": "./dist/index.js"
},
"./package.json": "./package.json"
}
这将允许像
这样的导入import { CardLink } from "components"
您的编辑器可以通过包相应的 package.json 文件中的
types
字段处理类型解析。
更好的方法是不捆绑,而只编译,同时生成 ES 模块和 CommonJS 构建。理想情况下,您使用不同的文件扩展名至少可以区分 CJS 类型。另外,避免使用桶文件并使用子路径导出。这样可以通过使用包和工具生态系统来更轻松地进行树摇动。
.
├── components/
│ ├── Foo/
│ │ └── foo.tsx
│ └── Bar/
│ └── bar.tsx
├── package.json
└── tsconfig.json
现在以某种方式创建一个双重构建而不捆绑。使用 @knighted/duel 和其他选项很容易。
现在在子路径导出中使用通配符。与之前相同,但更改了
exports
:
"exports": {
"./*": {
"import": {
"types": "./dist/*.d.ts",
"default": "./dist/*.js"
},
"require": {
"types": "./dist/*.d.cts",
"default": "./dist/*.cjs"
}
}
}
现在您可以从子路径而不是桶文件导入。
import { Foo } from "components/Foo"
编辑者可以通过
Foo
字段使用 types
的类型。