6

我试图在运行时通过require.context我的 CRA(使用 Typescript)项目做一些要求,但我只收到这些类型的错误:

TypeError: __webpack_require__(...).context 不是函数

关键依赖:require函数的使用方式不能静态提取依赖

我在某处读到现在需要通过 Babel 或cra-rewired. 好吧,我已经在使用 Craco 来启用 Less-support,但我不知道如何添加require.context到我的 Craco 配置中。

有人知道怎么做吗?

更新:这就是我调用 require.context 的方式:

const packagesDirectory = path.join(__dirname, '../../../../packages');
const textDataContext = require.context(packagesDirectory, true, /(\w+)\.(\w+)\.(mdx?)/);

更新 2:

正如该线程中的一些评论所暗示的那样,我尝试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 不是函数

更新 3:

似乎 CRA确实支持 require.context 而根本不需要任何 polyfill。但是当它通过导入的模块执行时似乎失败了。在我之前的尝试中,我一直在执行对require.contextin myfile.js(见上文)的调用,该调用已通过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(...);

它就像一个魅力!为什么?!

4

1 回答 1

3

Require.context它是一个 webpack 功能,而不是cra其他东西。

那么为什么它不适用于您的upd1orupd2并且它适用于upd3

答案很简单——因为这里使用了变量。Webpack 需要你的代码是可静态分析的。这意味着当您编写例如require.context('../src/directory/', true, /.ts$/)webpack 认为嗯好的时,我需要以递归方式查找并准备所有.ts文件,src/directory因为它可以在进一步的步骤中使用。

它不能与变量一起使用,因为它require.context(myPathVariable, true, /.ts$/)可以是任何东西。Webpack 不知道阶段是什么myPathVariablebuild因为它只会在runtime阶段计算。

这条规则也差不多dynamic importsimport('../src/keks/index.ts')会工作,import(myVar + '../src/keks/index.ts')不会。

请参阅此问题的讨论和有关require.context“静态”的一些提示。

如何让动态路径工作

使用动态路径的一种方法是使用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$/)orimport(PACKAGES_DIR + 'myfile.ts')因为 webpack 已经知道一些关于这个路径的信息。

于 2020-01-22T07:31:51.080 回答