使用 TypeScript 和 NPM 链接创建 React 应用程序:导致模块解析失败的枚举

Posted

技术标签:

【中文标题】使用 TypeScript 和 NPM 链接创建 React 应用程序:导致模块解析失败的枚举【英文标题】:Create React App with TypeScript and NPM Link: Enums causing Module parse failed 【发布时间】:2021-04-29 18:58:42 【问题描述】:

我有一个基本的create-react-app TypeScript 项目 (client)。只是目录,我有一个server 和一个shared 文件夹。在shared 文件夹中,我有一些interfaces 和enums 我在serverclient 之间共享。

我希望将此shared 文件夹链接到clientserver 包。

首先,我转到shared 并运行$ yarn link,然后从clientserver 文件夹运行$ yarn link shared

服务器非常高兴,大部分情况下客户端也是如此。但是,一旦我使用clientshared 目录中的enums 之一,我就会收到错误消息:

../shared/src/models/Roles.ts 4:0
Module parse failed: The keyword 'enum' is reserved (4:0)
File was processed with these loaders:
 * ./node_modules/@pmmmwh/react-refresh-webpack-plugin/loader/index.js
You may need an additional loader to handle the result of these loaders.
| $RefreshSetup$(module.id);
| 
> enum Roles 
|     RW_ORG = "rw_org", // can modifiy organization and it's users, nothing else

我是这样导入的: import Roles from "shared"; 但也尝试了许多其他方法。

我正在从 shared index.ts 像这样导出它

import Roles from "./models/Roles";

export type  
    // all of my interfaces
;
export  Roles 

我所有的interfaces 都可以使用,所以我不明白。这到底是怎么回事?

【问题讨论】:

【参考方案1】:

好吧,事实证明这些错误都是由 create-react-app 的默认 webpack.config.js 引起的。如果你导航到 code node_modules/react-scripts/config/webpack.config.js 你会找到一行 include: paths.appSrc 这基本上将 Babel 限制在 react 应用程序本身的 src/ 文件夹中。

这意味着,如果你在它之外yarn linked 一个文件夹,Babel 不会将其转换为普通 JS,因此 React 无法使用它。

有两个 hacky 解决方案,但我想要一个更好的解决方案。

    每次安装节点模块时手动(或通过构建脚本)从react-scripts 中删除include: paths.appSrc 行 制作一个脚本,在每次修改外部目录时将外部目录复制到您的 React src 目录中。

我真的希望有一个官方的方法来解决这个问题......

【讨论】:

我遇到了类似的问题,并通过将 ORIGINAL(共享)文件夹放在 react 应用程序源中并将链接文件夹放在服务器中来解决它,它不关心这个作为 react-script确实:) @YochailLehman 是的,这是另一种可能的解决方案。老实说,最好的办法就是执行这些选项之一,直到您准备好将共享目录变成实际模块。此时,您应该在进行更改时构建共享模块并将其安装为本地包(或某处的托管包),而不是依赖链接或其他任何东西。 我用@craco/craco 自动化了它:gist.github.com/PhilippMolitor/00f427d12a9c5bca84309058d88846b7 你也可以使用include: [paths.appSrc, /\.(ts|tsx)$/]【参考方案2】:

根据@foxtrotuniform6969 的回答,我创建了一个@cracro/craco 配置,它可以自行消除行为不端的设置。

module.exports = 
  webpack: 
    configure: (webpackConfig) => (
      ...webpackConfig,
      module: 
        ...webpackConfig.module,
        rules: webpackConfig.module.rules.map((rule) => 
          if (!rule.oneOf) return rule;
          return 
            ...rule,
            oneOf: rule.oneOf.map((ruleObject) => 
              if (
                !new RegExp(ruleObject.test).test('.ts') ||
                !ruleObject.include
              )
                return ruleObject;
              return  ...ruleObject, include: undefined ;
            ),
          ;
        ),
      ,
    ),
  ,
;

https://gist.github.com/PhilippMolitor/00f427d12a9c5bca84309058d88846b7

【讨论】:

我一定要尽可能地尝试一下,干得好 很好,这对我有用!【参考方案3】:

可以使用react-app-rewired 自动删除other answer 中提到的包含路径设置。

以下config-overrides.js 适用于react-scripts:4.0.3 并导致 babel 也转译节点模块中的文件。

// config-overrides.js
module.exports = function override(config, env) 
  // This line might break with other react-script versions
  delete config.module.rules[1].oneOf[2].include
  return config

【讨论】:

看起来有点可疑......但我想没有多少选择。 确实,非常可疑。但可能比替代品更好......【参考方案4】:

此问题的其他答案建议删除react-scripts'webpack.config 中的include(使用cracoreact-app-rewired)。我发现这适用于 yarn start,但是当我使用 yarn build 进行生产构建时,我在运行时收到错误 Uncaught ReferenceError: exports is not defined

除了删除现有的 src 目录之外,我还必须添加另一个项目的 src,而不是删除包含。 这是我的config-overrides.jsreact-app-rewired 一起使用。

对于react-scripts 4:

const path = require("path");

module.exports = function override(config) 
    // See https://***.com/questions/65893787/create-react-app-with-typescript-and-npm-link-enums-causing-module-parse-failed.
    config.module.rules[1].oneOf[2].include = [
        path.join(__dirname, './src'),
        path.join(__dirname, '../backend/src')
    ];
    return config

对于react-scripts 5:

const path = require("path");

module.exports = function override(config) 
    // See https://***.com/questions/65893787/create-react-app-with-typescript-and-npm-link-enums-causing-module-parse-failed.
    config.module.rules[1].oneOf[3].include = [
        path.join(__dirname, './src'),
        path.join(__dirname, '../backend/src')
    ];
    return config

【讨论】:

以上是关于使用 TypeScript 和 NPM 链接创建 React 应用程序:导致模块解析失败的枚举的主要内容,如果未能解决你的问题,请参考以下文章

通过 npm 链接和 typescript 本地开发的多模块

自定义npm包——typeScript版本

从使用 nestjs API 应用程序调试 npm 库(使用 noidejs、nestjs 和 typescript 构建)

将 npm 链接的 React JSX 项目/模块导入 AngularJS TypeScript 模块不起作用

NPM 模块 + TypeScript 最佳实践

在 NPM 注册表中发布的 Typescript 模块 - 在不同项目中使用时找不到模块