如何让 require.context 与 Create React App with/withou Craco 一起工作?
How to get require.context to work with Create React App with/withou Craco?
我试图在我的 CRA(使用 Typescript)项目中通过 require.context
在运行时执行一些要求,但我只收到以下类型的错误:
TypeError: __webpack_require__(...).context is not a function
和
Critical dependency: require function is used in a way in which dependencies cannot be statically extracted
我在某处读到现在需要通过 Babel 或 cra-rewired
进行 polyfill。好吧,我已经在使用 Craco 来启用 Less-support,但我不知道如何将 require.context
添加到我的 Craco 配置中。
有人知道怎么做吗?
更新: 这就是我调用的方式 require.context:
const packagesDirectory = path.join(__dirname, '../../../../packages');
const textDataContext = require.context(packagesDirectory, true, /(\w+)\.(\w+)\.(mdx?)/);
更新二:
正如 this thread 中的一些评论所建议的那样,我尝试将 babel-plugin-require-context-hook
添加到我的应用程序中,如下所示:
// craco.config.js
const CracoLessPlugin = require('craco-less');
module.exports = {
plugins: [
{plugin: CracoLessPlugin}
],
babel: {
plugins: ['require-context-hook']
}
};
然后我尝试像这样调用 require.context
:
// myfile.js
import registerRequireContextHook from 'babel-plugin-require-context-hook/register';
registerRequireContextHook();
const packagesDirectory = path.join(__dirname, '../../../../packages');
const textDataContext = require.context(packagesDirectory, true, /(\w+)\.(\w+)\.(mdx?)/);
但是我得到这个错误:
TypeError: fs.readdirSync is not a function
更新 3:
CRA 似乎 支持 require.context 而根本不需要任何 polyfill。但是当它通过导入的模块执行时看起来失败了。在我之前的尝试中,我一直在 myfile.js
中执行对 require.context
的调用(见上文),它已被 index.js
导入,如下所示:
// index.js
import myModules from 'myfile.js';
ReactDOM.render(...);
但是,如果我将 index.js
更改为:
// index.js
const something = require.context('../../packages/', true, /(\w+)\.(\w+)\.(mdx?)/);
something.keys().forEach(key => console.log(key));
ReactDOM.render(...);
它就像一个魅力! 为什么?!
Require.context
这是一个 webpack 特性,而不是 cra
或其他东西。
那么为什么它不适用于您的 upd1
或 upd2
而它适用于 upd3
?
答案很简单——因为这里使用了变量。 Webpack 需要你的代码是静态可分析的。这意味着当你编写 require.context('../src/directory/', true, /.ts$/)
时,webpack 认为 hmmm OK 我需要递归地查找和准备 src/directory
中的所有 .ts
文件,因为它可以在进一步的步骤中使用。
它不能使用变量,因为 require.context(myPathVariable, true, /.ts$/)
可以是任何东西。 Webpack 不知道 myPathVariable
在 build
阶段是什么,因为它只会在 runtime
阶段计算。
此规则也适用于 dynamic imports
。 import('../src/keks/index.ts')
有效,import(myVar + '../src/keks/index.ts')
无效。
请参阅此 issue,其中包含有关 require.context
"staticness" 的讨论和一些提示。
如何使动态路径工作
使用动态路径的一种方法是使用 DefinePlugin
。但是你所有的动态路径都应该在 build
阶段被知道和计算(在 webpack 配置或任何 node.js 脚本中)。
示例:
webpack.config.js
module.exports = {
plugins: [new DefinePlugin({ PACKAGES_DIR: JSON.stringify('path/to/packages') })]
}
然后:
index.ts
你可以使用 require.context(PACKAGES_DIR, true, /\.ts$/)
或 import(PACKAGES_DIR + 'myfile.ts')
因为 webpack 已经知道一些关于这个路径的信息。
我试图在我的 CRA(使用 Typescript)项目中通过 require.context
在运行时执行一些要求,但我只收到以下类型的错误:
TypeError: __webpack_require__(...).context is not a function
和
Critical dependency: require function is used in a way in which dependencies cannot be statically extracted
我在某处读到现在需要通过 Babel 或 cra-rewired
进行 polyfill。好吧,我已经在使用 Craco 来启用 Less-support,但我不知道如何将 require.context
添加到我的 Craco 配置中。
有人知道怎么做吗?
更新: 这就是我调用的方式 require.context:
const packagesDirectory = path.join(__dirname, '../../../../packages');
const textDataContext = require.context(packagesDirectory, true, /(\w+)\.(\w+)\.(mdx?)/);
更新二:
正如 this thread 中的一些评论所建议的那样,我尝试将 babel-plugin-require-context-hook
添加到我的应用程序中,如下所示:
// craco.config.js
const CracoLessPlugin = require('craco-less');
module.exports = {
plugins: [
{plugin: CracoLessPlugin}
],
babel: {
plugins: ['require-context-hook']
}
};
然后我尝试像这样调用 require.context
:
// myfile.js
import registerRequireContextHook from 'babel-plugin-require-context-hook/register';
registerRequireContextHook();
const packagesDirectory = path.join(__dirname, '../../../../packages');
const textDataContext = require.context(packagesDirectory, true, /(\w+)\.(\w+)\.(mdx?)/);
但是我得到这个错误:
TypeError: fs.readdirSync is not a function
更新 3:
CRA 似乎 支持 require.context 而根本不需要任何 polyfill。但是当它通过导入的模块执行时看起来失败了。在我之前的尝试中,我一直在 myfile.js
中执行对 require.context
的调用(见上文),它已被 index.js
导入,如下所示:
// index.js
import myModules from 'myfile.js';
ReactDOM.render(...);
但是,如果我将 index.js
更改为:
// index.js
const something = require.context('../../packages/', true, /(\w+)\.(\w+)\.(mdx?)/);
something.keys().forEach(key => console.log(key));
ReactDOM.render(...);
它就像一个魅力! 为什么?!
Require.context
这是一个 webpack 特性,而不是 cra
或其他东西。
那么为什么它不适用于您的 upd1
或 upd2
而它适用于 upd3
?
答案很简单——因为这里使用了变量。 Webpack 需要你的代码是静态可分析的。这意味着当你编写 require.context('../src/directory/', true, /.ts$/)
时,webpack 认为 hmmm OK 我需要递归地查找和准备 src/directory
中的所有 .ts
文件,因为它可以在进一步的步骤中使用。
它不能使用变量,因为 require.context(myPathVariable, true, /.ts$/)
可以是任何东西。 Webpack 不知道 myPathVariable
在 build
阶段是什么,因为它只会在 runtime
阶段计算。
此规则也适用于 dynamic imports
。 import('../src/keks/index.ts')
有效,import(myVar + '../src/keks/index.ts')
无效。
请参阅此 issue,其中包含有关 require.context
"staticness" 的讨论和一些提示。
如何使动态路径工作
使用动态路径的一种方法是使用 DefinePlugin
。但是你所有的动态路径都应该在 build
阶段被知道和计算(在 webpack 配置或任何 node.js 脚本中)。
示例:
webpack.config.js
module.exports = {
plugins: [new DefinePlugin({ PACKAGES_DIR: JSON.stringify('path/to/packages') })]
}
然后:
index.ts
你可以使用 require.context(PACKAGES_DIR, true, /\.ts$/)
或 import(PACKAGES_DIR + 'myfile.ts')
因为 webpack 已经知道一些关于这个路径的信息。