什么是`require.context`?


74

Webpack文件

您可以使用require.context()函数创建自己的上下文。

大。什么是“上下文”?这实际上是做什么的?

它允许您传递要搜索的目录,指示是否也应搜索子目录的标志以及用于匹配文件的正则表达式。

允许我“搜索”吗?搜索我假设的文件,然后呢?此功能最终会做什么?这有什么用途?


然后什么?那么具体取决于您在Webpack配置文件中指定的内容。您从文档中引用的内容对我来说听起来很清楚,它允许指定从何处开始收集文件并解析导入和其他标志以帮助完成此过程
Meme Composer

Answers:


73

之一的WebPack的编译器的主要特征是递归地解析所有的模块,从条目开始,建立通过分析所有的模块依赖关系的曲线图require()require.context()importimport()表达式。

webpack和Node.js中对“上下文”的通常解释是一些目录,用作解析模块路径的基础。例如,当前工作目录用作webpack的默认上下文,以解析index.js进入模块的实际路径;请求的上下文require.resolve('../../../foo.js')__dirname

require.context是webpack编译器支持的特殊功能,它使您可以从某个基本目录开始获取所有匹配的模块。目的是在编译时告诉webpack将表达式转换为它可以解析的所有可能匹配模块请求的动态列表,然后将它们添加为构建依赖项,并允许您在运行时要求它们。

简而言之,require.context当在运行时在Node.js中使用glob动态构建所需的模块路径列表时,将使用完全相同的情况。返回值是一个行为类似于require的可调用对象,该对象的键包含必要的模块请求数据,可以将这些数据作为参数传递给require模块。

您可以通过多种方式使用它,但是我认为两个最常见的用例要么是自动地需要一些众所周知的模块(例如,您仅添加some.test.js测试模块,然后在某些模块中require.context用于动态发现所有测试,因此不必记录文档并记住每次添加新的测试模块时都要手动进行操作),也不必在存储库中加载静态资产以将文件发送到构建输出(来自其他构建工具的新webpack用户通常会对它们的图像感到惊讶) ,字体,音频文件和其他资源不会显示在输出中,除非某些模块需要它们)。


23

这是一个实际的例子,但请耐心等待。我将向您展示如何从文件夹加载HTML片段,并使用Webpack和HTML将其输出到页面上。require.context().

如今,有很多方法可以使用模板和模板语言来构建网站:您已经拥有handlebars, mustache, markdown, jasmine, JSX,大量静态生成器来处理它们,例如Eleventy, Hugo, Gatsby。而且,更不用说选择普通HTML或某种框架了,例如Vue

但是有时您只需要从某些文件中获取一些HTML并将其发布到页面上即可。还有一种方法可以从文件夹中加载HTML片段,然后使用Webpack和HTML将其输出到页面上。require.context().

为什么要完全使用require.context或HTML片段?

如果您要建立一个网站甚至一个小型Web应用程序,那么可能会有更直接,可扩展的方法。

但是,最近,我一直在构建一个简单的组件UI库,并希望有一种快速的方法来简单地抓取一些HTML,并将其包含在最终页面(或一系列页面)中,以显示实际运行的库版本。

HTML文件不是完整的文档,而仅仅是HTML的片段,这些片段封装了库中的特定组件以显示其标记。另外,我希望将它们分解成一个文件夹中的单独文件,以更好地进行项目组织。提出的主要问题是找到一种可靠的方式来抓取所有文件,因为它们是分开的部分而不是整个HTML文档,并以逻辑顺序抓取它们,而不是必须拥有一个长期的文档。

我正在使用Webpack捆绑所有内容并处理CSS和JS处理,因此尝试找到一种简单的方法让Webpack抓取这些文件并进行处理是很有意义的。当然还有其他选择,但是有些不是全部可行的……但是在这里,我们专注于基于Webpack的解决方案

Webpack和require.context()可以解救!

因此,由于我们已经在使用Webpack来构建此东西,因此让我们利用Webpack的一项出色功能:require.context().

首先,配置html-loader处理文件。首先,因为我们正在加载HTML文件,所以我们需要安装Webpack的html-loader;用npm / yarn轻松完成:

npm i -D html-loader or yarn add --dev html-loader

从这里,我们需要将html-loader配置添加到我们的 webpack.config.js

module: {
        rules: 
        [
            {
                test: /\.html$/,
                exclude: /node_modules/,
                use: {
                    loader: 'html-loader'
                }
            },
            ...
            {
            //other rules here
            }
        ]
      }

现在,如果我们执行以下操作,Webpack可以为我们识别和处理HTML文件:

require('/path/to/html/file.html');

但这只是一个文件,我们需要加载一堆文件,这将是一个不断增长的列表–对于每次仅添加一行来说不切实际。

现在我们可以加载HTML文件,可以开始使用require.context()加载文件夹中的某些文件并处理其内容。

我要做的就是达到以下目的:

// grab the element where we'll output the HTML to
const output = document.querySelector('#output');

// create a 'cache' where we can store our built up HTML from our fragments
let htmlFragmentCache = {};

// here, we're creating an anonymous function that loads up our HTML fragments
// then it adds them to our cache object
const importAll = requireContext => requireContext.keys().forEach(key => htmlFragmentCache[key] = requireContext(key));

// next, we call our importAll() function to load the files
// notice how this is where we call the require.context() function
// it uses our file path, whether to load subdirectories and what file type to get
importAll(require.context('./fragments', false, /.html$/));

// finally, we can loop over our cache's keys and add the HTML to our output element
Object.keys(htmlFragmentCache).forEach(key => output.innerHTML += htmlFragmentCache[key]);

就这么简单!当然,即使是很少的几行也可以压缩成一个匿名函数(确实是一个示例,它Immediately Invoked Function Expression or IIFE)可以创建更清晰,更简洁的最终结果:

(context => {
    // need to clear out the current element's contents (just in case!)
    output.innerHTML = '';

    // now, load up the html fragments and add them to the page
    context.keys().forEach(key => output.innerHTML += context(key));
})(require.context('./fragments', false, /.html$/));

我们终于得到它了。这是一种非常干净,简单的方法,可以使用require.context()JavaScript文件在文件夹中加载一堆HTML文件,并使用Webpack进行加载,处理和捆绑。嘘!


我收到错误require.context不是函数@Humoyun Ahmad
Vish

1
您能否提供有关此案例的更多信息,仅说不起作用是不够的:例如,这require.context是Webpack特有的功能,因此,如果您直接将其与Jest(测试)一起使用(该功能不起作用),则需要尝试以某种方式进行模拟
Humoyun Ahmad

Vish最有可能尝试在webpack之外使用require.context,最有可能在测试脚本中使用,在这种情况下,需要对其进行填充。
RichS
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.