简体   繁体   English

Webpack + Typscript 库导入在 React 项目中未定义

[英]Webpack + Typscript library import is undefined in React project

I am trying to make a React library using Typescript, Webpack and Babel however I am running into a problem.我正在尝试使用 Typescript、Webpack 和 Babel 制作一个 React 库,但是我遇到了问题。 If I build then import the library into a React project then my import is 'undefined' (See the below error).如果我构建然后将库导入到 React 项目中,那么我的导入是“未定义的”(请参阅下面的错误)。 I think this would be because in the bundle.js there is no module.exports for the variable that would represent my class there is only a __webpack_exports__["default"] = (ExampleComponent);我认为这是因为在bundle.js中没有module.exports代表我的 class 的变量只有一个__webpack_exports__["default"] = (ExampleComponent); (However I am unsure of what this does in practice so I could be wrong.) (但是我不确定这在实践中会做什么,所以我可能是错的。)

I specifically got this error:我特别得到了这个错误:

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

What I have tried:我试过的:

  • Changing the tsconfig target to es6 and module to commonjs将 tsconfig 目标更改为 es6 并将模块更改为 commonjs
  • Changing the tsconfig target to es6 and module to esnext将 tsconfig 目标更改为 es6 并将模块更改为 esnext
  • Changing the tsconfig target to es5 and module to esnext将 tsconfig 目标更改为 es5 并将模块更改为 esnext
  • Changing the tsconfig target to esnext and module to esnext将 tsconfig 目标更改为 esnext 并将模块更改为 esnext
  • Changing the tsconfig target to es6 and module to es6将 tsconfig 目标更改为 es6 并将模块更改为 es6
  • Changing the tsconfig target to commonjs and module to es6将 tsconfig 目标更改为 commonjs 并将模块更改为 es6
  • Importing the library as 'import * as ExampleComponent from...' and 'import {ExampleComponent} from...' (As intended) both times 'ExampleComponent' was undefined.将库导入为“import * as ExampleComponent from...”和“import {ExampleComponent} from...”(如预期的那样)两次“ExampleComponent”都未定义。

Versions:版本:

  • babel-loader: ^8.1.0通天塔加载器:^8.1.0
  • Webpack: ^4.43.0 Webpack:^4.43.0
  • typescript: ^3.8.3 typescript:^3.8.3

Code:代码:

React Project:反应项目:

import React from "react";
import { ExampleComponent } from "test-lib";

// This is always undefined
console.log(ExampleComponent);

function App() {
    return <ExampleComponent />;
}

export default App;

Library Project:图书馆项目:

index.ts:索引.ts:

import ExampleComponent from './ExampleComponent'

export { ExampleComponent }

ExampleComponent.tsx ExampleComponent.tsx

import * as React from 'react'
import './ExampleComponent.css'

interface Props {
    text: string
}

// prettier-ignore
const ExampleComponent: React.FC<Props> = ({ text }) => (
    <h1 className="example-text">{text}</h1>
)

export default ExampleComponent

Library Configs:库配置:

tsconfig.json: tsconfig.json:

{
    "compilerOptions": {
        "outDir": "dist",
        "module": "esnext",
        "lib": ["dom", "esnext"],
        "moduleResolution": "node",
        "jsx": "react",
        "sourceMap": true,
        "declaration": true,
        "esModuleInterop": true,
        "noImplicitReturns": true,
        "noImplicitThis": true,
        "noImplicitAny": true,
        "strictNullChecks": true,
        "suppressImplicitAnyIndexErrors": true,
        "noUnusedLocals": true,
        "noUnusedParameters": true,
        "allowSyntheticDefaultImports": true,
        "target": "es5",
        "allowJs": true,
        "skipLibCheck": true,
        "strict": true,
        "forceConsistentCasingInFileNames": true,
        "resolveJsonModule": true
    },
    "include": ["src", "tests"],
    "exclude": ["node_modules", "dist", "example"]
}

.babelrc: .babelrc:

{
    "presets": [
        [
            "@babel/preset-env",
            {
                "debug": true,
                "useBuiltIns": "usage",
                "corejs": 3
            }
        ],
        "@babel/preset-react",
        "@babel/preset-typescript"
    ]
}

Webpack Config: Webpack 配置:

const path = require('path')
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin')

module.exports = {
    entry: {
        bundle: './src/index.ts',
    },

    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: '[name].js',
    },

    resolve: {
        extensions: ['.tsx', '.ts', '.js', '.json'],
    },

    devtool: 'source-map',

    module: {
        rules: [
            {
                test: /\.tsx?$/,
                exclude: /node_modules/,
                use: [{ loader: 'babel-loader' }, { loader: 'ts-loader' }],
            },

            {
                test: /\.css$/,
                loaders: ['style-loader', 'css-loader'],
            },

            {
                test: /\.(gif|png|jpe?g|svg)$/,
                use: [
                    'file-loader',
                    {
                        loader: 'image-webpack-loader',
                        options: {
                            disable: true,
                        },
                    },
                ],
            },

            {
                test: /\.js$/,
                enforce: 'pre',
                loader: 'source-map-loader',
            },
        ],
    },

    plugins: [new ForkTsCheckerWebpackPlugin()],
}

If you want to see the full code here is a link to the Github Repo .如果您想在此处查看完整代码,请参阅Github Repo的链接。

Based on the comment from Scovy I was able to get this working by using the output.libraryTarget and output.globalObject output options.根据 Scovy 的评论,我能够通过使用output.libraryTargetoutput.globalObject output 选项来完成这项工作。

Now my output entry in my webpack.base.config.js looks like this:现在我的 webpack.base.config.js 中的 output 条目如下所示:

output: {
    path: path.resolve(__dirname, 'dist'),
    filename: '[name].js',
    libraryTarget: 'umd',
    globalObject: 'this',
},

Update:更新:

The above change did not seam to work 100% of the time so I found a library called esm-webpack-plugin which ended up working perfectly.上述更改并没有在 100% 的情况下正常工作,因此我找到了一个名为esm-webpack-plugin的库,它最终可以完美运行。

So the final code for the output entry in the webpack config is:所以 webpack 配置中 output 条目的最终代码是:

output: {
    path: path.resolve(__dirname, 'dist'),
    filename: '[name].js',
    library: 'LIB',
    libraryTarget: 'var',
},

and I also added the plugin:我还添加了插件:

plugins: [new ForkTsCheckerWebpackPlugin(), new EsmWebpackPlugin()],

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM