使用 TypeScript 和 NPM Link 创建 React App:枚举导致模块解析失败
Create React App with TypeScript and NPM Link: Enums causing Module parse failed
我有一个基本的 create-react-app
TypeScript 项目 (client
)。只是目录,我有一个 server
和一个 shared
文件夹。在 shared
文件夹中,我有一些 interface
和 enum
我在 server
和 client
之间共享。
我希望 link 这个 shared
文件夹到 client
和 server
包。
首先,我去了 shared
和 运行 $ yarn link
,然后 运行 $ yarn link shared
从 client
和 server
个文件夹。
服务器非常开心,而且在大多数情况下,客户端也是如此。但是,一旦我在 client
中使用 shared
目录中的 enum
之一,我就会收到错误消息:
../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 }
我的interface
都是可以用的,不懂。这到底是怎么回事?
嗯,原来这些错误都是create-react-app默认造成的webpack.config.js
。如果您导航到 code node_modules/react-scripts/config/webpack.config.js
,您会找到一行 include: paths.appSrc
,它基本上将 Babel 限制在 React 应用程序本身的 src/
文件夹中。
这意味着,如果你 yarn link
在它之外编辑了一个文件夹,Babel 不会将它转换为普通的 JS,因此 React 无法使用它。
有两个 hacky 解决方案,但我想要一个更好的解决方案。
- 每次安装节点模块时手动(或通过构建脚本)从
react-scripts
中删除 include: paths.appSrc
行
- 制作一个脚本,在每次修改外部目录时将外部目录复制到您的 React
src
目录中。
我真的希望有一个正式的方法来解决这个问题...
可以自动删除 using react-app-rewired 中提到的包含路径设置。
以下 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
}
根据@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
此问题的其他答案建议删除 react-scripts
' webpack.config
中的 include
(使用 craco
或 react-app-rewired
)。我发现这适用于 yarn start
,但是当我使用 yarn build
进行生产构建时,我在运行时收到错误 Uncaught ReferenceError: exports is not defined
。
除了现有的 src 目录之外,我不得不添加其他项目的 src,而不是删除包含。
这是我要与 react-app-rewired
一起使用的 config-overrides.js
。
对于react-scripts
4:
const path = require("path");
module.exports = function override(config) {
// See
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
config.module.rules[1].oneOf[3].include = [
path.join(__dirname, './src'),
path.join(__dirname, '../backend/src')
];
return config
}
据我所知,我的 craco 配置与 Phil Mo 的版本功能相同,但更容易理解
module.exports = {
webpack: {
configure: (webpackConfig) => {
webpackConfig.module.rules[0].oneOf.find(
({ test: t }) =>
t != null &&
!Array.isArray(t) &&
t.toString().includes('ts')
).include = undefined
return webpackConfig
}
}
}
我有一个基本的 create-react-app
TypeScript 项目 (client
)。只是目录,我有一个 server
和一个 shared
文件夹。在 shared
文件夹中,我有一些 interface
和 enum
我在 server
和 client
之间共享。
我希望 link 这个 shared
文件夹到 client
和 server
包。
首先,我去了 shared
和 运行 $ yarn link
,然后 运行 $ yarn link shared
从 client
和 server
个文件夹。
服务器非常开心,而且在大多数情况下,客户端也是如此。但是,一旦我在 client
中使用 shared
目录中的 enum
之一,我就会收到错误消息:
../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 }
我的interface
都是可以用的,不懂。这到底是怎么回事?
嗯,原来这些错误都是create-react-app默认造成的webpack.config.js
。如果您导航到 code node_modules/react-scripts/config/webpack.config.js
,您会找到一行 include: paths.appSrc
,它基本上将 Babel 限制在 React 应用程序本身的 src/
文件夹中。
这意味着,如果你 yarn link
在它之外编辑了一个文件夹,Babel 不会将它转换为普通的 JS,因此 React 无法使用它。
有两个 hacky 解决方案,但我想要一个更好的解决方案。
- 每次安装节点模块时手动(或通过构建脚本)从
react-scripts
中删除include: paths.appSrc
行 - 制作一个脚本,在每次修改外部目录时将外部目录复制到您的 React
src
目录中。
我真的希望有一个正式的方法来解决这个问题...
可以自动删除
以下 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
}
根据@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
此问题的其他答案建议删除 react-scripts
' webpack.config
中的 include
(使用 craco
或 react-app-rewired
)。我发现这适用于 yarn start
,但是当我使用 yarn build
进行生产构建时,我在运行时收到错误 Uncaught ReferenceError: exports is not defined
。
除了现有的 src 目录之外,我不得不添加其他项目的 src,而不是删除包含。
这是我要与 react-app-rewired
一起使用的 config-overrides.js
。
对于react-scripts
4:
const path = require("path");
module.exports = function override(config) {
// See
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
config.module.rules[1].oneOf[3].include = [
path.join(__dirname, './src'),
path.join(__dirname, '../backend/src')
];
return config
}
据我所知,我的 craco 配置与 Phil Mo 的版本功能相同,但更容易理解
module.exports = {
webpack: {
configure: (webpackConfig) => {
webpackConfig.module.rules[0].oneOf.find(
({ test: t }) =>
t != null &&
!Array.isArray(t) &&
t.toString().includes('ts')
).include = undefined
return webpackConfig
}
}
}