从本地 npm 包导入 React 组件 return 空对象

Import React component from local npm package return empty object

我正在构建我的第一个 react 组件的 npm 包。

在我用webpack构建成功后,我尝试用npm link测试它。

已连接但组件未加载。它给了我一堆这样的错误

Uncaught Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports. Check the render method of `App`.

所以我尝试 console.log() 这个组件。它 returns 一个空 Object.

我为此苦苦挣扎了 2 天,不知道出了什么问题。

这里是一些配置

webpack.config.js

var path = require("path");
const isDevelopment = process.env.NODE_ENV === 'development'
const MiniCssExtractPlugin = require('mini-css-extract-plugin')

module.exports = {
    mode: "production",
    entry: {
        index: path.join(__dirname, 'src', 'index.tsx')
    },
    plugins: [
        new MiniCssExtractPlugin({
            filename: isDevelopment ? '[name].css' : '[name].[hash].css',
            chunkFilename: isDevelopment ? '[id].css' : '[id].[hash].css'
        })
    ],
    module: {
        rules: [
            {
                test: /\.tsx?$/,
                loader: 'ts-loader',
                exclude: /node_modules/,
                options: { allowTsInNodeModules: true }
            },
            {
                test: /\.css$/i,
                use: ["style-loader", "css-loader"],
            },
            {
                test: /\.module\.s[ac]ss$/,
                use: [
                    isDevelopment ? 'style-loader': MiniCssExtractPlugin.loader,
                    {
                        loader: 'css-loader',
                        options: {
                            modules: true,
                            sourceMap: isDevelopment
                        }
                    },
                    {
                        loader: 'sass-loader',
                        options: {
                            sourceMap: isDevelopment
                        }
                    }
                ]
            },
            {
                test: /\.s[ac]ss$/i,
                exclude: /\.module.(s[ac]ss)$/,
                use: [
                    // Creates `style` nodes from JS strings
                    isDevelopment ? 'style-loader': MiniCssExtractPlugin.loader,
                    // to generate a .d.ts module
                    "css-modules-typescript-loader",
                    // Translates CSS into CommonJS
                    {loader: "css-loader", options: {modules: true}},
                    // Compiles Sass to CSS
                    {loader: "sass-loader", options: {sourceMap: isDevelopment}},
                ],
            },
        ]
    },
    resolve: {
        extensions: [".ts", ".tsx", ".js", ".css", ".scss"]
    },
    output: {
        filename: '[name].js',
        path: path.resolve(__dirname, 'dist'),
    },
}

tsconfig.json

{
  "compilerOptions": {
    "outDir": "./dist/",
    "target": "es5",
    "lib": [
      "dom",
      "dom.iterable",
      "esnext"
    ],
    "allowJs": true,
    "declaration": true,
    "declarationMap": true,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "noFallthroughCasesInSwitch": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "removeComments": true,
    "noImplicitAny": true,
    "noEmit": false,
    "jsx": "react-jsx",
    "sourceMap": true,
    "plugins": [{"name": "typescript-plugin-css-modules"}]
  },
  "include": [
    "src"
  ]
}

package.json

{
  "name": "react-dissolve",
  "version": "1.0.0",
  "description": "A color and image animated dissolve effect.",
  "main": "./dist/index.js",
  "types": "./dist/index.d.ts",
  "files": [
    "dist",
    "src"
  ],
  "scripts": {
    "build": "webpack"
  },
  "author": "jack szeto",
  "license": "MIT",
  "devDependencies": {
    "@babel/core": "^7.16.5",
    "@babel/preset-env": "^7.16.5",
    "@babel/preset-react": "^7.16.5",
    "@testing-library/jest-dom": "^5.16.1",
    "@testing-library/react": "^12.1.2",
    "@testing-library/user-event": "^13.5.0",
    "@types/color-string": "^1.5.2",
    "@types/jest": "^27.0.3",
    "@types/node": "^16.11.15",
    "@types/node-sass": "^4.11.2",
    "@types/react": "^17.0.37",
    "@types/react-dom": "^17.0.11",
    "color-string": "^1.9.0",
    "css-loader": "^6.5.1",
    "css-modules-typescript-loader": "^4.0.1",
    "mini-css-extract-plugin": "^2.4.5",
    "node-sass": "^7.0.1",
    "rc-slider": "^9.7.5",
    "react": "^17.0.2",
    "react-dom": "^17.0.2",
    "react-p5": "^1.3.24",
    "react-scripts": "5.0.0",
    "sass": "^1.45.1",
    "sass-loader": "^12.4.0",
    "simplex-noise": "^3.0.0",
    "style-loader": "^3.3.1",
    "ts-loader": "^9.2.6",
    "typescript": "^4.5.4",
    "web-vitals": "^2.1.2",
    "webpack": "^5.65.0",
    "webpack-cli": "^4.9.1"
  },
  "peerDependencies": {
    "react": "^17.0.2",
    "react-p5": "^1.3.24",
    "simplex-noise": "^3.0.0",
    "color-string": "^1.9.0",
    "rc-slider": "^9.7.5",
    "sass": "^1.45.1"
  },
  "dependencies": {}
}

构建被放入 dist 文件夹中,似乎在 dist 中完美构建成功。

截图:

最小复制案例:

使用上面相同的配置。我创建了一个测试项目(见下面的结构)。

我 运行 npm run build 使用 webpack.

构建组件

然后npm link把测试项目link改成一个新的ts React项目。试图导入,但它产生了同样的错误。

用例

import Test from 'npm-test';
...
<Test />

文件结构

npm-test/
  dist/
  node_modules/
  src/
    declarations.d.ts
    index.tsx
    style.module.scss
  .babelrc
  .gitgnore
  .npmignore
  package.json
  tsconfig.json
  webpack.config.js

index.tsx

import React, { CSSProperties } from 'react'
import styles from './style.module.scss';

interface TestProps {
    className?: string,
    style?: CSSProperties,
}
const Test = ({className, style}:TestProps) => {
    return (
        <div className={`${styles.test} ${className}`}
            style={{...style}}
        >
            Test
        </div>
    )
}
export default Test;

出口index.d.ts

import { CSSProperties } from 'react';
interface TestProps {
    className?: string;
    style?: CSSProperties;
}
declare const Test: ({ className, style }: TestProps) => JSX.Element;
export default Test;
//# sourceMappingURL=index.d.ts.map

感谢阅读长文post!

我已经解决了这个问题。感谢@JaredSmith 帮助我。

我搞砸了 webpack 但最后,我决定继续使用 rollup,它更容易使用。

找到了 Rollup tutorial by Portexe,它很有帮助。

所以我把文件结构改成这样

npm-test-hellow-world/
  src/
    component/
      hello-world.tsx
    index.ts
  .babelrc
  .gitgnore
  .npmignore
  package.json
  tsconfig.json
  rollup.config.js

因为在 hello-world.tsx 中函数组件被默认导出

declare const HelloWorld: React.FC<HelloWorldProps>;
export default HelloWorld;

不知何故,编译器没有导出组件。所以我把它放在 src/component/ 文件夹中并从 src/index.ts

中导出
export {default} from './component/hello-world';
// notice: 
// export * from './component/hello-world';
// didn't work

而且有效!不太确定为什么。如果有人能解释一下,我将不胜感激。

如果您想查看更多详细信息,可以查看the GitHub repo