Skip to content

Commit

Permalink
docs: rewrite document for require.context() (#6736)
Browse files Browse the repository at this point in the history
  • Loading branch information
chenjiahan committed Jun 5, 2024
1 parent 8881822 commit 6ace5d3
Show file tree
Hide file tree
Showing 2 changed files with 158 additions and 32 deletions.
95 changes: 79 additions & 16 deletions website/docs/en/api/modules/module-methods.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export default {
### Dynamic import()

```ts
function(path: string): Promise
function import(path: string): Promise;
```

Dynamically load modules. Calls to `import()` are treated as split points, meaning the requested module and its children are split out into a separate chunk.
Expand Down Expand Up @@ -135,33 +135,96 @@ const {
The Data URI module can be used as a method to implement virtual modules, such as combining with a Loader to dynamically load custom modules at runtime.
:::

## Webpack
## Webpack specific

Aside from the module syntaxes described above, Rspack also support some webpack-specific methods.

#### require.context
### require.context

`require.context` is a special function in webpack that allows you to dynamically require a set of modules.

Rspack parses for `require.context()` in the code while building.

- **Type:**

```ts
require.context(
(directory: String),
(includeSubdirs: Boolean) /* optional, default true */,
(filter: RegExp) /* optional, default /^\.\/.*$/, any file */,
(mode: String) /* optional, 'sync' | 'eager' | 'weak' | 'lazy' | 'lazy-once', default 'sync' */
);
function requireContext(
/**
* A directory to search.
*/
directory: string,
/**
* Whether subdirectories should be searched.
* @default true
*/
includeSubdirs?: boolean,
/**
* A regular expression to match files.
* @default /^\.\/.*$/ (any file)
*/
filter?: RegExp,
/**
* Module loading mode.
* @default 'sync'
*/
mode?: 'sync' | 'eager' | 'weak' | 'lazy' | 'lazy-once',
): Context;
```

Specify a whole group of dependencies using a path to the `directory`, an option to `includeSubdirs`, a `filter` for more fine grained control of the modules included, and a mode to define the way how loading will work.
- **Example:**

```js
const context = require.context('components', true, /\.html$/);
const componentA = context.resolve('componentA');
// Create a context, with files from the test directory that
// can be required with a request ending with `.test.js`.
const context = require.context('./test', false, /\.test\.js$/);
```

If mode is set to 'lazy', the underlying modules will be loaded asynchronously.
```js
// Create a context with all files in the parent folder and
// descending folders ending with `.stories.js`.
const context = require.context('../', true, /\.stories\.js$/);
```

```js
const context = require.context('locales', true, /\.json$/, 'lazy');
context('localeA').then(locale => {
// do something with locale
// If mode is set to 'lazy', the underlying modules will be loaded asynchronously
const context = require.context('./locales', true, /\.json$/, 'lazy');
```

> The arguments passed to `require.context()` must be literals.
#### context API

The context returned by `require.context()` is a function that takes a `request` argument (module path).

This function has three properties: `resolve`, `keys`, and `id`.

- `resolve` is a function and returns the module id of the parsed request.
- `keys` is a function that returns an array of all possible requests that the context module can handle.
- `id` is the module id of the context module. This may be useful for `module.hot.accept`.

This can be useful if you want to require all files in a directory or matching a pattern.

Consider a scenario where you have a folder structure like this:

```
src
├── components
│ ├── Button.js
│ ├── Header.js
│ └── Footer.js
```

You can use `require.context()` to dynamically import all component files in the folder:

```js
const componentsContext = require.context('./components', false, /\.js$/);

componentsContext.keys().forEach(fileName => {
const componentModule = componentsContext(fileName);

// Here you can use your module, for example console.log
console.log(componentModule);
});
```

`require.context()` streamlines the process of module importation especially when you have a lot of files to manage. When using it, please avoid matching unnecessary files, as this might lead to significantly increased build time and output size.
95 changes: 79 additions & 16 deletions website/docs/zh/api/modules/module-methods.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export default {
### 动态 import()

```ts
function(path: string): Promise
function import(path: string): Promise;
```

动态加载模块。对 `import()` 的调用被视为分割点,这意味着请求的模块及其子模块被拆分成单独的 chunk。
Expand Down Expand Up @@ -135,33 +135,96 @@ const {
Data URI 模块可以被用作虚拟模块(Virtual Modules)的实现方式,如:配合 loader 完成运行时动态加载自定义模块。
:::

## Webpack
## Webpack specific

除了上述的模块方法之外,Rspack 还支持一些 webpack 特有的方法。

#### require.context
### require.context

`require.context` 是 webpack 中的一个特殊函数,它允许你动态地 context 一组模块。

Rspack 会在构建过程中解析代码里的 `require.context()`

- **类型:**

```ts
require.context(
(directory: String),
(includeSubdirs: Boolean) /*可选,默认为true */,
(filter: RegExp) /* 可选的,默认为/^\.\/.*$/ */。
(mode: String) /* 可选的, 'sync' | 'eager' | 'weak' | 'lazy' | 'lazy-once', 默认 'sync' */
);
function requireContext(
/**
* 要搜索的目录
*/
directory: string,
/**
* 是否还搜索其子目录
* @default true
*/
includeSubdirs?: boolean,
/**
* 匹配文件的正则表达式
* @default /^\.\/.*$/(匹配任意文件)
*/
filter?: RegExp,
/**
* 模块加载模式
* @default 'sync'
*/
mode?: 'sync' | 'eager' | 'weak' | 'lazy' | 'lazy-once',
): Context;
```

通过 `directory``includeSubdirs``filter` 参数,可以对引入的模块进行更精细控制。
- **示例:**

```js
const context = require.context('components', true, /\.html$/);
const componentA = context.resolve('componentA');
// 创建一个上下文,
// 文件直接来自 test 目录,匹配的文件名以 `.test.js` 结尾。
const context = require.context('./test', false, /\.test\.js$/);
```

如果 `mode` 被设置为 `lazy`,模块将会被异步加载。
```js
// 创建一个上下文,
// 文件来自父文件夹及其所有子级文件夹,匹配的文件名以 `.stories.js` 结尾。
const context = require.context('../', true, /\.stories\.js$/);
```

```js
const context = require.context('locales', true, /\.json$/, 'lazy');
context('localeA').then(locale => {
// 做一些与区域设置有关的事情
// 如果 `mode` 被设置为 `lazy`,模块将会被异步加载
const context = require.context('./locales', true, /\.json$/, 'lazy');
```

> 传递给 `require.context()` 的参数必须是字面量。
#### context API

`require.context()` 返回的 context 是一个函数,它接收一个 `request` 参数(模块路径)。

这个函数有三个属性:`resolve``keys``id`

- `resolve` 是一个函数,它返回 request 被解析后得到的模块 id。
- `keys` 也是一个函数,它返回一个数组,由所有可能被此上下文模块处理的请求组成。
- `id` 是上下文模块的模块 id. 它可能在使用 `module.hot.accept` 时会用到。

如果你想引入一个文件夹下面的所有文件,或者引入能匹配一个正则表达式的所有文件,这个功能就会很有帮助。

考虑一种情况,你有一个这样的文件夹结构:

```
src
├── components
│ ├── Button.js
│ ├── Header.js
│ └── Footer.js
```

你可以使用 `require.context()` 动态导入文件夹中的所有组件:

```js
const componentsContext = require.context('./components', false, /\.js$/);

componentsContext.keys().forEach(fileName => {
const componentModule = componentsContext(fileName);

// 在这里你可以使用你的模块,例如使用 console.log 输出
console.log(componentModule);
});
```

`require.context()` 简化了模块导入过程,尤其是当你有大量模块需要管理时。在使用时,请避免匹配到不需要的文件,否则可能导致构建时间和产物体积明显增加。

0 comments on commit 6ace5d3

Please sign in to comment.