ReactJS TypeScript:尝试导入错误:未从“ ./ActionButton”导出“ ActionButtonProps”

时间:2020-10-26 23:17:28

标签: javascript reactjs typescript webpack antd

我有一个使用create-react-app创建的TypeScript ReactJS项目,并且我试图将antd npm包中的代码包含到该项目中,以便我可以测试代码更改,从而为antd开源项目。

我已经获取了仓库的代码,并将其放置在/src/antd目录中。

我还将其./tsconfig.json./webpack.config.js文件复制到我创建的create-react-app项目的根目录中。

当我尝试运行项目时,收到以下“无法编译”错误:

./src/antd/components/modal/index.tsx
Attempted import error: 'ActionButtonProps' is not exported from './ActionButton'.

./src/antd/components/modal/index.tsx文件中,有以下行:

export { ActionButtonProps } from './ActionButton';

./src/antd/components/modal/ActionButton.tsx中,它导出以下接口:

export interface ActionButtonProps {
  type?: LegacyButtonType;
  actionFn?: (...args: any[]) => any | PromiseLike<any>;
  closeModal: Function;
  autoFocus?: boolean;
  prefixCls: string;
  buttonProps?: ButtonProps;
}

以下是从webpack.config.js回购中复制的antd文件:

/* eslint no-param-reassign: 0 */
// This config is for building dist files
const getWebpackConfig = require('@ant-design/tools/lib/getWebpackConfig');
const IgnoreEmitPlugin = require('ignore-emit-webpack-plugin');
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
const EsbuildPlugin = require('esbuild-webpack-plugin').default;
const darkVars = require('./scripts/dark-vars');
const compactVars = require('./scripts/compact-vars');

const { webpack } = getWebpackConfig;

// noParse still leave `require('./locale' + name)` in dist files
// ignore is better: http://stackoverflow.com/q/25384360
function ignoreMomentLocale(webpackConfig) {
  delete webpackConfig.module.noParse;
  webpackConfig.plugins.push(new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/));
}

function addLocales(webpackConfig) {
  let packageName = 'antd-with-locales';
  if (webpackConfig.entry['antd.min']) {
    packageName += '.min';
  }
  webpackConfig.entry[packageName] = './index-with-locales.js';
  webpackConfig.output.filename = '[name].js';
}

function externalMoment(config) {
  config.externals.moment = {
    root: 'moment',
    commonjs2: 'moment',
    commonjs: 'moment',
    amd: 'moment',
  };
}

function injectWarningCondition(config) {
  config.module.rules.forEach(rule => {
    // Remove devWarning if needed
    if (rule.test.test('test.tsx')) {
      rule.use = [
        ...rule.use,
        {
          loader: 'string-replace-loader',
          options: {
            search: 'devWarning(',
            replace: "if (process.env.NODE_ENV !== 'production') devWarning(",
          },
        },
      ];
    }
  });
}

function processWebpackThemeConfig(themeConfig, theme, vars) {
  themeConfig.forEach(config => {
    ignoreMomentLocale(config);
    externalMoment(config);

    // rename default entry to ${theme} entry
    Object.keys(config.entry).forEach(entryName => {
      config.entry[entryName.replace('antd', `antd.${theme}`)] = config.entry[entryName];
      delete config.entry[entryName];
    });

    // apply ${theme} less variables
    config.module.rules.forEach(rule => {
      // filter less rule
      if (rule.test instanceof RegExp && rule.test.test('.less')) {
        const lessRule = rule.use[rule.use.length - 1];
        if (lessRule.options.lessOptions) {
          lessRule.options.lessOptions.modifyVars = vars;
        } else {
          lessRule.options.modifyVars = vars;
        }
      }
    });

    const themeReg = new RegExp(`${theme}(.min)?\\.js(\\.map)?$`);
    // ignore emit ${theme} entry js & js.map file
    config.plugins.push(new IgnoreEmitPlugin(themeReg));
  });
}

const webpackConfig = getWebpackConfig(false);
const webpackDarkConfig = getWebpackConfig(false);
const webpackCompactConfig = getWebpackConfig(false);

webpackConfig.forEach(config => {
  injectWarningCondition(config);
});

if (process.env.RUN_ENV === 'PRODUCTION') {
  webpackConfig.forEach(config => {
    ignoreMomentLocale(config);
    externalMoment(config);
    addLocales(config);
    // Reduce non-minified dist files size
    config.optimization.usedExports = true;
    // use esbuild
    if (process.env.ESBUILD || process.env.CSB_REPO) {
      config.optimization.minimizer[0] = new EsbuildPlugin({
        target: 'chrome49',
      });
    }

    config.plugins.push(
      new BundleAnalyzerPlugin({
        analyzerMode: 'static',
        openAnalyzer: false,
        reportFilename: '../report.html',
      }),
    );
  });

  processWebpackThemeConfig(webpackDarkConfig, 'dark', darkVars);
  processWebpackThemeConfig(webpackCompactConfig, 'compact', compactVars);
}

module.exports = [...webpackConfig, ...webpackDarkConfig, ...webpackCompactConfig];

以下是从tsconfig.json回购中复制的antd文件:

{
  "compilerOptions": {
    "baseUrl": "./",
    "strictNullChecks": true,
    "moduleResolution": "node",
    "esModuleInterop": true,
    "experimentalDecorators": true,
    "jsx": "preserve",
    "noUnusedParameters": true,
    "noUnusedLocals": true,
    "noImplicitAny": true,
    "target": "es6",
    "lib": [
      "dom",
      "es2017"
    ],
    "skipLibCheck": true,
    "allowJs": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "module": "esnext",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true
  },
  "exclude": [
    "node_modules",
    "lib",
    "es"
  ],
  "include": [
    "src"
  ]
}

以下是src/antd/index.js

/* eslint no-console:0 */
function pascalCase(name) {
  return name.charAt(0).toUpperCase() + name.slice(1).replace(/-(\w)/g, (m, n) => n.toUpperCase());
}

// Just import style for https://github.com/ant-design/ant-design/issues/3745
const req = require.context('./components', true, /^\.\/[^_][\w-]+\/style\/index\.tsx?$/);

req.keys().forEach(mod => {
  let v = req(mod);
  if (v && v.default) {
    v = v.default;
  }
  const match = mod.match(/^\.\/([^_][\w-]+)\/index\.tsx?$/);
  if (match && match[1]) {
    if (match[1] === 'message' || match[1] === 'notification') {
      // message & notification should not be capitalized
      exports[match[1]] = v;
    } else {
      exports[pascalCase(match[1])] = v;
    }
  }
});

module.exports = require('./components');

我在做什么的错误是编译器在构建时无法看到ActionButton.tsx导出的接口?

1 个答案:

答案 0 :(得分:0)

问题在于 create-react-app ReactJS 项目的限制以及它们如何使用 webpack 或 babel 来热加载文件更改。

在将 antd 的分布式包添加到您的项目时,这些问题不会出现在它们中,因为在编译时不需要热加载其内容。

我的解决方法是使用 Gatsby 而不是 create-react-app 来运行我的 ReactJS 项目。