> For AI agents: the complete documentation index is available at /zh/llms.txt, the full documentation bundle is available at /zh/llms-full.txt.

# Environment API

在这里你可以找到所有与 environment 相关的 API。

> 参考 [多环境构建](/zh/guide/advanced/environments.md) 了解更多。

## Environment context

Environment context 是一个只读对象，提供一些和当前 environment 有关的上下文信息。

- **类型：**

```ts
type EnvironmentContext = {
  index: number;
  name: string;
  browserslist: string[];
  config: NormalizedEnvironmentConfig;
  distPath: string;
  entry: RsbuildEntry;
  htmlPaths: Record<string, string>;
  tsconfigPath?: string;
  manifest?: Record<string, unknown> | ManifestData;
  webSocketToken: string;
};
```

Environment context 可以通过以下方式获取：

1. 在 Rsbuild 的 [插件 hooks](/zh/plugins/dev/hooks.md#plugin-hooks) 中，你可以通过 `environment` 或 `environments` 入参获取 environment context 对象。
2. 在 [Environment API](#environment-api-1) 中，可以通过 `environments[name].context` 获取。

### index

当前 environment 从零开始的索引。

- **类型：** `number`

### name

当前环境的唯一名称，用于区分和定位环境，对应于 [environments](/zh/config/environments.md) 配置中的 key。

- **类型：** `string`
- **示例：**

```js
api.modifyRspackConfig((config, { environment }) => {
  if (environment.name === 'node') {
    // modify config for node environment
  }
  return config;
});
```

### browserslist

当前环境设置的目标浏览器范围。详见 [浏览器范围](/zh/guide/advanced/browserslist.md)。

- **类型：** `string[]`
- **示例：**

```js
api.modifyRspackConfig((config, { environment }) => {
  console.log(environment.browserslist);
  return config;
});
```

### config

当前环境使用的 Rsbuild 配置（已经过规范化处理）。

- **类型：**

```ts
type NormalizedEnvironmentConfig = TwoLevelReadonly<{
  mode: RsbuildMode;
  root: string;
  dev: NormalizedDevConfig;
  server: NormalizedServerConfig;
  html: NormalizedHtmlConfig;
  tools: NormalizedToolsConfig;
  resolve: NormalizedResolveConfig;
  source: NormalizedSourceConfig;
  output: NormalizedOutputConfig;
  plugins?: RsbuildPlugins;
  security: NormalizedSecurityConfig;
  performance: NormalizedPerformanceConfig;
  splitChunks: NormalizedSplitChunksConfig | false;
  moduleFederation?: ModuleFederationConfig;
}>;
```

- **示例：**

```js
api.modifyRspackConfig((config, { environment }) => {
  // Rspack
  console.log(config);
  // Rsbuild config for current environment
  console.log(environment.config);
  return config;
});
```

### distPath

构建产物输出目录的绝对路径，对应 Rsbuild 的 [output.distPath.root](/zh/config/output/dist-path.md) 配置项。

- **类型：** `string`
- **示例：**

```js
api.modifyRspackConfig((config, { environment }) => {
  console.log(environment.distPath);
  return config;
});
```

### entry

构建入口对象，对应 [source.entry](/zh/config/source/entry.md) 选项。

- **类型：**

```ts
type RsbuildEntry = Record<string, string | string[] | RsbuildEntryDescription>;
```

- **示例：**

```js
api.modifyRspackConfig((config, { environment }) => {
  console.log(environment.entry);
  return config;
});
```

### htmlPaths

HTML 产物的路径信息。

这个值是一个对象，对象的 key 为 entry 名称，value 为 HTML 文件在产物目录下的相对路径。

- **类型：**

```ts
type htmlPaths = Record<string, string>;
```

- **示例：**

```js
api.modifyRspackConfig((config, { environment }) => {
  console.log(environment.htmlPaths);
  return config;
});
```

### tsconfigPath

tsconfig.json 文件的绝对路径，若项目中不存在 tsconfig.json 文件，则为 `undefined`。

- **类型：**

```ts
type TsconfigPath = string | undefined;
```

- **示例：**

```js
api.modifyRspackConfig((config, { environment }) => {
  console.log(environment.tsconfigPath);
  return config;
});
```

### manifest

manifest 文件数据。仅在 [output.manifest](/zh/config/output/manifest.md) 配置被启用时才能访问。

- **类型：** `Record<string, unknown> | ManifestData | undefined`
- **示例：**

```js
api.onAfterBuild(({ environments }) => {
  // Get the manifest data of web environment
  console.log(environments.web.manifest);
});

api.onAfterDevCompile(({ environments }) => {
  console.log(environments.web.manifest);
});

api.onAfterEnvironmentCompile(({ environment }) => {
  console.log(environment.manifest);
});
```

manifest 数据仅在构建完成后才能被访问，你可以在以下 hooks 中访问：

- [onAfterBuild](/zh/plugins/dev/hooks.md#onafterbuild)
- [onAfterEnvironmentCompile](/zh/plugins/dev/hooks.md#onafterenvironmentcompile)
- [onCloseBuild](/zh/plugins/dev/hooks.md#onclosebuild)
- [onCloseDevServer](/zh/plugins/dev/hooks.md#onclosedevserver)
- [onAfterDevCompile](/zh/plugins/dev/hooks.md#onafterdevcompile)
- [onExit](/zh/plugins/dev/hooks.md#onexit)

### webSocketToken

WebSocket 认证 token，用于认证 WebSocket 连接，防止未授权访问。

当 Rsbuild 执行 `dev` action 时，该字段包含一个 token；执行其他 action 时为空字符串。

- **类型：** `string`
- **版本：** 添加于 v1.4.4

当你需要在浏览器中建立与 Rsbuild dev server 的 WebSocket 连接时，需要使用这个 token 作为 query 参数。

```js
const { webSocketToken } = environments.web.context;

const webSocketUrl = `ws://localhost:${port}${pathname}?token=${webSocketToken}`;
```

## Environment API

Environment API 提供一些与多环境构建相关的 API。

你可以通过 [rsbuild.createDevServer()](/zh/api/javascript-api/instance.md#rsbuildcreatedevserver) 或 [server.setup](/zh/config/server/setup.md) 使用 environment API，这允许你在服务端获取特定环境下的构建产物信息。

```ts
type EnvironmentAPI = {
  [name: string]: {
    context: EnvironmentContext;
    getStats: () => Promise<Stats>;
    loadBundle: <T = unknown>(entryName: string) => Promise<T>;
    getTransformedHtml: (entryName: string) => Promise<string>;
    hot: {
      send: HotSend;
      onConnect: HotOnConnect;
    };
  };
};
```

### context

你可以通过 Environment API 获取和当前环境有关的上下文信息。

- **类型：** [EnvironmentContext](#environment-context)
- **示例：**

```ts
const webManifest = environments.web.context.manifest;

console.log(webManifest.entries);
```

### getStats

获取当前环境的产物信息。

- **类型：**

```ts
type GetStats = () => Promise<Stats>;
```

- **示例：**

```ts
const webStats = await environments.web.getStats();

console.log(webStats.toJson({ all: false }));
```

### loadBundle

用于在服务端加载并执行构建产物。调用该方法后，会返回指定入口模块导出的内容，通常用于在服务端环境中运行由 Rsbuild 构建生成的产物。

`loadBundle` 会在构建完成且 [onAfterDevCompile](/zh/plugins/dev/hooks.md#onafterdevcompile) hook 执行结束后返回结果。因此，无法在 `onAfterDevCompile` hook 内调用 `loadBundle`。

- **类型：**

```ts
/**
 * @param entryName - 入口名称，和 Rsbuild `source.entry` 的某一个 key 值对应
 * @returns 入口模块的返回值
 */
type LoadBundle = <T = unknown>(entryName: string) => Promise<T>;
```

- **示例：**

```ts
// 加载 `main` 入口的 bundle
const result = await environments.node.loadBundle('main');
```

### getTransformedHtml

获取经过编译和转换后的 HTML 模版内容。

- **类型：**

```ts
type GetTransformedHtml = (entryName: string) => Promise<string>;
```

- **示例：**

```ts
// 获取 main 入口的 HTML 内容
const html = await environments.web.getTransformedHtml('main');
```

该方法会返回完整的 HTML 字符串，包含了所有通过 HTML 插件注入的资源和内容。

### hot.send

向当前 environment 对应的客户端发送 HMR 消息。

它和 [server.sockWrite](/zh/api/javascript-api/server-api.md#sockwrite) 的行为一致，区别是只会影响当前匹配的 environment。

- **类型：**

```ts
type HotSend = {
  (type: 'full-reload', data?: { path?: string }): void;
  (type: 'static-changed'): void;
  (type: 'custom', data: { event: string; data?: any }): void;
};
```

#### full-reload

如果你发送一个 `'full-reload'` 的消息，页面将会重新加载。

```ts
if (someCondition) {
  environments.web.hot.send('full-reload');
}
```

当传入 `path` 且它以 `.html` 结尾时，Rsbuild 只会重新加载当前 environment 中 URL 与该 HTML 路径匹配的页面。

当 `path` 为 `'*'` 时，Rsbuild 会重新加载当前 environment 中的所有页面。

HTML 路径应当相对于 dev server 根路径，并且不应包含 `server.base`。

```ts
environments.web.hot.send('full-reload', {
  path: '/foo.html',
});
```

> `'static-changed'` 是 `'full-reload'` 的一个别名。

#### custom

你也可以通过 `custom` 类型向浏览器发送自定义消息，并携带可选的 data，然后通过 HMR 事件进行处理：

```ts
environments.web.hot.send('custom', {
  event: 'count',
  data: { value: 1 },
});
```

Rsbuild 在 Rspack 的 [import.meta.webpackHot](https://rspack.rs/zh/api/runtime-api/hmr) 对象上扩展了 `on()` 方法，它允许你在浏览器端监听自定义事件，并处理数据：

```ts title="client.js"
if (import.meta.webpackHot) {
  import.meta.webpackHot.on('count', (data) => {
    console.log('count update', data.value);
  });
  import.meta.webpackHot.accept();
}
```

### hot.onConnect

注册一个回调，在 HMR 客户端连接或重新连接到当前 environment 时调用。

- **版本：** `>= v2.2.8`
- **类型：**

```ts
type HotClient = {
  send: HotSend;
};

type HotOnConnect = (
  callback: (client: HotClient) => void | Promise<void>,
) => () => void;
```

请在客户端连接前注册回调，例如在 `server.setup` 中，或在调用 `server.listen()` 之前。已连接的客户端不会触发该回调。

回调接收一个 `client` 对象。使用 `client.send` 可以单独向该客户端发送消息，参数与 `hot.send` 相同。

例如，你可以在每个客户端连接时，向其发送一条欢迎消息：

```ts
const unsubscribe = server.environments.web.hot.onConnect((client) => {
  client.send('custom', {
    event: 'welcome',
    data: { message: 'Hello!' },
  });
});
```

不再需要监听客户端连接时，调用返回的 `unsubscribe` 函数即可取消订阅。

:::note
回调执行时，浏览器端应用可能仍在初始化。请尽早在浏览器端注册自定义事件监听器，并根据需要缓存消息。Rsbuild 不会保存或重放自定义消息。
:::
